Events Manager - Version 5.0b3

Version Description

For those upgrading from version 3 to 4, you must upgrade to version 3.0.98 manually and then to the latest version as usual. Please see this screencast for a walkthrough.

Download this release

Release Info

Developer netweblogic
Plugin Icon 128x128 Events Manager
Version 5.0b3
Comparing to
See all releases

Code changes from version 3.0.98 to 5.0b3

Files changed (87) hide show
  1. admin/bookings/em-cancelled.php +28 -24
  2. admin/bookings/em-confirmed.php +32 -28
  3. admin/bookings/em-events.php +10 -10
  4. admin/bookings/em-pending.php +40 -36
  5. admin/bookings/em-person.php +25 -23
  6. admin/bookings/em-rejected.php +29 -25
  7. admin/em-admin.php +184 -213
  8. admin/em-bookings.php +235 -101
  9. admin/em-categories.php +0 -177
  10. admin/em-docs.php +152 -88
  11. admin/em-event.php +0 -627
  12. admin/em-events.php +0 -242
  13. admin/em-help.php +25 -8
  14. admin/em-locations-search.php +7 -3
  15. admin/em-locations.php +0 -268
  16. admin/em-ms-locations.php +55 -0
  17. admin/em-ms-options.php +213 -0
  18. admin/em-options.php +1197 -297
  19. admin/em-people.php +0 -192
  20. buddypress/bp-em-activity.php +126 -0
  21. buddypress/bp-em-core.php +240 -0
  22. buddypress/bp-em-groups.php +57 -0
  23. buddypress/bp-em-notifications.php +82 -0
  24. buddypress/bp-em-templatetags.php +21 -0
  25. buddypress/screens/attending.php +29 -0
  26. buddypress/screens/group-events.php +30 -0
  27. buddypress/screens/my-bookings.php +35 -0
  28. buddypress/screens/my-events.php +67 -0
  29. buddypress/screens/my-group-events.php +27 -0
  30. buddypress/screens/my-locations.php +69 -0
  31. buddypress/screens/profile.php +32 -0
  32. classes/em-booking.php +355 -104
  33. classes/em-bookings.php +260 -162
  34. classes/em-calendar.php +101 -126
  35. classes/em-categories-taxonomy.php +87 -0
  36. classes/em-categories.php +259 -107
  37. classes/em-category-taxonomy.php +57 -0
  38. classes/em-category.php +136 -95
  39. classes/em-event-post-admin.php +372 -0
  40. classes/em-event-post.php +250 -0
  41. classes/em-event-posts-admin.php +243 -0
  42. classes/em-event.php +1311 -607
  43. classes/em-events.php +180 -70
  44. classes/em-location-post-admin.php +123 -0
  45. classes/em-location-post.php +67 -0
  46. classes/em-location-posts-admin.php +68 -0
  47. classes/em-location.php +484 -189
  48. classes/em-locations.php +139 -58
  49. classes/em-mailer.php +4 -1
  50. classes/em-map.php +0 -60
  51. classes/em-notices.php +196 -0
  52. classes/em-object.php +401 -41
  53. classes/em-people.php +19 -114
  54. classes/em-permalinks.php +191 -0
  55. classes/em-person.php +67 -130
  56. classes/em-recurrence.php +0 -89
  57. classes/em-ticket-booking.php +222 -0
  58. classes/em-ticket.php +338 -0
  59. classes/em-tickets-bookings.php +283 -0
  60. classes/em-tickets.php +241 -0
  61. classes/phpmailer/class.phpmailer.php +2393 -1426
  62. classes/phpmailer/class.smtp.php +721 -949
  63. classes/phpmailer/language/phpmailer.lang-ar.php +27 -0
  64. classes/phpmailer/language/phpmailer.lang-br.php +23 -18
  65. classes/phpmailer/language/phpmailer.lang-ca.php +22 -18
  66. classes/phpmailer/language/phpmailer.lang-ch.php +26 -0
  67. classes/phpmailer/language/phpmailer.lang-cz.php +21 -20
  68. classes/phpmailer/language/phpmailer.lang-de.php +22 -20
  69. classes/phpmailer/language/phpmailer.lang-dk.php +22 -20
  70. classes/phpmailer/language/phpmailer.lang-es.php +22 -19
  71. classes/phpmailer/language/phpmailer.lang-et.php +26 -0
  72. classes/phpmailer/language/phpmailer.lang-fi.php +23 -19
  73. classes/phpmailer/language/phpmailer.lang-fo.php +27 -25
  74. classes/phpmailer/language/phpmailer.lang-fr.php +22 -21
  75. classes/phpmailer/language/phpmailer.lang-hu.php +21 -19
  76. classes/phpmailer/language/phpmailer.lang-it.php +20 -21
  77. classes/phpmailer/language/phpmailer.lang-ja.php +22 -21
  78. classes/phpmailer/language/phpmailer.lang-nl.php +21 -19
  79. classes/phpmailer/language/phpmailer.lang-no.php +22 -20
  80. classes/phpmailer/language/phpmailer.lang-pl.php +21 -20
  81. classes/phpmailer/language/phpmailer.lang-ro.php +24 -20
  82. classes/phpmailer/language/phpmailer.lang-ru.php +25 -23
  83. classes/phpmailer/language/phpmailer.lang-se.php +22 -20
  84. classes/phpmailer/language/phpmailer.lang-tr.php +23 -21
  85. classes/phpmailer/language/phpmailer.lang-zh.php +26 -0
  86. classes/phpmailer/language/phpmailer.lang-zh_cn.php +26 -0
  87. em-actions.php +240 -0
admin/bookings/em-cancelled.php CHANGED
@@ -5,7 +5,7 @@
5
  * @param int $event_id
6
  */
7
  function em_bookings_cancelled_table(){
8
- global $EM_Event, $wpdb, $current_user;
9
 
10
  $action_scope = ( !empty($_REQUEST['em_obj']) && $_REQUEST['em_obj'] == 'em_bookings_cancelled_table' );
11
  $action = ( $action_scope && !empty($_GET ['action']) ) ? $_GET ['action']:'';
@@ -14,12 +14,16 @@ function em_bookings_cancelled_table(){
14
  $page = ( $action_scope && !empty($_GET['pno']) ) ? $_GET['pno']:1;
15
  $offset = ( $action_scope && $page > 1 ) ? ($page-1)*$limit : 0;
16
 
17
- if( is_object($EM_Event) ){
18
- $bookings = $EM_Event->get_bookings()->get_cancelled_bookings();
19
  }else{
20
- return false;
 
 
 
 
21
  }
22
- $bookings_count = (is_array($bookings)) ? count($bookings):0;
23
  ?>
24
  <div class='wrap em_bookings_pending_table em_obj'>
25
  <form id='bookings-filter' method='get' action='<?php bloginfo('wpurl') ?>/wp-admin/edit.php'>
@@ -31,9 +35,9 @@ function em_bookings_cancelled_table(){
31
  </li>
32
  </ul>
33
  <p class="search-box">
34
- <label class="screen-reader-text" for="post-search-input"><?php _e('Search'); ?>:</label>
35
  <input type="text" id="post-search-input" name="em_search" value="<?php echo (!empty($_GET['em_search'])) ? $_GET['em_search']:''; ?>" />
36
- <input type="submit" value="<?php _e('Search'); ?>" class="button" />
37
  </p>
38
  -->
39
  <?php if ( $bookings_count >= $limit ) : ?>
@@ -42,7 +46,7 @@ function em_bookings_cancelled_table(){
42
  <div class="alignleft actions">
43
  <select name="action">
44
  <option value="-1" selected="selected">
45
- <?php _e('Bulk Actions'); ?>
46
  </option>
47
  <option value="approve">
48
  <?php _e('Approve', 'dbem'); ?>
@@ -61,8 +65,7 @@ function em_bookings_cancelled_table(){
61
  -->
62
  <?php
63
  if ( $bookings_count >= $limit ) {
64
- $page_link_template = em_add_get_params($_SERVER['REQUEST_URI'], array('pno'=>'%PAGE%', 'em_ajax'=>0, 'em_obj'=>'em_bookings_confirmed_table'));
65
- $bookings_nav = em_admin_paginate( $page_link_template, $bookings_count, $limit, $page, 5);
66
  echo $bookings_nav;
67
  }
68
  ?>
@@ -72,16 +75,16 @@ function em_bookings_cancelled_table(){
72
  <div class="clear"></div>
73
  <?php if( $bookings_count > 0 ): ?>
74
  <div class='table-wrap'>
75
- <table id='dbem-bookings-table' class='widefat post fixed'>
76
  <thead>
77
  <tr>
78
  <th class='manage-column column-cb check-column' scope='col'>
79
  <input class='select-all' type="checkbox" value='1' />
80
  </th>
81
- <th class='manage-column' scope='col'>Booker</th>
82
- <th class='manage-column' scope='col'>E-mail</th>
83
- <th class='manage-column' scope='col'>Phone number</th>
84
- <th class='manage-column' scope='col'>Spaces</th>
85
  <th class='manage-column' scope='col'>&nbsp;</th>
86
  </tr>
87
  </thead>
@@ -89,23 +92,24 @@ function em_bookings_cancelled_table(){
89
  <?php
90
  $rowno = 0;
91
  $event_count = 0;
92
- foreach ($bookings as $EM_Booking) {
93
  if( ($rowno < $limit || empty($limit)) && ($event_count >= $offset || $offset === 0) ) {
94
  $rowno++;
95
  ?>
96
  <tr>
97
- <th scope="row" class="check-column" style="padding:7px 0px 7px;"><input type='checkbox' value='<?php echo $EM_Booking->id ?>' name='bookings[]'/></th>
98
- <td><a href="<?php bloginfo ( 'wpurl' )?>/wp-admin/admin.php?page=events-manager-bookings&amp;person_id=<?php echo $EM_Booking->person->id; ?>"><?php echo $EM_Booking->person->name ?></a></td>
99
- <td><?php echo $EM_Booking->person->email ?></td>
100
  <td><?php echo $EM_Booking->person->phone ?></td>
101
- <td><?php echo $EM_Booking->seats ?></td>
102
  <td>
103
  <?php
104
- $approve_url = em_add_get_params($_SERVER['REQUEST_URI'], array('action'=>'bookings_approve', 'booking_id'=>$EM_Booking->id));
105
- $delete_url = em_add_get_params($_SERVER['REQUEST_URI'], array('action'=>'bookings_delete', 'booking_id'=>$EM_Booking->id));
 
106
  ?>
107
  <a class="em-bookings-approve" href="<?php echo $approve_url ?>"><?php _e('Restore','dbem'); ?></a> |
108
- <a class="em-bookings-edit" href="<?php bloginfo ( 'wpurl' )?>/wp-admin/admin.php?page=events-manager-bookings&amp;booking_id=<?php echo $EM_Booking->id; ?>"><?php _e('Edit'); ?></a> |
109
  <a class="em-bookings-delete" href="<?php echo $delete_url ?>"><?php _e('Delete','dbem'); ?></a>
110
  </td>
111
  </tr>
@@ -121,7 +125,7 @@ function em_bookings_cancelled_table(){
121
  <?php _e('No cancelled bookings.', 'dbem'); ?>
122
  <?php endif; ?>
123
  </form>
124
- <?php if( !empty($bookings_nav) ) : ?>
125
  <div class='tablenav'>
126
  <?php echo $bookings_nav; ?>
127
  <div class="clear"></div>
5
  * @param int $event_id
6
  */
7
  function em_bookings_cancelled_table(){
8
+ global $EM_Event, $EM_Ticket, $wpdb, $current_user;
9
 
10
  $action_scope = ( !empty($_REQUEST['em_obj']) && $_REQUEST['em_obj'] == 'em_bookings_cancelled_table' );
11
  $action = ( $action_scope && !empty($_GET ['action']) ) ? $_GET ['action']:'';
14
  $page = ( $action_scope && !empty($_GET['pno']) ) ? $_GET['pno']:1;
15
  $offset = ( $action_scope && $page > 1 ) ? ($page-1)*$limit : 0;
16
 
17
+ if( is_object($EM_Ticket) ){
18
+ $EM_Bookings = $EM_Ticket->get_bookings()->get_cancelled_bookings();
19
  }else{
20
+ if( is_object($EM_Event) ){
21
+ $EM_Bookings = $EM_Event->get_bookings()->get_cancelled_bookings();
22
+ }else{
23
+ return false;
24
+ }
25
  }
26
+ $bookings_count = (is_array($EM_Bookings->bookings)) ? count($EM_Bookings->bookings):0;
27
  ?>
28
  <div class='wrap em_bookings_pending_table em_obj'>
29
  <form id='bookings-filter' method='get' action='<?php bloginfo('wpurl') ?>/wp-admin/edit.php'>
35
  </li>
36
  </ul>
37
  <p class="search-box">
38
+ <label class="screen-reader-text" for="post-search-input"><?php _e('Search', 'dbem'); ?>:</label>
39
  <input type="text" id="post-search-input" name="em_search" value="<?php echo (!empty($_GET['em_search'])) ? $_GET['em_search']:''; ?>" />
40
+ <input type="submit" value="<?php _e('Search', 'dbem'); ?>" class="button" />
41
  </p>
42
  -->
43
  <?php if ( $bookings_count >= $limit ) : ?>
46
  <div class="alignleft actions">
47
  <select name="action">
48
  <option value="-1" selected="selected">
49
+ <?php _e('Bulk Actions', 'dbem'); ?>
50
  </option>
51
  <option value="approve">
52
  <?php _e('Approve', 'dbem'); ?>
65
  -->
66
  <?php
67
  if ( $bookings_count >= $limit ) {
68
+ $bookings_nav = em_admin_paginate( $bookings_count, $limit, $page, array('em_ajax'=>0, 'em_obj'=>'em_bookings_confirmed_table'));
 
69
  echo $bookings_nav;
70
  }
71
  ?>
75
  <div class="clear"></div>
76
  <?php if( $bookings_count > 0 ): ?>
77
  <div class='table-wrap'>
78
+ <table id='dbem-bookings-table' class='widefat post '>
79
  <thead>
80
  <tr>
81
  <th class='manage-column column-cb check-column' scope='col'>
82
  <input class='select-all' type="checkbox" value='1' />
83
  </th>
84
+ <th class='manage-column' scope='col'><?php _e('Booker', 'dbem'); ?></th>
85
+ <th class='manage-column' scope='col'><?php _e('E-mail', 'dbem'); ?></th>
86
+ <th class='manage-column' scope='col'><?php _e('Phone number', 'dbem'); ?></th>
87
+ <th class='manage-column' scope='col'><?php _e('Spaces', 'dbem'); ?></th>
88
  <th class='manage-column' scope='col'>&nbsp;</th>
89
  </tr>
90
  </thead>
92
  <?php
93
  $rowno = 0;
94
  $event_count = 0;
95
+ foreach ($EM_Bookings->bookings as $EM_Booking) {
96
  if( ($rowno < $limit || empty($limit)) && ($event_count >= $offset || $offset === 0) ) {
97
  $rowno++;
98
  ?>
99
  <tr>
100
+ <th scope="row" class="check-column" style="padding:7px 0px 7px;"><input type='checkbox' value='<?php echo $EM_Booking->booking_id ?>' name='bookings[]'/></th>
101
+ <td><a href="<?php echo EM_ADMIN_URL; ?>&amp;page=events-manager-bookings&amp;person_id=<?php echo $EM_Booking->person->ID; ?>"><?php echo $EM_Booking->person->get_name() ?></a></td>
102
+ <td><?php echo $EM_Booking->person->user_email ?></td>
103
  <td><?php echo $EM_Booking->person->phone ?></td>
104
+ <td><?php echo $EM_Booking->get_spaces() ?></td>
105
  <td>
106
  <?php
107
+ $approve_url = em_add_get_params($_SERVER['REQUEST_URI'], array('action'=>'bookings_approve', 'booking_id'=>$EM_Booking->booking_id));
108
+ $delete_url = em_add_get_params($_SERVER['REQUEST_URI'], array('action'=>'bookings_delete', 'booking_id'=>$EM_Booking->booking_id));
109
+ $edit_url = em_add_get_params($_SERVER['REQUEST_URI'], array('booking_id'=>$EM_Booking->booking_id, 'em_ajax'=>null, 'em_obj'=>null));
110
  ?>
111
  <a class="em-bookings-approve" href="<?php echo $approve_url ?>"><?php _e('Restore','dbem'); ?></a> |
112
+ <a class="em-bookings-edit" href="<?php echo $edit_url; ?>"><?php _e('Edit/View','dbem'); ?></a> |
113
  <a class="em-bookings-delete" href="<?php echo $delete_url ?>"><?php _e('Delete','dbem'); ?></a>
114
  </td>
115
  </tr>
125
  <?php _e('No cancelled bookings.', 'dbem'); ?>
126
  <?php endif; ?>
127
  </form>
128
+ <?php if( !empty($bookings_nav) && $EM_Bookings >= $limit ) : ?>
129
  <div class='tablenav'>
130
  <?php echo $bookings_nav; ?>
131
  <div class="clear"></div>
admin/bookings/em-confirmed.php CHANGED
@@ -6,7 +6,7 @@
6
  * @param int $event_id
7
  */
8
  function em_bookings_confirmed_table(){
9
- global $EM_Event, $wpdb, $current_user;
10
 
11
  $action_scope = ( !empty($_REQUEST['em_obj']) && $_REQUEST['em_obj'] == 'em_bookings_confirmed_table' );
12
  $action = ( $action_scope && !empty($_GET ['action']) ) ? $_GET ['action']:'';
@@ -15,12 +15,16 @@ function em_bookings_confirmed_table(){
15
  $page = ( $action_scope && !empty($_GET['pno']) ) ? $_GET['pno']:1;
16
  $offset = ( $action_scope && $page > 1 ) ? ($page-1)*$limit : 0;
17
 
18
- if( is_object($EM_Event) ){
19
- $bookings = $EM_Event->get_bookings()->get_bookings();
20
  }else{
21
- return false;
 
 
 
 
22
  }
23
- $bookings_count = (is_array($bookings)) ? count($bookings):0;
24
  ?>
25
  <div class='wrap em_bookings_pending_table em_obj'>
26
  <form id='bookings-filter' method='get' action='<?php bloginfo('wpurl') ?>/wp-admin/edit.php'>
@@ -32,9 +36,9 @@ function em_bookings_confirmed_table(){
32
  </li>
33
  </ul>
34
  <p class="search-box">
35
- <label class="screen-reader-text" for="post-search-input"><?php _e('Search'); ?>:</label>
36
  <input type="text" id="post-search-input" name="em_search" value="<?php echo (!empty($_GET['em_search'])) ? $_GET['em_search']:''; ?>" />
37
- <input type="submit" value="<?php _e('Search'); ?>" class="button" />
38
  </p>
39
  -->
40
  <?php if ( $bookings_count >= $limit ) : ?>
@@ -43,7 +47,7 @@ function em_bookings_confirmed_table(){
43
  <div class="alignleft actions">
44
  <select name="action">
45
  <option value="-1" selected="selected">
46
- <?php _e('Bulk Actions'); ?>
47
  </option>
48
  <option value="approve">
49
  <?php _e('Approve', 'dbem'); ?>
@@ -62,8 +66,7 @@ function em_bookings_confirmed_table(){
62
  -->
63
  <?php
64
  if ( $bookings_count >= $limit ) {
65
- $page_link_template = em_add_get_params($_SERVER['REQUEST_URI'], array('pno'=>'%PAGE%', 'em_ajax'=>0, 'em_obj'=>'em_bookings_confirmed_table'));
66
- $bookings_nav = em_admin_paginate( $page_link_template, $bookings_count, $limit, $page, 5);
67
  echo $bookings_nav;
68
  }
69
  ?>
@@ -73,16 +76,16 @@ function em_bookings_confirmed_table(){
73
  <div class="clear"></div>
74
  <?php if( $bookings_count > 0 ): ?>
75
  <div class='table-wrap'>
76
- <table id='dbem-bookings-table' class='widefat post fixed'>
77
  <thead>
78
  <tr>
79
  <th class='manage-column column-cb check-column' scope='col'>
80
  <input class='select-all' type="checkbox" value='1' />
81
  </th>
82
- <th class='manage-column' scope='col'>Booker</th>
83
- <th class='manage-column' scope='col'>E-mail</th>
84
- <th class='manage-column' scope='col'>Phone number</th>
85
- <th class='manage-column' scope='col'>Spaces</th>
86
  <th class='manage-column' scope='col'>&nbsp;</th>
87
  </tr>
88
  </thead>
@@ -90,29 +93,30 @@ function em_bookings_confirmed_table(){
90
  <?php
91
  $rowno = 0;
92
  $event_count = 0;
93
- foreach ($bookings as $EM_Booking) {
94
  if( ($rowno < $limit || empty($limit)) && ($event_count >= $offset || $offset === 0) ) {
95
  $rowno++;
96
  ?>
97
  <tr>
98
- <th scope="row" class="check-column" style="padding:7px 0px 7px;"><input type='checkbox' value='<?php echo $EM_Booking->id ?>' name='bookings[]'/></th>
99
- <td><a href="<?php bloginfo ( 'wpurl' )?>/wp-admin/admin.php?page=events-manager-bookings&amp;person_id=<?php echo $EM_Booking->person_id; ?>"><?php echo $EM_Booking->person->name ?></a></td>
100
- <td><?php echo $EM_Booking->person->email ?></td>
101
  <td><?php echo $EM_Booking->person->phone ?></td>
102
- <td><?php echo $EM_Booking->seats ?></td>
103
- <td>
104
  <?php
105
- $unapprove_url = em_add_get_params($_SERVER['REQUEST_URI'], array('action'=>'bookings_unapprove', 'booking_id'=>$EM_Booking->id));
106
- $reject_url = em_add_get_params($_SERVER['REQUEST_URI'], array('action'=>'bookings_reject', 'booking_id'=>$EM_Booking->id));
107
- $delete_url = em_add_get_params($_SERVER['REQUEST_URI'], array('action'=>'bookings_delete', 'booking_id'=>$EM_Booking->id));
 
108
  ?>
109
- <?php if( get_option('dbem_bookings_approval') ): ?>
110
  <a class="em-bookings-unapprove" href="<?php echo $unapprove_url ?>"><?php _e('Unapprove','dbem'); ?></a> |
111
  <?php else: ?>
112
  <a class="em-bookings-reject" href="<?php echo $reject_url ?>"><?php _e('Reject','dbem'); ?></a> |
113
  <?php endif; ?>
114
- <a class="em-bookings-delete" href="<?php echo $delete_url ?>"><?php _e('Delete','dbem'); ?></a> |
115
- <a class="em-bookings-edit" href="<?php bloginfo ( 'wpurl' )?>/wp-admin/admin.php?page=events-manager-bookings&amp;booking_id=<?php echo $EM_Booking->id; ?>"><?php _e('Edit'); ?></a>
116
  </td>
117
  </tr>
118
  <?php
@@ -127,7 +131,7 @@ function em_bookings_confirmed_table(){
127
  <?php _e('No confirmed bookings.', 'dbem'); ?>
128
  <?php endif; ?>
129
  </form>
130
- <?php if( !empty($bookings_nav) ) : ?>
131
  <div class='tablenav'>
132
  <?php echo $bookings_nav; ?>
133
  <div class="clear"></div>
6
  * @param int $event_id
7
  */
8
  function em_bookings_confirmed_table(){
9
+ global $EM_Event, $EM_Ticket, $wpdb, $current_user;
10
 
11
  $action_scope = ( !empty($_REQUEST['em_obj']) && $_REQUEST['em_obj'] == 'em_bookings_confirmed_table' );
12
  $action = ( $action_scope && !empty($_GET ['action']) ) ? $_GET ['action']:'';
15
  $page = ( $action_scope && !empty($_GET['pno']) ) ? $_GET['pno']:1;
16
  $offset = ( $action_scope && $page > 1 ) ? ($page-1)*$limit : 0;
17
 
18
+ if( is_object($EM_Ticket) ){
19
+ $EM_Bookings = $EM_Ticket->get_bookings()->get_bookings();
20
  }else{
21
+ if( is_object($EM_Event) ){
22
+ $EM_Bookings = $EM_Event->get_bookings()->get_bookings();
23
+ }else{
24
+ return false;
25
+ }
26
  }
27
+ $bookings_count = (is_array($EM_Bookings->bookings)) ? count($EM_Bookings->bookings):0;
28
  ?>
29
  <div class='wrap em_bookings_pending_table em_obj'>
30
  <form id='bookings-filter' method='get' action='<?php bloginfo('wpurl') ?>/wp-admin/edit.php'>
36
  </li>
37
  </ul>
38
  <p class="search-box">
39
+ <label class="screen-reader-text" for="post-search-input"><?php _e('Search', 'dbem'); ?>:</label>
40
  <input type="text" id="post-search-input" name="em_search" value="<?php echo (!empty($_GET['em_search'])) ? $_GET['em_search']:''; ?>" />
41
+ <input type="submit" value="<?php _e('Search', 'dbem'); ?>" class="button" />
42
  </p>
43
  -->
44
  <?php if ( $bookings_count >= $limit ) : ?>
47
  <div class="alignleft actions">
48
  <select name="action">
49
  <option value="-1" selected="selected">
50
+ <?php _e('Bulk Actions', 'dbem'); ?>
51
  </option>
52
  <option value="approve">
53
  <?php _e('Approve', 'dbem'); ?>
66
  -->
67
  <?php
68
  if ( $bookings_count >= $limit ) {
69
+ $bookings_nav = em_admin_paginate($bookings_count, $limit, $page, array('em_ajax'=>0, 'em_obj'=>'em_bookings_confirmed_table'));
 
70
  echo $bookings_nav;
71
  }
72
  ?>
76
  <div class="clear"></div>
77
  <?php if( $bookings_count > 0 ): ?>
78
  <div class='table-wrap'>
79
+ <table id='dbem-bookings-table' class='widefat post '>
80
  <thead>
81
  <tr>
82
  <th class='manage-column column-cb check-column' scope='col'>
83
  <input class='select-all' type="checkbox" value='1' />
84
  </th>
85
+ <th class='manage-column' scope='col'><?php _e('Booker', 'dbem'); ?></th>
86
+ <th class='manage-column' scope='col'><?php _e('E-mail', 'dbem'); ?></th>
87
+ <th class='manage-column' scope='col'><?php _e('Phone number', 'dbem'); ?></th>
88
+ <th class='manage-column' scope='col'><?php _e('Spaces', 'dbem'); ?></th>
89
  <th class='manage-column' scope='col'>&nbsp;</th>
90
  </tr>
91
  </thead>
93
  <?php
94
  $rowno = 0;
95
  $event_count = 0;
96
+ foreach ($EM_Bookings->bookings as $EM_Booking) {
97
  if( ($rowno < $limit || empty($limit)) && ($event_count >= $offset || $offset === 0) ) {
98
  $rowno++;
99
  ?>
100
  <tr>
101
+ <th scope="row" class="check-column" style="padding:7px 0px 7px;"><input type='checkbox' value='<?php echo $EM_Booking->booking_id ?>' name='bookings[]'/></th>
102
+ <td><a href="<?php echo EM_ADMIN_URL; ?>&amp;page=events-manager-bookings&amp;person_id=<?php echo $EM_Booking->person_id; ?>"><?php echo $EM_Booking->person->get_name() ?></a></td>
103
+ <td><?php echo $EM_Booking->person->user_email ?></td>
104
  <td><?php echo $EM_Booking->person->phone ?></td>
105
+ <td><?php echo $EM_Booking->get_spaces() ?></td>
106
+ <td>
107
  <?php
108
+ $unapprove_url = em_add_get_params($_SERVER['REQUEST_URI'], array('action'=>'bookings_unapprove', 'booking_id'=>$EM_Booking->booking_id));
109
+ $reject_url = em_add_get_params($_SERVER['REQUEST_URI'], array('action'=>'bookings_reject', 'booking_id'=>$EM_Booking->booking_id));
110
+ $delete_url = em_add_get_params($_SERVER['REQUEST_URI'], array('action'=>'bookings_delete', 'booking_id'=>$EM_Booking->booking_id));
111
+ $edit_url = em_add_get_params($_SERVER['REQUEST_URI'], array('booking_id'=>$EM_Booking->booking_id, 'em_ajax'=>null, 'em_obj'=>null));
112
  ?>
113
+ <?php if( current_user_can('manage_bookings') && get_option('dbem_bookings_approval') ): ?>
114
  <a class="em-bookings-unapprove" href="<?php echo $unapprove_url ?>"><?php _e('Unapprove','dbem'); ?></a> |
115
  <?php else: ?>
116
  <a class="em-bookings-reject" href="<?php echo $reject_url ?>"><?php _e('Reject','dbem'); ?></a> |
117
  <?php endif; ?>
118
+ <span class="trash"><a class="em-bookings-delete" href="<?php echo $delete_url ?>"><?php _e('Delete','dbem'); ?></a></span> |
119
+ <a class="em-bookings-edit" href="<?php echo $edit_url; ?>"><?php _e('Edit/View','dbem'); ?></a>
120
  </td>
121
  </tr>
122
  <?php
131
  <?php _e('No confirmed bookings.', 'dbem'); ?>
132
  <?php endif; ?>
133
  </form>
134
+ <?php if( !empty($bookings_nav) && $EM_Bookings >= $limit ) : ?>
135
  <div class='tablenav'>
136
  <?php echo $bookings_nav; ?>
137
  <div class="clear"></div>
admin/bookings/em-events.php CHANGED
@@ -35,13 +35,14 @@ function em_bookings_events_table() {
35
  $title = __ ( 'Future Events', 'dbem' );
36
  $scope = "future";
37
  }
38
- $events = EM_Events::get( array('scope'=>$scope, 'limit'=>0, 'order'=>$order, 'rsvp'=>true ) );
 
39
  $events_count = count ( $events );
40
 
41
  $use_events_end = get_option ( 'dbem_use_event_end' );
42
  ?>
43
  <div class="wrap em_bookings_events_table em_obj">
44
- <form id="posts-filter" action="<?php echo $_SERVER['REQUEST_URI'] ?>" method="get">
45
  <input type="hidden" name="em_obj" value="em_bookings_events_table" />
46
  <?php if(!empty($_GET['page'])): ?>
47
  <input type='hidden' name='page' value='events-manager-bookings' />
@@ -77,8 +78,7 @@ function em_bookings_events_table() {
77
  -->
78
  <?php
79
  if ( $events_count >= $limit ) {
80
- $page_link_template = em_add_get_params($_SERVER['REQUEST_URI'], array('pno'=>'%PAGE%', 'em_ajax'=>0, 'em_obj'=>'em_bookings_events_table'));
81
- $events_nav = em_admin_paginate( $page_link_template, $events_count, $limit, $page, 5);
82
  echo $events_nav;
83
  }
84
  ?>
@@ -112,8 +112,8 @@ function em_bookings_events_table() {
112
  $rowno++;
113
  $class = ($rowno % 2) ? ' class="alternate"' : '';
114
  // FIXME set to american
115
- $localised_start_date = date_i18n('D d M Y', $event->start);
116
- $localised_end_date = date_i18n('D d M Y', $event->end);
117
  $style = "";
118
  $today = date ( "Y-m-d" );
119
 
@@ -128,12 +128,12 @@ function em_bookings_events_table() {
128
  </td>
129
  <td>
130
  <strong>
131
- <a class="row-title" href="<?php bloginfo ( 'wpurl' )?>/wp-admin/admin.php?page=events-manager-bookings&amp;event_id=<?php echo $event->id ?>"><?php echo ($event->name); ?></a>
132
  </strong>
133
  &ndash;
134
- <?php _e("Booked Seats",'dbem') ?>: <?php echo $event->get_bookings()->get_booked_seats()."/".$event->seats ?>
135
  <?php if( get_option('dbem_bookings_approval') == 1 ) : ?>
136
- | <?php _e("Pending",'dbem') ?>: <?php echo $event->get_bookings()->get_pending_seats(); ?>
137
  <?php endif; ?>
138
  </td>
139
 
@@ -162,7 +162,7 @@ function em_bookings_events_table() {
162
  <div class="alignleft actions">
163
  <br class='clear' />
164
  </div>
165
- <?php if( !empty($events_nav) ) : ?>
166
  <div class="tablenav-pages">
167
  <?php
168
  echo $events_nav;
35
  $title = __ ( 'Future Events', 'dbem' );
36
  $scope = "future";
37
  }
38
+ $owner = !current_user_can('edit_others_events') ? get_current_user_id() : false;
39
+ $events = EM_Events::get( array('scope'=>$scope, 'limit'=>0, 'order'=>$order, 'bookings'=>true, 'owner' => $owner ) );
40
  $events_count = count ( $events );
41
 
42
  $use_events_end = get_option ( 'dbem_use_event_end' );
43
  ?>
44
  <div class="wrap em_bookings_events_table em_obj">
45
+ <form id="posts-filter" action="" method="get">
46
  <input type="hidden" name="em_obj" value="em_bookings_events_table" />
47
  <?php if(!empty($_GET['page'])): ?>
48
  <input type='hidden' name='page' value='events-manager-bookings' />
78
  -->
79
  <?php
80
  if ( $events_count >= $limit ) {
81
+ $events_nav = em_admin_paginate( $events_count, $limit, $page, array('em_ajax'=>0, 'em_obj'=>'em_bookings_events_table'));
 
82
  echo $events_nav;
83
  }
84
  ?>
112
  $rowno++;
113
  $class = ($rowno % 2) ? ' class="alternate"' : '';
114
  // FIXME set to american
115
+ $localised_start_date = date_i18n(get_option('date_format'), $event->start);
116
+ $localised_end_date = date_i18n(get_option('date_format'), $event->end);
117
  $style = "";
118
  $today = date ( "Y-m-d" );
119
 
128
  </td>
129
  <td>
130
  <strong>
131
+ <?php echo $event->output('#_BOOKINGSLINK'); ?>
132
  </strong>
133
  &ndash;
134
+ <?php _e("Booked Spaces",'dbem') ?>: <?php echo $event->get_bookings()->get_booked_spaces()."/".$event->get_spaces() ?>
135
  <?php if( get_option('dbem_bookings_approval') == 1 ) : ?>
136
+ | <?php _e("Pending",'dbem') ?>: <?php echo $event->get_bookings()->get_pending_spaces(); ?>
137
  <?php endif; ?>
138
  </td>
139
 
162
  <div class="alignleft actions">
163
  <br class='clear' />
164
  </div>
165
+ <?php if (!empty($events_nav) && $events_count >= $limit ) : ?>
166
  <div class="tablenav-pages">
167
  <?php
168
  echo $events_nav;
admin/bookings/em-pending.php CHANGED
@@ -7,7 +7,7 @@
7
  * @param int $event_id
8
  */
9
  function em_bookings_pending_table($event_id = false){
10
- global $EM_Event, $wpdb, $current_user;
11
 
12
  if( get_option('dbem_bookings_approval') == 0 ){
13
  return false;
@@ -20,21 +20,25 @@ function em_bookings_pending_table($event_id = false){
20
  $page = ( $action_scope && !empty($_GET['pno']) ) ? $_GET['pno']:1;
21
  $offset = ( $action_scope && $page > 1 ) ? ($page-1)*$limit : 0;
22
 
23
- if( is_object($EM_Event) ){
24
- $bookings = $EM_Event->get_bookings()->get_pending();
25
  }else{
26
- //To optimize performance, we can do one query here for all pending bookings to show.
27
- $bookings = EM_Bookings::get(array('status'=>0));
28
- $events = array();
29
- //Now let's create events and bookings for this:
30
- foreach($bookings as $EM_Booking){
31
- //create event
32
- if( !array_key_exists($EM_Booking->event_id,$events) ){
33
- $events[$EM_Booking->event_id] = new EM_Event($EM_Booking->event_id);
 
 
 
 
34
  }
35
  }
36
  }
37
- $bookings_count = (is_array($bookings)) ? count($bookings):0;
38
  ?>
39
  <div class='wrap em_bookings_pending_table em_obj'>
40
  <form id='bookings-filter' method='get' action='<?php bloginfo('wpurl') ?>/wp-admin/edit.php'>
@@ -46,9 +50,9 @@ function em_bookings_pending_table($event_id = false){
46
  </li>
47
  </ul>
48
  <p class="search-box">
49
- <label class="screen-reader-text" for="post-search-input"><?php _e('Search'); ?>:</label>
50
  <input type="text" id="post-search-input" name="em_search" value="<?php echo (!empty($_GET['em_search'])) ? $_GET['em_search']:''; ?>" />
51
- <input type="submit" value="<?php _e('Search'); ?>" class="button" />
52
  </p>
53
  -->
54
  <?php if ( $bookings_count >= $limit ) : ?>
@@ -57,7 +61,7 @@ function em_bookings_pending_table($event_id = false){
57
  <div class="alignleft actions">
58
  <select name="action">
59
  <option value="-1" selected="selected">
60
- <?php _e('Bulk Actions'); ?>
61
  </option>
62
  <option value="approve">
63
  <?php _e('Approve', 'dbem'); ?>
@@ -76,8 +80,7 @@ function em_bookings_pending_table($event_id = false){
76
  -->
77
  <?php
78
  if ( $bookings_count >= $limit ) {
79
- $page_link_template = em_add_get_params($_SERVER['REQUEST_URI'], array('pno'=>'%PAGE%', 'em_ajax'=>0, 'em_obj'=>'em_bookings_pending_table'));
80
- $bookings_nav = em_admin_paginate( $page_link_template, $bookings_count, $limit, $page, 5);
81
  echo $bookings_nav;
82
  }
83
  ?>
@@ -87,19 +90,19 @@ function em_bookings_pending_table($event_id = false){
87
  <div class="clear"></div>
88
  <?php if( $bookings_count > 0 ): ?>
89
  <div class='table-wrap'>
90
- <table id='dbem-bookings-table' class='widefat post fixed'>
91
  <thead>
92
  <tr>
93
  <th class='manage-column column-cb check-column' scope='col'>
94
  <input class='select-all' type="checkbox" value='1' />
95
  </th>
96
- <th class='manage-column' scope='col'>Booker</th>
97
- <?php if( !is_object($EM_Event) ): ?>
98
- <th class='manage-column' scope="col">Event</th>
99
  <?php endif; ?>
100
- <th class='manage-column' scope='col'>E-mail</th>
101
- <th class='manage-column' scope='col'>Phone number</th>
102
- <th class='manage-column' scope='col'>Spaces</th>
103
  <th class='manage-column' scope='col'>&nbsp;</th>
104
  </tr>
105
  </thead>
@@ -107,27 +110,29 @@ function em_bookings_pending_table($event_id = false){
107
  <?php
108
  $rowno = 0;
109
  $event_count = 0;
110
- foreach ($bookings as $EM_Booking) {
111
  if( ($rowno < $limit || empty($limit)) && ($event_count >= $offset || $offset === 0) ) {
112
  $rowno++;
113
  ?>
114
  <tr>
115
- <th scope="row" class="check-column" style="padding:7px 0px 7px;"><input type='checkbox' value='<?php echo $EM_Booking->id ?>' name='bookings[]'/></th>
116
- <td><a href="<?php bloginfo ( 'wpurl' )?>/wp-admin/admin.php?page=events-manager-bookings&amp;person_id=<?php echo $EM_Booking->person->id; ?>"><?php echo $EM_Booking->person->name ?></a></td>
117
- <?php if( !is_object($EM_Event) ): ?>
118
- <td><a href="<?php bloginfo ( 'wpurl' )?>/wp-admin/admin.php?page=events-manager-bookings&amp;event_id=<?php echo $EM_Booking->event_id; ?>"><?php echo $events[$EM_Booking->event_id]->name ?></a></td>
119
  <?php endif; ?>
120
- <td><?php echo $EM_Booking->person->email ?></td>
121
  <td><?php echo $EM_Booking->person->phone ?></td>
122
- <td><?php echo $EM_Booking->seats ?></td>
123
  <td>
124
  <?php
125
- $approve_url = em_add_get_params($_SERVER['REQUEST_URI'], array('action'=>'bookings_approve', 'booking_id'=>$EM_Booking->id));
126
- $reject_url = em_add_get_params($_SERVER['REQUEST_URI'], array('action'=>'bookings_reject', 'booking_id'=>$EM_Booking->id));
 
127
  ?>
128
  <a class="em-bookings-approve" href="<?php echo $approve_url ?>"><?php _e('Approve','dbem'); ?></a> |
129
  <a class="em-bookings-reject" href="<?php echo $reject_url ?>"><?php _e('Reject','dbem'); ?></a> |
130
- <a class="em-bookings-edit" href="<?php bloginfo ( 'wpurl' )?>/wp-admin/admin.php?page=events-manager-bookings&amp;booking_id=<?php echo $EM_Booking->id; ?>"><?php _e('Edit'); ?></a>
 
131
  </td>
132
  </tr>
133
  <?php
@@ -142,7 +147,7 @@ function em_bookings_pending_table($event_id = false){
142
  <?php _e('No pending bookings.', 'dbem'); ?>
143
  <?php endif; ?>
144
  </form>
145
- <?php if( !empty($bookings_nav) ) : ?>
146
  <div class='tablenav'>
147
  <?php echo $bookings_nav; ?>
148
  <div class="clear"></div>
@@ -150,6 +155,5 @@ function em_bookings_pending_table($event_id = false){
150
  <?php endif; ?>
151
  </div>
152
  <?php
153
-
154
  }
155
  ?>
7
  * @param int $event_id
8
  */
9
  function em_bookings_pending_table($event_id = false){
10
+ global $EM_Event, $EM_Ticket, $wpdb, $current_user;
11
 
12
  if( get_option('dbem_bookings_approval') == 0 ){
13
  return false;
20
  $page = ( $action_scope && !empty($_GET['pno']) ) ? $_GET['pno']:1;
21
  $offset = ( $action_scope && $page > 1 ) ? ($page-1)*$limit : 0;
22
 
23
+ if( is_object($EM_Ticket) ){
24
+ $EM_Bookings = $EM_Ticket->get_bookings()->get_pending_bookings();
25
  }else{
26
+ if( is_object($EM_Event) ){
27
+ $EM_Bookings = $EM_Event->get_bookings()->get_pending_bookings();
28
+ }else{
29
+ //To optimize performance, we can do one query here for all pending bookings to show.
30
+ $EM_Bookings = EM_Bookings::get(array('status'=>0));
31
+ $events = array();
32
+ //Now let's create events and bookings for this:
33
+ foreach($EM_Bookings->bookings as $EM_Booking){
34
+ //create event
35
+ if( !array_key_exists($EM_Booking->event_id,$events) ){
36
+ $events[$EM_Booking->event_id] = new EM_Event($EM_Booking->event_id);
37
+ }
38
  }
39
  }
40
  }
41
+ $bookings_count = (is_array($EM_Bookings->bookings)) ? count($EM_Bookings->bookings):0;
42
  ?>
43
  <div class='wrap em_bookings_pending_table em_obj'>
44
  <form id='bookings-filter' method='get' action='<?php bloginfo('wpurl') ?>/wp-admin/edit.php'>
50
  </li>
51
  </ul>
52
  <p class="search-box">
53
+ <label class="screen-reader-text" for="post-search-input"><?php _e('Search', 'dbem'); ?>:</label>
54
  <input type="text" id="post-search-input" name="em_search" value="<?php echo (!empty($_GET['em_search'])) ? $_GET['em_search']:''; ?>" />
55
+ <input type="submit" value="<?php _e('Search', 'dbem'); ?>" class="button" />
56
  </p>
57
  -->
58
  <?php if ( $bookings_count >= $limit ) : ?>
61
  <div class="alignleft actions">
62
  <select name="action">
63
  <option value="-1" selected="selected">
64
+ <?php _e('Bulk Actions', 'dbem'); ?>
65
  </option>
66
  <option value="approve">
67
  <?php _e('Approve', 'dbem'); ?>
80
  -->
81
  <?php
82
  if ( $bookings_count >= $limit ) {
83
+ $bookings_nav = em_admin_paginate( $bookings_count, $limit, $page, array('em_ajax'=>0, 'em_obj'=>'em_bookings_pending_table'));
 
84
  echo $bookings_nav;
85
  }
86
  ?>
90
  <div class="clear"></div>
91
  <?php if( $bookings_count > 0 ): ?>
92
  <div class='table-wrap'>
93
+ <table id='dbem-bookings-table' class='widefat post '>
94
  <thead>
95
  <tr>
96
  <th class='manage-column column-cb check-column' scope='col'>
97
  <input class='select-all' type="checkbox" value='1' />
98
  </th>
99
+ <th class='manage-column' scope='col'><?php _e('Booker', 'dbem'); ?></th>
100
+ <?php if( !is_object($EM_Event) && !is_object($EM_Ticket) ): ?>
101
+ <th class='manage-column' scope="col"><?php _e('Event', 'dbem'); ?></th>
102
  <?php endif; ?>
103
+ <th class='manage-column' scope='col'><?php _e('E-mail', 'dbem'); ?></th>
104
+ <th class='manage-column' scope='col'><?php _e('Phone number', 'dbem'); ?></th>
105
+ <th class='manage-column' scope='col'><?php _e('Spaces', 'dbem'); ?></th>
106
  <th class='manage-column' scope='col'>&nbsp;</th>
107
  </tr>
108
  </thead>
110
  <?php
111
  $rowno = 0;
112
  $event_count = 0;
113
+ foreach ($EM_Bookings->bookings as $EM_Booking) {
114
  if( ($rowno < $limit || empty($limit)) && ($event_count >= $offset || $offset === 0) ) {
115
  $rowno++;
116
  ?>
117
  <tr>
118
+ <th scope="row" class="check-column" style="padding:7px 0px 7px;"><input type='checkbox' value='<?php echo $EM_Booking->booking_id ?>' name='bookings[]'/></th>
119
+ <td><a href="<?php echo EM_ADMIN_URL; ?>&amp;page=events-manager-bookings&amp;person_id=<?php echo $EM_Booking->person->ID; ?>"><?php echo $EM_Booking->person->get_name() ?></a></td>
120
+ <?php if( !is_object($EM_Event) && !is_object($EM_Ticket) ): ?>
121
+ <td><a href="<?php echo EM_ADMIN_URL; ?>&amp;page=events-manager-bookings&amp;event_id=<?php echo $EM_Booking->event_id; ?>"><?php echo $events[$EM_Booking->event_id]->name ?></a></td>
122
  <?php endif; ?>
123
+ <td><?php echo $EM_Booking->person->user_email ?></td>
124
  <td><?php echo $EM_Booking->person->phone ?></td>
125
+ <td><?php echo $EM_Booking->get_spaces() ?></td>
126
  <td>
127
  <?php
128
+ $approve_url = em_add_get_params($_SERVER['REQUEST_URI'], array('action'=>'bookings_approve', 'booking_id'=>$EM_Booking->booking_id));
129
+ $reject_url = em_add_get_params($_SERVER['REQUEST_URI'], array('action'=>'bookings_reject', 'booking_id'=>$EM_Booking->booking_id));
130
+ $delete_url = em_add_get_params($_SERVER['REQUEST_URI'], array('action'=>'bookings_delete', 'booking_id'=>$EM_Booking->booking_id));
131
  ?>
132
  <a class="em-bookings-approve" href="<?php echo $approve_url ?>"><?php _e('Approve','dbem'); ?></a> |
133
  <a class="em-bookings-reject" href="<?php echo $reject_url ?>"><?php _e('Reject','dbem'); ?></a> |
134
+ <span class="trash"><a class="em-bookings-delete" href="<?php echo $delete_url ?>"><?php _e('Delete','dbem'); ?></a></span> |
135
+ <a class="em-bookings-edit" href="<?php echo EM_ADMIN_URL; ?>&amp;page=events-manager-bookings&amp;booking_id=<?php echo $EM_Booking->booking_id; ?>"><?php _e('Edit/View','dbem'); ?></a>
136
  </td>
137
  </tr>
138
  <?php
147
  <?php _e('No pending bookings.', 'dbem'); ?>
148
  <?php endif; ?>
149
  </form>
150
+ <?php if( !empty($bookings_nav) && $EM_Bookings >= $limit ) : ?>
151
  <div class='tablenav'>
152
  <?php echo $bookings_nav; ?>
153
  <div class="clear"></div>
155
  <?php endif; ?>
156
  </div>
157
  <?php
 
158
  }
159
  ?>
admin/bookings/em-person.php CHANGED
@@ -18,7 +18,7 @@ function em_bookings_person_table(){
18
  $offset = ( $action_scope && $page > 1 ) ? ($page-1)*$limit : 0;
19
 
20
  $bookings = $EM_Person->get_bookings();
21
- $bookings_count = (is_array($bookings)) ? count($bookings):0;
22
  if($bookings_count > 0){
23
  //Get events here in one query to speed things up
24
  foreach($bookings as $EM_Booking){
@@ -37,9 +37,9 @@ function em_bookings_person_table(){
37
  </li>
38
  </ul>
39
  <p class="search-box">
40
- <label class="screen-reader-text" for="post-search-input"><?php _e('Search'); ?>:</label>
41
  <input type="text" id="post-search-input" name="em_search" value="<?php echo (!empty($_GET['em_search'])) ? $_GET['em_search']:''; ?>" />
42
- <input type="submit" value="<?php _e('Search'); ?>" class="button" />
43
  </p>
44
  -->
45
  <?php if ( $bookings_count >= $limit ) : ?>
@@ -48,7 +48,7 @@ function em_bookings_person_table(){
48
  <div class="alignleft actions">
49
  <select name="action">
50
  <option value="-1" selected="selected">
51
- <?php _e('Bulk Actions'); ?>
52
  </option>
53
  <option value="approve">
54
  <?php _e('Approve', 'dbem'); ?>
@@ -67,8 +67,7 @@ function em_bookings_person_table(){
67
  -->
68
  <?php
69
  if ( $bookings_count >= $limit ) {
70
- $page_link_template = em_add_get_params($_SERVER['REQUEST_URI'], array('pno'=>'%PAGE%', 'em_ajax'=>0, 'em_obj'=>'em_bookings_confirmed_table'));
71
- $bookings_nav = em_admin_paginate( $page_link_template, $bookings_count, $limit, $page, 5);
72
  echo $bookings_nav;
73
  }
74
  ?>
@@ -78,15 +77,15 @@ function em_bookings_person_table(){
78
  <div class="clear"></div>
79
  <?php if( $bookings_count > 0 ): ?>
80
  <div class='table-wrap'>
81
- <table id='dbem-bookings-table' class='widefat post fixed'>
82
  <thead>
83
  <tr>
84
  <th class='manage-column column-cb check-column' scope='col'>
85
  <input class='select-all' type="checkbox" value='1' />
86
  </th>
87
- <th class='manage-column' scope='col'>Event</th>
88
- <th class='manage-column' scope='col'>Spaces</th>
89
- <th class='manage-column' scope='col'>Status</th>
90
  <th class='manage-column' scope='col'>&nbsp;</th>
91
  </tr>
92
  </thead>
@@ -96,33 +95,36 @@ function em_bookings_person_table(){
96
  $event_count = 0;
97
  foreach ($bookings as $EM_Booking) {
98
  $EM_Event = $events[$EM_Booking->event_id];
99
- if( $EM_Event->can_manage() && ($rowno < $limit || empty($limit)) && ($event_count >= $offset || $offset === 0) ) {
100
  $rowno++;
101
  ?>
102
  <tr>
103
- <th scope="row" class="check-column" style="padding:7px 0px 7px;"><input type='checkbox' value='<?php echo $EM_Booking->id ?>' name='bookings[]'/></th>
104
- <td><a class="row-title" href="<?php bloginfo ( 'wpurl' )?>/wp-admin/admin.php?page=events-manager-bookings&amp;event_id=<?php echo $EM_Event->id ?>"><?php echo ($EM_Event->name); ?></a></td>
105
- <td><?php echo $EM_Booking->seats ?></td>
106
  <td><?php echo $EM_Booking->status_array[$EM_Booking->status]; ?>
107
  </td>
108
  <td>
109
  <?php
110
- $unapprove_url = em_add_get_params($_SERVER['REQUEST_URI'], array('action'=>'bookings_unapprove', 'bookings'=>$EM_Booking->id));
111
- $approve_url = em_add_get_params($_SERVER['REQUEST_URI'], array('action'=>'bookings_approve', 'bookings'=>$EM_Booking->id));
112
- $reject_url = em_add_get_params($_SERVER['REQUEST_URI'], array('action'=>'bookings_reject', 'bookings'=>$EM_Booking->id));
113
- $delete_url = em_add_get_params($_SERVER['REQUEST_URI'], array('action'=>'bookings_delete', 'bookings'=>$EM_Booking->id));
114
  ?>
115
- <?php if( $EM_Booking->status == 0 || $EM_Booking->status == 2 ): ?>
116
  <a class="em-bookings-approve" href="<?php echo $approve_url ?>"><?php _e('Approve','dbem'); ?></a> |
117
  <?php endif; ?>
118
- <?php if( $EM_Booking->status == 2 ): ?>
119
  <a class="em-bookings-unapprove" href="<?php echo $unapprove_url ?>"><?php _e('Unapprove','dbem'); ?></a> |
120
  <?php endif; ?>
 
 
 
121
  <?php if( $EM_Booking->status == 0 || $EM_Booking->status == 1 ): ?>
122
  <a class="em-bookings-reject" href="<?php echo $reject_url ?>"><?php _e('Reject','dbem'); ?></a> |
123
  <?php endif; ?>
124
- <a class="em-bookings-edit" href="<?php bloginfo ( 'wpurl' )?>/wp-admin/admin.php?page=events-manager-bookings&amp;booking_id=<?php echo $EM_Booking->id; ?>"><?php _e('Edit'); ?></a> |
125
- <a class="em-bookings-delete" href="<?php echo $delete_url ?>"><?php _e('Delete','dbem'); ?></a>
126
  </td>
127
  </tr>
128
  <?php
@@ -137,7 +139,7 @@ function em_bookings_person_table(){
137
  <?php _e('No confirmed bookings.', 'dbem'); ?>
138
  <?php endif; ?>
139
  </form>
140
- <?php if( !empty($bookings_nav) ) : ?>
141
  <div class='tablenav'>
142
  <?php echo $bookings_nav; ?>
143
  <div class="clear"></div>
18
  $offset = ( $action_scope && $page > 1 ) ? ($page-1)*$limit : 0;
19
 
20
  $bookings = $EM_Person->get_bookings();
21
+ $bookings_count = count($bookings);
22
  if($bookings_count > 0){
23
  //Get events here in one query to speed things up
24
  foreach($bookings as $EM_Booking){
37
  </li>
38
  </ul>
39
  <p class="search-box">
40
+ <label class="screen-reader-text" for="post-search-input"><?php _e('Search', 'dbem'); ?>:</label>
41
  <input type="text" id="post-search-input" name="em_search" value="<?php echo (!empty($_GET['em_search'])) ? $_GET['em_search']:''; ?>" />
42
+ <input type="submit" value="<?php _e('Search', 'dbem'); ?>" class="button" />
43
  </p>
44
  -->
45
  <?php if ( $bookings_count >= $limit ) : ?>
48
  <div class="alignleft actions">
49
  <select name="action">
50
  <option value="-1" selected="selected">
51
+ <?php _e('Bulk Actions', 'dbem'); ?>
52
  </option>
53
  <option value="approve">
54
  <?php _e('Approve', 'dbem'); ?>
67
  -->
68
  <?php
69
  if ( $bookings_count >= $limit ) {
70
+ $bookings_nav = em_admin_paginate( $bookings_count, $limit, $page, array('em_ajax'=>0, 'em_obj'=>'em_bookings_confirmed_table'));
 
71
  echo $bookings_nav;
72
  }
73
  ?>
77
  <div class="clear"></div>
78
  <?php if( $bookings_count > 0 ): ?>
79
  <div class='table-wrap'>
80
+ <table id='dbem-bookings-table' class='widefat post '>
81
  <thead>
82
  <tr>
83
  <th class='manage-column column-cb check-column' scope='col'>
84
  <input class='select-all' type="checkbox" value='1' />
85
  </th>
86
+ <th class='manage-column' scope='col'><?php _e('Event', 'dbem'); ?></th>
87
+ <th class='manage-column' scope='col'><?php _e('Spaces', 'dbem'); ?></th>
88
+ <th class='manage-column' scope='col'><?php _e('Status', 'dbem'); ?></th>
89
  <th class='manage-column' scope='col'>&nbsp;</th>
90
  </tr>
91
  </thead>
95
  $event_count = 0;
96
  foreach ($bookings as $EM_Booking) {
97
  $EM_Event = $events[$EM_Booking->event_id];
98
+ if( $EM_Event->can_manage('edit_events','edit_others_events') && ($rowno < $limit || empty($limit)) && ($event_count >= $offset || $offset === 0) ) {
99
  $rowno++;
100
  ?>
101
  <tr>
102
+ <th scope="row" class="check-column" style="padding:7px 0px 7px;"><input type='checkbox' value='<?php echo $EM_Booking->booking_id ?>' name='bookings[]'/></th>
103
+ <td><a class="row-title" href="<?php echo EM_ADMIN_URL; ?>&amp;page=events-manager-bookings&amp;event_id=<?php echo $EM_Event->id ?>"><?php echo ($EM_Event->name); ?></a></td>
104
+ <td><?php echo $EM_Booking->get_spaces() ?></td>
105
  <td><?php echo $EM_Booking->status_array[$EM_Booking->status]; ?>
106
  </td>
107
  <td>
108
  <?php
109
+ $unapprove_url = em_add_get_params($_SERVER['REQUEST_URI'], array('action'=>'bookings_unapprove', 'booking_id'=>$EM_Booking->booking_id));
110
+ $approve_url = em_add_get_params($_SERVER['REQUEST_URI'], array('action'=>'bookings_approve', 'booking_id'=>$EM_Booking->booking_id));
111
+ $reject_url = em_add_get_params($_SERVER['REQUEST_URI'], array('action'=>'bookings_reject', 'booking_id'=>$EM_Booking->booking_id));
112
+ $delete_url = em_add_get_params($_SERVER['REQUEST_URI'], array('action'=>'bookings_delete', 'booking_id'=>$EM_Booking->booking_id));
113
  ?>
114
+ <?php if( get_option('dbem_bookings_approval') && ($EM_Booking->status == 0 ) ): ?>
115
  <a class="em-bookings-approve" href="<?php echo $approve_url ?>"><?php _e('Approve','dbem'); ?></a> |
116
  <?php endif; ?>
117
+ <?php if( get_option('dbem_bookings_approval') && $EM_Booking->status == 1 ): ?>
118
  <a class="em-bookings-unapprove" href="<?php echo $unapprove_url ?>"><?php _e('Unapprove','dbem'); ?></a> |
119
  <?php endif; ?>
120
+ <?php if( $EM_Booking->status == 2 ): ?>
121
+ <a class="em-bookings-approve" href="<?php echo $approve_url ?>"><?php _e('Restore','dbem'); ?></a> |
122
+ <?php endif; ?>
123
  <?php if( $EM_Booking->status == 0 || $EM_Booking->status == 1 ): ?>
124
  <a class="em-bookings-reject" href="<?php echo $reject_url ?>"><?php _e('Reject','dbem'); ?></a> |
125
  <?php endif; ?>
126
+ <a class="em-bookings-edit" href="<?php echo EM_ADMIN_URL; ?>&amp;page=events-manager-bookings&amp;booking_id=<?php echo $EM_Booking->booking_id; ?>"><?php _e('Edit/View','dbem'); ?></a> |
127
+ <span class="trash"><a class="em-bookings-delete" href="<?php echo $delete_url ?>"><?php _e('Delete','dbem'); ?></a></span>
128
  </td>
129
  </tr>
130
  <?php
139
  <?php _e('No confirmed bookings.', 'dbem'); ?>
140
  <?php endif; ?>
141
  </form>
142
+ <?php if( !empty($bookings_nav) && $bookings >= $limit ) : ?>
143
  <div class='tablenav'>
144
  <?php echo $bookings_nav; ?>
145
  <div class="clear"></div>
admin/bookings/em-rejected.php CHANGED
@@ -5,7 +5,7 @@
5
  * @param int $event_id
6
  */
7
  function em_bookings_rejected_table(){
8
- global $EM_Event, $wpdb, $current_user;
9
 
10
  $action_scope = ( !empty($_REQUEST['em_obj']) && $_REQUEST['em_obj'] == 'em_bookings_confirmed_table' );
11
  $action = ( $action_scope && !empty($_GET ['action']) ) ? $_GET ['action']:'';
@@ -14,12 +14,16 @@ function em_bookings_rejected_table(){
14
  $page = ( $action_scope && !empty($_GET['pno']) ) ? $_GET['pno']:1;
15
  $offset = ( $action_scope && $page > 1 ) ? ($page-1)*$limit : 0;
16
 
17
- if( is_object($EM_Event) ){
18
- $bookings = $EM_Event->get_bookings()->get_rejected_bookings();
19
  }else{
20
- return false;
 
 
 
 
21
  }
22
- $bookings_count = (is_array($bookings)) ? count($bookings):0;
23
  ?>
24
  <div class='wrap em_bookings_pending_table em_obj'>
25
  <form id='bookings-filter' method='get' action='<?php bloginfo('wpurl') ?>/wp-admin/edit.php'>
@@ -31,9 +35,9 @@ function em_bookings_rejected_table(){
31
  </li>
32
  </ul>
33
  <p class="search-box">
34
- <label class="screen-reader-text" for="post-search-input"><?php _e('Search'); ?>:</label>
35
  <input type="text" id="post-search-input" name="em_search" value="<?php echo (!empty($_GET['em_search'])) ? $_GET['em_search']:''; ?>" />
36
- <input type="submit" value="<?php _e('Search'); ?>" class="button" />
37
  </p>
38
  -->
39
  <?php if ( $bookings_count >= $limit ) : ?>
@@ -42,7 +46,7 @@ function em_bookings_rejected_table(){
42
  <div class="alignleft actions">
43
  <select name="action">
44
  <option value="-1" selected="selected">
45
- <?php _e('Bulk Actions'); ?>
46
  </option>
47
  <option value="approve">
48
  <?php _e('Approve', 'dbem'); ?>
@@ -61,8 +65,7 @@ function em_bookings_rejected_table(){
61
  -->
62
  <?php
63
  if ( $bookings_count >= $limit ) {
64
- $page_link_template = em_add_get_params($_SERVER['REQUEST_URI'], array('pno'=>'%PAGE%', 'em_ajax'=>0, 'em_obj'=>'em_bookings_confirmed_table'));
65
- $bookings_nav = em_admin_paginate( $page_link_template, $bookings_count, $limit, $page, 5);
66
  echo $bookings_nav;
67
  }
68
  ?>
@@ -72,16 +75,16 @@ function em_bookings_rejected_table(){
72
  <div class="clear"></div>
73
  <?php if( $bookings_count > 0 ): ?>
74
  <div class='table-wrap'>
75
- <table id='dbem-bookings-table' class='widefat post fixed'>
76
  <thead>
77
  <tr>
78
  <th class='manage-column column-cb check-column' scope='col'>
79
  <input class='select-all' type="checkbox" value='1' />
80
  </th>
81
- <th class='manage-column' scope='col'>Booker</th>
82
- <th class='manage-column' scope='col'>E-mail</th>
83
- <th class='manage-column' scope='col'>Phone number</th>
84
- <th class='manage-column' scope='col'>Spaces</th>
85
  <th class='manage-column' scope='col'>&nbsp;</th>
86
  </tr>
87
  </thead>
@@ -89,24 +92,25 @@ function em_bookings_rejected_table(){
89
  <?php
90
  $rowno = 0;
91
  $event_count = 0;
92
- foreach ($bookings as $EM_Booking) {
93
  if( ($rowno < $limit || empty($limit)) && ($event_count >= $offset || $offset === 0) ) {
94
  $rowno++;
95
  ?>
96
  <tr>
97
- <th scope="row" class="check-column" style="padding:7px 0px 7px;"><input type='checkbox' value='<?php echo $EM_Booking->id ?>' name='bookings[]'/></th>
98
- <td><a href="<?php bloginfo ( 'wpurl' )?>/wp-admin/admin.php?page=events-manager-bookings&amp;person_id=<?php echo $EM_Booking->person->id; ?>"><?php echo $EM_Booking->person->name ?></a></td>
99
- <td><?php echo $EM_Booking->person->email ?></td>
100
  <td><?php echo $EM_Booking->person->phone ?></td>
101
- <td><?php echo $EM_Booking->seats ?></td>
102
  <td>
103
  <?php
104
- $approve_url = em_add_get_params($_SERVER['REQUEST_URI'], array('action'=>'bookings_approve', 'booking_id'=>$EM_Booking->id));
105
- $delete_url = em_add_get_params($_SERVER['REQUEST_URI'], array('action'=>'bookings_delete', 'booking_id'=>$EM_Booking->id));
 
106
  ?>
107
  <a class="em-bookings-approve" href="<?php echo $approve_url ?>"><?php _e('Approve','dbem'); ?></a> |
108
- <a class="em-bookings-edit" href="<?php bloginfo ( 'wpurl' )?>/wp-admin/admin.php?page=events-manager-bookings&amp;booking_id=<?php echo $EM_Booking->id; ?>"><?php _e('Edit'); ?></a> |
109
- <a class="em-bookings-delete" href="<?php echo $delete_url ?>"><?php _e('Delete','dbem'); ?></a>
110
  </td>
111
  </tr>
112
  <?php
@@ -121,7 +125,7 @@ function em_bookings_rejected_table(){
121
  <?php _e('No rejected bookings.', 'dbem'); ?>
122
  <?php endif; ?>
123
  </form>
124
- <?php if( !empty($bookings_nav) ) : ?>
125
  <div class='tablenav'>
126
  <?php echo $bookings_nav; ?>
127
  <div class="clear"></div>
5
  * @param int $event_id
6
  */
7
  function em_bookings_rejected_table(){
8
+ global $EM_Event, $EM_Ticket, $wpdb, $current_user;
9
 
10
  $action_scope = ( !empty($_REQUEST['em_obj']) && $_REQUEST['em_obj'] == 'em_bookings_confirmed_table' );
11
  $action = ( $action_scope && !empty($_GET ['action']) ) ? $_GET ['action']:'';
14
  $page = ( $action_scope && !empty($_GET['pno']) ) ? $_GET['pno']:1;
15
  $offset = ( $action_scope && $page > 1 ) ? ($page-1)*$limit : 0;
16
 
17
+ if( is_object($EM_Ticket) ){
18
+ $EM_Bookings = $EM_Ticket->get_bookings()->get_rejected_bookings();
19
  }else{
20
+ if( is_object($EM_Event) ){
21
+ $EM_Bookings = $EM_Event->get_bookings()->get_rejected_bookings();
22
+ }else{
23
+ return false;
24
+ }
25
  }
26
+ $bookings_count = (is_array($EM_Bookings->bookings)) ? count($EM_Bookings->bookings):0;
27
  ?>
28
  <div class='wrap em_bookings_pending_table em_obj'>
29
  <form id='bookings-filter' method='get' action='<?php bloginfo('wpurl') ?>/wp-admin/edit.php'>
35
  </li>
36
  </ul>
37
  <p class="search-box">
38
+ <label class="screen-reader-text" for="post-search-input"><?php _e('Search', 'dbem'); ?>:</label>
39
  <input type="text" id="post-search-input" name="em_search" value="<?php echo (!empty($_GET['em_search'])) ? $_GET['em_search']:''; ?>" />
40
+ <input type="submit" value="<?php _e('Search', 'dbem'); ?>" class="button" />
41
  </p>
42
  -->
43
  <?php if ( $bookings_count >= $limit ) : ?>
46
  <div class="alignleft actions">
47
  <select name="action">
48
  <option value="-1" selected="selected">
49
+ <?php _e('Bulk Actions', 'dbem'); ?>
50
  </option>
51
  <option value="approve">
52
  <?php _e('Approve', 'dbem'); ?>
65
  -->
66
  <?php
67
  if ( $bookings_count >= $limit ) {
68
+ $bookings_nav = em_admin_paginate( $bookings_count, $limit, $page, array('em_ajax'=>0, 'em_obj'=>'em_bookings_confirmed_table'));
 
69
  echo $bookings_nav;
70
  }
71
  ?>
75
  <div class="clear"></div>
76
  <?php if( $bookings_count > 0 ): ?>
77
  <div class='table-wrap'>
78
+ <table id='dbem-bookings-table' class='widefat post '>
79
  <thead>
80
  <tr>
81
  <th class='manage-column column-cb check-column' scope='col'>
82
  <input class='select-all' type="checkbox" value='1' />
83
  </th>
84
+ <th class='manage-column' scope='col'><?php _e('Booker', 'dbem'); ?></th>
85
+ <th class='manage-column' scope='col'><?php _e('E-mail', 'dbem'); ?></th>
86
+ <th class='manage-column' scope='col'><?php _e('Phone number', 'dbem'); ?></th>
87
+ <th class='manage-column' scope='col'><?php _e('Spaces', 'dbem'); ?></th>
88
  <th class='manage-column' scope='col'>&nbsp;</th>
89
  </tr>
90
  </thead>
92
  <?php
93
  $rowno = 0;
94
  $event_count = 0;
95
+ foreach ($EM_Bookings->bookings as $EM_Booking) {
96
  if( ($rowno < $limit || empty($limit)) && ($event_count >= $offset || $offset === 0) ) {
97
  $rowno++;
98
  ?>
99
  <tr>
100
+ <th scope="row" class="check-column" style="padding:7px 0px 7px;"><input type='checkbox' value='<?php echo $EM_Booking->booking_id ?>' name='bookings[]'/></th>
101
+ <td><a href="<?php echo EM_ADMIN_URL; ?>&amp;page=events-manager-bookings&amp;person_id=<?php echo $EM_Booking->person->ID; ?>"><?php echo $EM_Booking->person->get_name() ?></a></td>
102
+ <td><?php echo $EM_Booking->person->user_email ?></td>
103
  <td><?php echo $EM_Booking->person->phone ?></td>
104
+ <td><?php echo $EM_Booking->get_spaces() ?></td>
105
  <td>
106
  <?php
107
+ $approve_url = em_add_get_params($_SERVER['REQUEST_URI'], array('action'=>'bookings_approve', 'booking_id'=>$EM_Booking->booking_id));
108
+ $delete_url = em_add_get_params($_SERVER['REQUEST_URI'], array('action'=>'bookings_delete', 'booking_id'=>$EM_Booking->booking_id));
109
+ $edit_url = em_add_get_params($_SERVER['REQUEST_URI'], array('booking_id'=>$EM_Booking->booking_id, 'em_ajax'=>null, 'em_obj'=>null));
110
  ?>
111
  <a class="em-bookings-approve" href="<?php echo $approve_url ?>"><?php _e('Approve','dbem'); ?></a> |
112
+ <a class="em-bookings-edit" href="<?php echo $edit_url ?>"><?php _e('Edit/View','dbem'); ?></a> |
113
+ <span class="trash"><a class="em-bookings-delete" href="<?php echo $delete_url ?>"><?php _e('Delete','dbem'); ?></a></span>
114
  </td>
115
  </tr>
116
  <?php
125
  <?php _e('No rejected bookings.', 'dbem'); ?>
126
  <?php endif; ?>
127
  </form>
128
+ <?php if( !empty($bookings_nav) && $EM_Bookings >= $limit ) : ?>
129
  <div class='tablenav'>
130
  <?php echo $bookings_nav; ?>
131
  <div class="clear"></div>
admin/em-admin.php CHANGED
@@ -1,87 +1,188 @@
1
  <?php
2
  //Admin functions
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
 
4
  /**
5
  * Generate warnings and notices in the admin area
6
  */
7
  function em_admin_warnings() {
 
8
  //If we're editing the events page show hello to new user
9
  $events_page_id = get_option ( 'dbem_events_page' );
10
  $dismiss_link_joiner = ( count($_GET) > 0 ) ? '&amp;':'?';
11
 
12
- if( em_verify_admin() ){
13
  //New User Intro
14
  if (isset ( $_GET ['disable_hello_to_user'] ) && $_GET ['disable_hello_to_user'] == 'true'){
15
  // Disable Hello to new user if requested
16
- update_option ( 'dbem_hello_to_user', 0 );
17
- }elseif ( get_option ( 'dbem_hello_to_user' ) == 1 && !empty($_GET['page']) && $_GET['page'] == 'events-manager-events' ) {
18
- $current_user = wp_get_current_user ();
19
  //FIXME update welcome msg with good links
20
- $advice = sprintf ( __ ( "<p>Hey, <strong>%s</strong>, welcome to <strong>Events Manager</strong>! We hope you like it around here.</p>
21
- <p>Now it's time to insert events lists through <a href='%s' title='Widgets page'>widgets</a>, <a href='%s' title='Template tags documentation'>template tags</a> or <a href='%s' title='Shortcodes documentation'>shortcodes</a>.</p>
22
- <p>By the way, have you taken a look at the <a href='%s' title='Change settings'>Settings page</a>? That's where you customize the way events and locations are displayed.</p>
23
- <p>What? Tired of seeing this advice? I hear you, <a href='%s' title='Don't show this advice again'>click here</a> and you won't see this again!</p>", 'dbem' ), $current_user->display_name, get_bloginfo ( 'url' ) . '/wp-admin/widgets.php', 'http://wp-events-plugin.com/documentation/template-tags/', 'http://wp-events-plugin.com/documentation/shortcodes/', get_bloginfo ( 'url' ) . '/wp-admin/admin.php?page=events-manager-options', get_bloginfo ( 'url' ) . '/wp-admin/admin.php?page=events-manager&disable_hello_to_user=true' );
24
  ?>
25
  <div id="message" class="updated">
26
  <?php echo $advice; ?>
27
  </div>
28
  <?php
29
- }
30
 
31
- //If events page couldn't be created
32
- if( !empty($_GET['em_dismiss_admin_notice']) ){
33
- delete_option('dbem_admin_notice_'.$_GET['em_dismiss_admin_notice']);
34
  }else{
35
- if ( get_option('dbem_admin_notice_3.0.91') ){
36
  ?>
37
- <div class="updated">
38
- <p><?php echo sprintf ( __( '<strong>Events Manager has some new features!</strong><ul><li>Bookings can now be approved before they count towards your event\'s space allocations.</li><li>Events now have owners, and you can restrict users so they can only manage events/locations/categories they create.<br/><br/>These new permissions are enabled by default, but since you upgraded it has been disabled to maintain the previous plugin behaviour. You can re-enable it from the <a href="%s">settings page</a>. <a href="%s">Dismiss</a>', 'dbem'), get_bloginfo ( 'url' ) . '/wp-admin/admin.php?page=events-manager-options', $_SERVER['REQUEST_URI'].$dismiss_link_joiner.'em_dismiss_admin_notice=3.0.91' ); ?></p>
39
  </div>
40
  <?php
41
  }
42
  }
43
- //If events page couldn't be created
44
- if( !empty($_GET['em_dismiss_rc_notice']) ){
45
- delete_option('dbem_admin_notice_rc');
46
- }elseif( get_option('dbem_admin_notice_rc')){
47
  ?>
48
- <div class="updated">
49
- <p>
50
- <strong>Events Manager 4.0 on its way!</strong>
51
- We've just about finished with 4.0, which boasts TONS of long awaited features including advanced booking, permalinks, MultiSite and BuddPress integration, and much more!
52
- It is undergoing final testing to be released in the coming days, and the website has already had a documentation and tutorial overhaul in preparation.
53
- </p><p>
54
- To read up on the changes and get a hold of the Release Candidate
55
- <a href="http://wp-events-plugin.com/try-the-beta/?utm_source=plugin&utm_medium=html&utm_campaign=rc_notice">click here</a>.
56
- Please make sure to have a look at this page if you use EM for bookings or have made any mods to the plugin, as there are some considerations to make when upgrading.<br />
57
- <a href="http://wp-events-plugin.com/try-the-beta/?utm_source=plugin&utm_medium=html&utm_campaign=rc_notice">See what's new</a> | <a href="<?php echo $_SERVER['REQUEST_URI'].$dismiss_link_joiner.'em_dismiss_rc_notice=1' ?>">Dismiss this message.</a>
58
- </p>
59
  </div>
60
- <?php
61
  }
62
 
63
- //If events page couldn't be created
64
- if( !empty($_GET['em_dismiss_events_page']) ){
65
- update_option('dbem_dismiss_events_page',1);
66
- }else{
67
- if ( !get_page($events_page_id) && !get_option('dbem_dismiss_events_page') ){
68
  ?>
69
  <div id="em_page_error" class="updated">
70
- <p><?php echo sprintf ( __( 'Uh Oh! For some reason wordpress could not create an events page for you (or you just deleted it). Not to worry though, all you have to do is create an empty page, name it whatever you want, and select it as your events page in your <a href="%s">settings page</a>. Sorry for the extra step! If you know what you are doing, you may have done this on purpose, if so <a href="%s">ignore this message</a>', 'dbem'), get_bloginfo ( 'url' ) . '/wp-admin/admin.php?page=events-manager-options', $_SERVER['REQUEST_URI'].$dismiss_link_joiner.'em_dismiss_events_page=1' ); ?></p>
71
  </div>
72
- <?php
 
 
 
 
 
 
 
 
 
 
 
 
73
  }
74
  }
75
  }
76
  //Warn about EM page edit
77
  if ( preg_match( '/(post|page).php/', $_SERVER ['SCRIPT_NAME']) && isset ( $_GET ['action'] ) && $_GET ['action'] == 'edit' && isset ( $_GET ['post'] ) && $_GET ['post'] == "$events_page_id") {
78
- $message = sprintf ( __ ( "This page corresponds to <strong>Events Manager</strong> events page. Its content will be overriden by <strong>Events Manager</strong>. If you want to display your content, you can can assign another page to <strong>Events Manager</strong> in the the <a href='%s'>Settings</a>. ", 'dbem' ), 'admin.php?page=events-manager-options' );
79
  $notice = "<div class='error'><p>$message</p></div>";
80
  echo $notice;
81
  }
82
-
83
  }
84
- add_action ( 'admin_notices', 'em_admin_warnings' );
85
 
86
  /**
87
  * Creates a wp-admin style navigation. All this does is wrap some html around the em_paginate function result to make it style correctly in the admin area.
@@ -91,55 +192,26 @@ add_action ( 'admin_notices', 'em_admin_warnings' );
91
  * @param int $page
92
  * @param int $pagesToShow
93
  * @return string
94
- * @uses em_paginate()
 
95
  */
96
- function em_admin_paginate($link, $total, $limit, $page=1, $pagesToShow=5){
97
  $return = '<div class="tablenav-pages">';
98
- $return .= sprintf( '<span class="displaying-num">' . __( 'Displaying %s&#8211;%s of %s' ) . '</span>',
 
 
 
 
 
 
 
99
  number_format_i18n( ( $page - 1 ) * $limit + 1 ),
100
  number_format_i18n( min( $page * $limit, $total ) ),
101
- number_format_i18n( $total )
 
102
  );
103
- $return .= em_paginate($link, $total, $limit, $page, $pagesToShow);
104
  $return .= '</div>';
105
- return $return;
106
- }
107
-
108
- /**
109
- * Called by admin_print_scripts-(hook|page) action, created when adding menu items in events-manager.php
110
- */
111
- function em_admin_load_scripts(){
112
- //Load the UI items, currently date picker and autocomplete plus dependencies
113
- //wp_enqueue_script('em-ui-js', WP_PLUGIN_URL.'/events-manager/includes/js/jquery-ui-1.8.5.custom.min.js', array('jquery', 'jquery-ui-core'));
114
- wp_enqueue_script('em-ui-js', WP_PLUGIN_URL.'/events-manager/includes/js/em_ui.js', array('jquery', 'jquery-ui-core'));
115
-
116
- //Add maps
117
- if( get_option('dbem_gmap_is_active') ){
118
- wp_enqueue_script('em-google-maps', 'http://maps.google.com/maps/api/js?sensor=false');
119
- }
120
- //Time Entry
121
- wp_enqueue_script('em-timeentry', WP_PLUGIN_URL.'/events-manager/includes/js/timeentry/jquery.timeentry.js', array('jquery'));
122
-
123
- //Date Picker Locale
124
- $locale_code = substr ( get_locale (), 0, 2 );
125
- $locale_file = "/events-manager/includes/js/i18n/jquery.ui.datepicker-$locale_code.js";
126
- if ( file_exists(WP_PLUGIN_DIR.$locale_file) ) {
127
- wp_enqueue_script("em-ui-datepicker-$locale_code", WP_PLUGIN_URL.$locale_file, array('em-ui-js'));
128
- }
129
- wp_enqueue_script('em-script', WP_PLUGIN_URL.'/events-manager/includes/js/em_admin.js', array('em-ui-js'));
130
-
131
- //TinyMCE Editor
132
- remove_filter('the_editor', 'qtrans_modifyRichEditor'); //qtranslate filter
133
- add_action( 'admin_print_footer_scripts', 'wp_tiny_mce', 25 );
134
- add_action( 'admin_print_footer_scripts', 'wp_tiny_mce_preload_dialogs', 30 );
135
- wp_enqueue_script('post');
136
- if ( user_can_richedit() )
137
- wp_enqueue_script('editor');
138
-
139
- add_thickbox();
140
- wp_enqueue_script('media-upload');
141
- wp_enqueue_script('word-count');
142
- wp_enqueue_script('quicktags');
143
  }
144
 
145
  /**
@@ -147,139 +219,38 @@ function em_admin_load_scripts(){
147
  */
148
  function em_admin_load_styles() {
149
  add_thickbox();
150
- wp_enqueue_style('em-ui-css', WP_PLUGIN_URL.'/events-manager/includes/css/jquery-ui-1.7.3.custom.css');
151
- wp_enqueue_style('events-manager-admin', WP_PLUGIN_URL.'/events-manager/includes/css/events_manager_admin.css');
152
  }
153
 
154
  /**
155
- * Loads script inline due to insertion of php values
 
 
 
156
  */
157
- function em_admin_general_script() {
158
- //TODO clean script up, remove dependency of php so it can be moved to js file.
159
- // Check if the locale is there and loads it
160
- $locale_code = substr ( get_locale (), 0, 2 );
161
- $show24Hours = 'true';
162
- // Setting 12 hours format for those countries using it
163
- if (preg_match ( "/en|sk|zh|us|uk/", $locale_code ))
164
- $show24Hours = 'false';
165
- ?>
166
- <script type="text/javascript">
167
- //<![CDATA[
168
- // TODO: make more general, to support also latitude and longitude (when added)
169
-
170
- jQuery(document).ready( function($) {
171
 
172
- function updateIntervalDescriptor () {
173
- $(".interval-desc").hide();
174
- var number = "-plural";
175
- if ($('input#recurrence-interval').val() == 1 || $('input#recurrence-interval').val() == "")
176
- number = "-singular"
177
- var descriptor = "span#interval-"+$("select#recurrence-frequency").val()+number;
178
- $(descriptor).show();
179
- }
180
- function updateIntervalSelectors () {
181
- $('p.alternate-selector').hide();
182
- $('p#'+ $('select#recurrence-frequency').val() + "-selector").show();
183
- }
184
- function updateShowHideRsvp () {
185
- if($('input#rsvp-checkbox').attr("checked")) {
186
- $("div#rsvp-data").fadeIn();
187
- } else {
188
- $("div#rsvp-data").hide();
189
- }
190
- }
191
- function updateShowHideRecurrence () {
192
- if( $('input#event-recurrence').attr("checked")) {
193
- $("#event_recurrence_pattern").fadeIn();
194
- $("#event-date-explanation").hide();
195
- $("#recurrence-dates-explanation").show();
196
- $("h3#recurrence-dates-title").show();
197
- $("h3#event-date-title").hide();
198
- } else {
199
- $("#event_recurrence_pattern").hide();
200
- $("#recurrence-dates-explanation").hide();
201
- $("#event-date-explanation").show();
202
- $("h3#recurrence-dates-title").hide();
203
- $("h3#event-date-title").show();
204
- }
205
- }
206
- $("#recurrence-dates-explanation").hide();
207
- $("#localised-date").show();
208
- $("#localised-end-date").show();
209
-
210
- $("#date-to-submit").hide();
211
- $("#end-date-to-submit").hide();
212
-
213
- $("#start-time").timeEntry({spinnerImage: '', show24Hours: <?php echo $show24Hours; ?> });
214
- $("#end-time").timeEntry({spinnerImage: '', show24Hours: <?php echo $show24Hours; ?>});
215
-
216
- $('input.select-all').change(function(){
217
- if($(this).is(':checked'))
218
- $('input.row-selector').attr('checked', true);
219
- else
220
- $('input.row-selector').attr('checked', false);
221
- });
222
-
223
- updateIntervalDescriptor();
224
- updateIntervalSelectors();
225
- updateShowHideRecurrence();
226
- updateShowHideRsvp();
227
- $('input#event-recurrence').change(updateShowHideRecurrence);
228
- $('input#rsvp-checkbox').change(updateShowHideRsvp);
229
-
230
- // recurrency elements
231
- $('input#recurrence-interval').keyup(updateIntervalDescriptor);
232
- $('select#recurrence-frequency').change(updateIntervalDescriptor);
233
- $('select#recurrence-frequency').change(updateIntervalSelectors);
234
-
235
- // hiding or showing notes according to their content
236
- $('.postbox h3').prepend('<a class="togbox">+</a> ');
237
- $('#event_notes h3').click( function() {
238
- $(this).parent().first().toggleClass('closed');
239
- });
240
-
241
- // users cannot submit the event form unless some fields are filled
242
- function validateEventForm(){
243
- errors = "";
244
- var recurring = $("input[@name=repeated_event]:checked").val();
245
- requiredFields= new Array('event_name', 'localised_event_date', 'location_name','location_address','location_town');
246
- var localisedRequiredFields = {
247
- 'event_name':"<?php _e ( 'Name', 'dbem' )?>",
248
- 'localised_event_date':"<?php _e ( 'Date', 'dbem' )?>",
249
- 'location_name':"<?php _e ( 'Location', 'dbem' )?>",
250
- 'location_address':"<?php _e ( 'Address', 'dbem' )?>",
251
- 'location_town':"<?php _e ( 'Town', 'dbem' )?>"
252
- };
253
- missingFields = new Array;
254
- for (var i in requiredFields) {
255
- if ($("input[@name=" + requiredFields[i]+ "]").val() == 0) {
256
- missingFields.push(localisedRequiredFields[requiredFields[i]]);
257
- $("input[@name=" + requiredFields[i]+ "]").css('border','2px solid red');
258
- } else {
259
- $("input[@name=" + requiredFields[i]+ "]").css('border','1px solid #DFDFDF');
260
- }
261
- }
262
-
263
- // alert('ciao ' + recurring+ " end: " + $("input[@name=localised_event_end_date]").val());
264
- if (missingFields.length > 0) {
265
- errors = "<?php _e ( 'Some required fields are missing:', 'dbem' )?> " + missingFields.join(", ") + ".\n";
266
- }
267
- if(recurring && $("input[@name=localised_event_end_date]").val() == "") {
268
- errors = errors + "<?php _e ( 'Since the event is repeated, you must specify an end date', 'dbem' )?>.";
269
- $("input[@name=localised_event_end_date]").css('border','2px solid red');
270
- } else {
271
- $("input[@name=localised_event_end_date]").css('border','1px solid #DFDFDF');
272
- }
273
- if(errors != "") {
274
- alert(errors);
275
- return false;
276
- }
277
- return true;
278
- }
279
- $('#event-form').bind("submit", validateEventForm);
280
- });
281
- //]]>
282
- </script>
283
- <?php
284
  }
 
285
  ?>
1
  <?php
2
  //Admin functions
3
+ function em_admin_menu(){
4
+ global $menu, $submenu, $pagenow;
5
+ //Count pending bookings
6
+ if( get_option('dbem_rsvp_enabled') ){
7
+ $bookings_num = '';
8
+ $bookings_pending_count = apply_filters('em_bookings_pending_count',0);
9
+ if( get_option('dbem_bookings_approval') == 1){
10
+ $bookings_pending_count += count(EM_Bookings::get(array('status'=>'0', 'blog'=>get_current_blog_id()))->bookings);
11
+ }
12
+ if($bookings_pending_count > 0){
13
+ $bookings_num = '<span class="update-plugins count-'.$bookings_pending_count.'"><span class="plugin-count">'.$bookings_pending_count.'</span></span>';
14
+ }
15
+ }else{
16
+ $bookings_num = '';
17
+ $bookings_pending_count = 0;
18
+ }
19
+ //Count pending events
20
+ $events_num = '';
21
+ $events_pending_count = EM_Events::count(array('status'=>0, 'scope'=>'all', 'blog'=>get_current_blog_id()));
22
+ //TODO Add flexible permissions
23
+ if($events_pending_count > 0){
24
+ $events_num = '<span class="update-plugins count-'.$events_pending_count.'"><span class="plugin-count">'.$events_pending_count.'</span></span>';
25
+ }
26
+ //Count pending recurring events
27
+ $events_recurring_num = '';
28
+ $events_recurring_pending_count = EM_Events::count(array('status'=>0, 'recurring'=>1, 'scope'=>'all', 'blog'=>get_current_blog_id()));
29
+ //TODO Add flexible permissions
30
+ if($events_recurring_pending_count > 0){
31
+ $events_recurring_num = '<span class="update-plugins count-'.$events_recurring_pending_count.'"><span class="plugin-count">'.$events_recurring_pending_count.'</span></span>';
32
+ }
33
+ $both_pending_count = apply_filters('em_items_pending_count', $events_pending_count + $bookings_pending_count + $events_recurring_pending_count);
34
+ $both_num = ($both_pending_count > 0) ? '<span class="update-plugins count-'.$both_pending_count.'"><span class="plugin-count">'.$both_pending_count.'</span></span>':'';
35
+ // Add a submenu to the custom top-level menu:
36
+ $plugin_pages = array();
37
+ if( get_option('dbem_rsvp_enabled') ){
38
+ $plugin_pages['bookings'] = add_submenu_page('edit.php?post_type='.EM_POST_TYPE_EVENT, __('Bookings', 'dbem'), __('Bookings', 'dbem').$bookings_num, 'manage_bookings', 'events-manager-bookings', "em_bookings_page");
39
+ }
40
+ $plugin_pages['options'] = add_submenu_page('edit.php?post_type='.EM_POST_TYPE_EVENT, __('Events Manager Settings','dbem'),__('Settings','dbem'), 'activate_plugins', "events-manager-options", 'em_admin_options_page');
41
+ $plugin_pages['help'] = add_submenu_page('edit.php?post_type='.EM_POST_TYPE_EVENT, __('Getting Help for Events Manager','dbem'),__('Help','dbem'), 'activate_plugins', "events-manager-help", 'em_admin_help_page');
42
+ //If multisite global with locations set to be saved in main blogs we can force locations to be created on the main blog only
43
+ if( EM_MS_GLOBAL && !is_main_site() && get_site_option('dbem_ms_mainblog_locations') ){
44
+ include( dirname(__FILE__)."/em-ms-locations.php" );
45
+ $plugin_pages['locations'] = add_submenu_page('edit.php?post_type='.EM_POST_TYPE_EVENT, __('Locations','dbem'),__('Locations','dbem'), 'read_others_locations', "locations", 'em_admin_ms_locations');
46
+ }
47
+ $plugin_pages = apply_filters('em_create_events_submenu',$plugin_pages);
48
+ //We have to modify the menus manually
49
+ if( !empty($both_num) ){ //Main Event Menu
50
+ //go through the menu array and modify the events menu if found
51
+ foreach ( (array)$menu as $key => $parent_menu ) {
52
+ if ( $parent_menu[2] == 'edit.php?post_type='.EM_POST_TYPE_EVENT ){
53
+ $menu[$key][0] = $menu[$key][0]. $both_num;
54
+ break;
55
+ }
56
+ }
57
+ }
58
+ if( !empty($events_num) && !empty($submenu['edit.php?post_type='.EM_POST_TYPE_EVENT]) ){ //Submenu Event Item
59
+ //go through the menu array and modify the events menu if found
60
+ foreach ( (array)$submenu['edit.php?post_type='.EM_POST_TYPE_EVENT] as $key => $submenu_item ) {
61
+ if ( $submenu_item[2] == 'edit.php?post_type='.EM_POST_TYPE_EVENT ){
62
+ $submenu['edit.php?post_type='.EM_POST_TYPE_EVENT][$key][0] = $submenu['edit.php?post_type='.EM_POST_TYPE_EVENT][$key][0]. $events_num;
63
+ break;
64
+ }
65
+ }
66
+ }
67
+ if( !empty($events_recurring_num) && !empty($submenu['edit.php?post_type='.EM_POST_TYPE_EVENT]) ){ //Submenu Recurring Event Item
68
+ //go through the menu array and modify the events menu if found
69
+ foreach ( (array)$submenu['edit.php?post_type='.EM_POST_TYPE_EVENT] as $key => $submenu_item ) {
70
+ if ( $submenu_item[2] == 'edit.php?post_type=event-recurring' ){
71
+ $submenu['edit.php?post_type='.EM_POST_TYPE_EVENT][$key][0] = $submenu['edit.php?post_type='.EM_POST_TYPE_EVENT][$key][0]. $events_recurring_num;
72
+ break;
73
+ }
74
+ }
75
+ }
76
+ /* Hack! Add location/recurrence isn't possible atm so this is a workaround */
77
+ global $_wp_submenu_nopriv;
78
+ if( $pagenow == 'post-new.php' && !empty($_REQUEST['post_type']) ){
79
+ if( $_REQUEST['post_type'] == EM_POST_TYPE_LOCATION && !empty($_wp_submenu_nopriv['edit.php']['post-new.php']) && current_user_can('edit_locations') ){
80
+ unset($_wp_submenu_nopriv['edit.php']['post-new.php']);
81
+ }
82
+ if( $_REQUEST['post_type'] == 'event-recurring' && !empty($_wp_submenu_nopriv['edit.php']['post-new.php']) && current_user_can('edit_recurring_events') ){
83
+ unset($_wp_submenu_nopriv['edit.php']['post-new.php']);
84
+ }
85
+ }
86
+ }
87
+ add_action('admin_menu','em_admin_menu');
88
+
89
+ function em_ms_admin_menu(){
90
+ add_menu_page( __('Events Manager','dbem'), __('Events Manager','dbem'), 'activate_plugins', 'events-manager-options', 'em_ms_admin_options_page', plugins_url('includes/images/calendar-16.png', dirname(dirname(__FILE__)).'/events-manager.php') );
91
+ add_submenu_page('events-manager-options', __('Update Blogs','dbem'),__('Update Blogs','dbem'), 'activate_plugins', "events-manager-update", 'em_ms_upgrade');
92
+ }
93
+ add_action('network_admin_menu','em_ms_admin_menu');
94
+
95
+ function em_admin_init(){
96
+ //in MS global mode
97
+ if( EM_MS_GLOBAL && is_user_logged_in() && !is_main_site() && get_site_option('dbem_ms_mainblog_locations') ){
98
+ EM_Object::ms_global_switch();
99
+ $user = new WP_User(get_current_user_id());
100
+ if( count($user->roles) == 0 ){
101
+ $user->set_role('subscriber');
102
+ }
103
+ EM_Object::ms_global_switch_back();
104
+ }
105
+ }
106
+ add_action('admin_init','em_admin_init');
107
 
108
  /**
109
  * Generate warnings and notices in the admin area
110
  */
111
  function em_admin_warnings() {
112
+ global $EM_Notices;
113
  //If we're editing the events page show hello to new user
114
  $events_page_id = get_option ( 'dbem_events_page' );
115
  $dismiss_link_joiner = ( count($_GET) > 0 ) ? '&amp;':'?';
116
 
117
+ if( current_user_can('activate_plugins') ){
118
  //New User Intro
119
  if (isset ( $_GET ['disable_hello_to_user'] ) && $_GET ['disable_hello_to_user'] == 'true'){
120
  // Disable Hello to new user if requested
121
+ update_option('dbem_hello_to_user',0);
122
+ }elseif ( get_option ( 'dbem_hello_to_user' ) ) {
 
123
  //FIXME update welcome msg with good links
124
+ $advice = sprintf( __("<p>Events Manager is ready to go! It is highly recommended you read the <a href='%s'>Getting Started</a> guide on our site, as well as checking out the <a href='%s'>Settings Page</a>. <a href='%s' title='Don't show this advice again'>Dismiss</a></p>", 'dbem'), 'http://wp-events-plugin.com/documentation/getting-started/?utm_source=em&utm_medium=plugin&utm_content=installationlink&utm_campaign=plugin_links', EM_ADMIN_URL .'&amp;page=events-manager-options', $_SERVER['REQUEST_URI'].$dismiss_link_joiner.'disable_hello_to_user=true');
 
 
 
125
  ?>
126
  <div id="message" class="updated">
127
  <?php echo $advice; ?>
128
  </div>
129
  <?php
130
+ }
131
 
132
+ //If events page couldn't be created or is missing
133
+ if( !empty($_GET['em_dismiss_events_page']) ){
134
+ update_option('dbem_dismiss_events_page',1);
135
  }else{
136
+ if ( !get_page($events_page_id) && !get_option('dbem_dismiss_events_page') ){
137
  ?>
138
+ <div id="em_page_error" class="updated">
139
+ <p><?php echo sprintf ( __( 'Uh Oh! For some reason WordPress could not create an events page for you (or you just deleted it). Not to worry though, all you have to do is create an empty page, name it whatever you want, and select it as your events page in your <a href="%s">settings page</a>. Sorry for the extra step! If you know what you are doing, you may have done this on purpose, if so <a href="%s">ignore this message</a>', 'dbem'), EM_ADMIN_URL .'&amp;page=events-manager-options', $_SERVER['REQUEST_URI'].$dismiss_link_joiner.'em_dismiss_events_page=1' ); ?></p>
140
  </div>
141
  <?php
142
  }
143
  }
144
+
145
+ if( defined('EMP_VERSION') && EMP_VERSION < EM_PRO_MIN_VERSION ){
 
 
146
  ?>
147
+ <div id="em_page_error" class="updated">
148
+ <p><?php _e('There is a newer version of Events Manager Pro which is required for this current version of Events Manager. Please go to the plugin website and download the latest update.','dbem'); ?></p>
 
 
 
 
 
 
 
 
 
149
  </div>
150
+ <?php
151
  }
152
 
153
+ if( is_multisite() && !empty($_REQUEST['page']) && $_REQUEST['page']=='events-manager-options' && is_super_admin() && get_option('dbem_ms_update_nag') ){
154
+ if( !empty($_GET['disable_dbem_ms_update_nag']) ){
155
+ delete_site_option('dbem_ms_update_nag');
156
+ }else{
 
157
  ?>
158
  <div id="em_page_error" class="updated">
159
+ <p><?php echo sprintf(__('MultiSite options have moved <a href="%s">here</a>. <a href="%s">Dismiss message</a>','dbem'),admin_url().'network/admin.php?page=events-manager-options', $_SERVER['REQUEST_URI'].'&amp;disable_dbem_ms_update_nag=1'); ?></p>
160
  </div>
161
+ <?php
162
+ }
163
+ }
164
+
165
+ if( is_super_admin() && get_option('dbem_migrate_images_nag') ){
166
+ if( !empty($_GET['disable_dbem_migrate_images_nag']) ){
167
+ delete_site_option('dbem_migrate_images_nag');
168
+ }else{
169
+ ?>
170
+ <div id="em_page_error" class="updated">
171
+ <p><?php echo sprintf(__('Whilst they will still appear using placeholders, you need to <a href="%s">migrate your location and event images</a> in order for them to appear in your edit forms and media library. <a href="%s">Dismiss message</a>','dbem'),admin_url().'edit.php?post_type=event&page=events-manager-options&em_migrate_images=1&_wpnonce='.wp_create_nonce('em_migrate_images'), em_add_get_params($_SERVER['REQUEST_URI'], array('disable_dbem_migrate_images_nag' => 1))); ?></p>
172
+ </div>
173
+ <?php
174
  }
175
  }
176
  }
177
  //Warn about EM page edit
178
  if ( preg_match( '/(post|page).php/', $_SERVER ['SCRIPT_NAME']) && isset ( $_GET ['action'] ) && $_GET ['action'] == 'edit' && isset ( $_GET ['post'] ) && $_GET ['post'] == "$events_page_id") {
179
+ $message = sprintf ( __ ( "This page corresponds to <strong>Events Manager</strong> events page. Its content will be overriden by Events Manager, although if you include the word CONTENTS (exactly in capitals) and surround it with other text, only CONTENTS will be overwritten. If you want to change the way your events look, go to the <a href='%s'>settings</a> page. ", 'dbem' ), EM_ADMIN_URL .'&amp;page=events-manager-options' );
180
  $notice = "<div class='error'><p>$message</p></div>";
181
  echo $notice;
182
  }
183
+ echo $EM_Notices;
184
  }
185
+ add_action ( 'admin_notices', 'em_admin_warnings', 100 );
186
 
187
  /**
188
  * Creates a wp-admin style navigation. All this does is wrap some html around the em_paginate function result to make it style correctly in the admin area.
192
  * @param int $page
193
  * @param int $pagesToShow
194
  * @return string
195
+ * @uses paginate_links()
196
+ * @uses add_query_arg()
197
  */
198
+ function em_admin_paginate($total, $limit, $page=1, $vars=false){
199
  $return = '<div class="tablenav-pages">';
200
+ $events_nav = paginate_links( array(
201
+ 'base' => add_query_arg( 'pno', '%#%' ),
202
+ 'format' => '',
203
+ 'total' => ceil($total / $limit),
204
+ 'current' => $page,
205
+ 'add_args' => $vars
206
+ ));
207
+ $return .= sprintf( '<span class="displaying-num">' . __( 'Displaying %s&#8211;%s of %s', 'dbem') . ' </span>%s',
208
  number_format_i18n( ( $page - 1 ) * $limit + 1 ),
209
  number_format_i18n( min( $page * $limit, $total ) ),
210
+ number_format_i18n( $total ),
211
+ $events_nav
212
  );
 
213
  $return .= '</div>';
214
+ return apply_filters('em_admin_paginate',$return,$total,$limit,$page,$vars);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
215
  }
216
 
217
  /**
219
  */
220
  function em_admin_load_styles() {
221
  add_thickbox();
222
+ wp_enqueue_style('em-ui-css', plugins_url('includes/css/jquery-ui-1.8.13.custom.css',dirname(__FILE__)));
223
+ wp_enqueue_style('events-manager-admin', plugins_url('includes/css/events_manager_admin.css',dirname(__FILE__)));
224
  }
225
 
226
  /**
227
+ * Settings link in the plugins page menu
228
+ * @param array $links
229
+ * @param string $file
230
+ * @return array
231
  */
232
+ function em_set_plugin_meta($links, $file) {
233
+ $plugin = plugin_basename(__FILE__);
234
+ // create link
235
+ if ($file == $plugin) {
236
+ return array_merge(
237
+ $links,
238
+ array( sprintf( '<a href="'.EM_ADMIN_URL.'&amp;page=events-manager-options">%s</a>', __('Settings', 'dbem') ) )
239
+ );
240
+ }
241
+ return $links;
242
+ }
243
+ //add_filter( 'plugin_row_meta', 'em_set_plugin_meta', 10, 2 );
 
 
244
 
245
+ function em_plugin_action_links($actions, $file, $plugin_data) {
246
+ $actions['settings'] = sprintf( '<a href="'.EM_ADMIN_URL.'&amp;page=events-manager-options">%s</a>', __('Settings', 'dbem') );
247
+ if( is_multisite() ){
248
+ $uninstall_url = admin_url().'network/admin.php?page=events-manager-options&amp;action=uninstall&amp;_wpnonce='.wp_create_nonce('em_uninstall_'.get_current_user_id().'_wpnonce');
249
+ }else{
250
+ $uninstall_url = EM_ADMIN_URL.'&amp;page=events-manager-options&amp;action=uninstall&amp;_wpnonce='.wp_create_nonce('em_uninstall_'.get_current_user_id().'_wpnonce');
251
+ }
252
+ $actions['uninstall'] = '<span class="delete"><a href="'.$uninstall_url.'" class="delete">'.__('Uninstall','dbem').'</a></span>';
253
+ return $actions;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
254
  }
255
+ add_filter( 'plugin_action_links_events-manager/events-manager.php', 'em_plugin_action_links', 10, 3 );
256
  ?>
admin/em-bookings.php CHANGED
@@ -6,46 +6,17 @@
6
  function em_admin_actions_bookings() {
7
  global $dbem_form_add_message;
8
  global $dbem_form_delete_message;
9
- global $wpdb, $EM_Booking, $EM_Event;
10
 
11
- if( current_user_can(EM_MIN_CAPABILITY) && is_object($EM_Booking) && !empty($_REQUEST['action']) ) {
12
- if( $_REQUEST['action'] == 'bookings_delete' ){
13
- //Delete
14
- if( isset($_POST['booking_id']) ){
15
- $EM_Booking = new EM_Booking($_POST['booking_id']);
16
- $EM_Booking->delete();
17
- }
18
- }elseif( $_REQUEST['action'] == 'bookings_edit' ){
19
- //Edit Booking
20
- $validation = $EM_Booking->get_post();
21
- if ( $validation ) { //EM_Event gets the event if submitted via POST and validates it (safer than to depend on JS)
22
- //Save
23
- if( $EM_Booking->save() ) {
24
- function em_booking_save_notification(){ global $EM_Booking; ?><div class="updated"><p><strong><?php echo $EM_Booking->feedback_message; ?></strong></p></div><?php }
25
- }else{
26
- function em_booking_save_notification(){ global $EM_Booking; ?><div class="error"><p><strong><?php echo $EM_Booking->feedback_message; ?></strong></p></div><?php }
27
- }
28
- }else{
29
- //TODO make errors clearer when saving person
30
- function em_booking_save_notification(){ global $EM_Booking; ?><div class="error"><p><strong><?php echo $EM_Booking->feedback_message; ?></strong></p></div><?php }
31
- }
32
- add_action ( 'admin_notices', 'em_booking_save_notification' );
33
- }elseif( $_REQUEST['action'] == 'bookings_approve' || $_REQUEST['action'] == 'bookings_reject' || $_REQUEST['action'] == 'bookings_unapprove' ){
34
- //Booking Approvals
35
- $status_array = array('bookings_unapprove' => 0,'bookings_approve' => 1,'bookings_reject' => 2, 'bookings_cancel' => 3);
36
- if( $EM_Booking->set_status( $status_array[$_REQUEST['action']] ) ) {
37
- function em_booking_save_notification(){ global $EM_Booking; ?><div class="updated"><p><strong><?php echo $EM_Booking->feedback_message; ?></strong></p></div><?php }
38
- }else{
39
- function em_booking_save_notification(){ global $EM_Booking; ?><div class="error"><p><strong><?php echo $EM_Booking->feedback_message; ?></strong></p></div><?php }
40
- }
41
- add_action ( 'admin_notices', 'em_booking_save_notification' );
42
- }elseif( $_REQUEST['action'] == 'bookings_add_note' ){
43
  $EM_Booking->add_note($_REQUEST['booking_note']);
44
  function em_booking_save_notification(){ global $EM_Booking; ?><div class="updated"><p><strong><?php echo $EM_Booking->feedback_message; ?></strong></p></div><?php }
45
  add_action ( 'admin_notices', 'em_booking_save_notification' );
46
  }
47
- }elseif( current_user_can(EM_MIN_CAPABILITY) && is_object($EM_Event) && !empty($_REQUEST['action']) ){
48
- if( $_REQUEST['action'] == 'export_csv' ){
 
49
  $EM_Event->get_bookings()->export_csv();
50
  exit();
51
  }
@@ -57,13 +28,18 @@ add_action('admin_init','em_admin_actions_bookings',100);
57
  * Decide what content to show in the bookings section.
58
  */
59
  function em_bookings_page(){
 
60
  //First any actions take priority
61
- if( !empty($_REQUEST['booking_id']) ){
 
 
62
  em_bookings_single();
63
  }elseif( !empty($_REQUEST['person_id']) ){
64
  em_bookings_person();
65
  }elseif( !empty($_REQUEST['event_id']) ){
66
  em_bookings_event();
 
 
67
  }else{
68
  em_bookings_dashboard();
69
  }
@@ -73,6 +49,7 @@ function em_bookings_page(){
73
  * Generates the bookings dashboard, showing information on all events
74
  */
75
  function em_bookings_dashboard(){
 
76
  ?>
77
  <div class='wrap'>
78
  <div id='icon-users' class='icon32'>
@@ -81,12 +58,14 @@ function em_bookings_dashboard(){
81
  <h2>
82
  <?php _e('Event Bookings Dashboard', 'dbem'); ?>
83
  </h2>
84
- <?php if( get_option('dbem_bookings_approval') ): ?>
 
85
  <h2><?php _e('Pending Bookings','dbem'); ?></h2>
86
  <?php em_bookings_pending_table(); ?>
87
  <?php endif; ?>
88
  <h2><?php _e('Events With Bookings Enabled','dbem'); ?></h2>
89
  <?php em_bookings_events_table(); ?>
 
90
  </div>
91
  <?php
92
  }
@@ -95,9 +74,9 @@ function em_bookings_dashboard(){
95
  * Shows all booking data for a single event
96
  */
97
  function em_bookings_event(){
98
- global $EM_Event,$EM_Person;
99
  //check that user can access this page
100
- if( is_object($EM_Event) && !$EM_Event->can_manage() ){
101
  ?>
102
  <div class="wrap"><h2><?php _e('Unauthorized Access','dbem'); ?></h2><p><?php _e('You do not have the rights to manage this event.','dbem'); ?></p></div>
103
  <?php
@@ -112,12 +91,14 @@ function em_bookings_event(){
112
  </div>
113
  <h2>
114
  <?php echo sprintf(__('Manage %s Bookings', 'dbem'), "'{$EM_Event->name}'"); ?>
115
- <a href="admin.php?page=events-manager-event&event_id=<?php echo $EM_Event->id; ?>" class="button add-new-h2"><?php _e('View/Edit Event','dbem') ?></a>
 
116
  </h2>
117
- <div><a href='<?php echo get_bloginfo('wpurl') . "/wp-admin/admin.php?page=events-manager-bookings&action=export_csv&event_id=".$EM_Event->id ?>'><?php _e('export csv','dbem')?></a></div>
 
118
  <div>
119
  <p><strong><?php _e('Event Name','dbem'); ?></strong> : <?php echo ($EM_Event->name); ?></p>
120
- <p><strong>Availability :</strong> <?php echo $EM_Event->get_bookings()->get_booked_seats() . '/'. $EM_Event->seats ." ". __('Seats confirmed','dbem'); ?></p>
121
  <p>
122
  <strong><?php _e('Date','dbem'); ?></strong> :
123
  <?php echo $localised_start_date; ?>
@@ -126,10 +107,10 @@ function em_bookings_event(){
126
  </p>
127
  <p>
128
  <strong><?php _e('Location','dbem'); ?></strong> :
129
- <a class="row-title" href="<?php bloginfo ( 'wpurl' )?>/wp-admin/admin.php?page=events-manager-locations&amp;location_id=<?php echo $EM_Event->location->id ?>"><?php echo ($EM_Event->location->name); ?></a>
130
  </p>
131
  </div>
132
- <?php if( get_option('dbem_bookings_approval') ): ?>
133
  <h2><?php _e('Pending Bookings','dbem'); ?></h2>
134
  <?php em_bookings_pending_table(); ?>
135
  <?php endif; ?>
@@ -139,15 +120,68 @@ function em_bookings_event(){
139
  <?php em_bookings_rejected_table(); ?>
140
  <h2><?php _e('Cancelled Bookings','dbem'); ?></h2>
141
  <?php em_bookings_cancelled_table(); ?>
 
142
  </div>
143
  <?php
144
  }
145
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
146
  /**
147
  * Shows a single booking for a single person.
148
  */
149
  function em_bookings_single(){
150
- global $EM_Booking;
151
  //check that user can access this page
152
  if( is_object($EM_Booking) && !$EM_Booking->can_manage() ){
153
  ?>
@@ -163,35 +197,138 @@ function em_bookings_single(){
163
  <h2>
164
  <?php _e('Edit Booking', 'dbem'); ?>
165
  </h2>
166
- <div id="poststuff" class="metabox-holder has-right-sidebar">
 
167
  <div id="post-body">
168
  <div id="post-body-content">
169
- <div id="event_name" class="stuffbox">
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
170
  <h3>
171
  <?php _e ( 'Booking Details', 'dbem' ); ?>
172
  </h3>
173
  <div class="inside">
174
- <?php em_bookings_edit_form(); ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
175
  </div>
176
- </div>
177
- </div>
178
- </div>
179
- </div>
180
- <br style="clear:both;" />
181
- <div id="poststuff" class="metabox-holder has-right-sidebar">
182
- <div id="post-body">
183
- <div id="post-body-content">
184
- <div id="event_name" class="stuffbox">
185
  <h3>
186
  <?php _e ( 'Booking Notes', 'dbem' ); ?>
187
  </h3>
188
  <div class="inside">
189
  <p><?php _e('You can add private notes below for internal reference that only event managers will see.','dbem'); ?></p>
190
  <?php foreach( $EM_Booking->notes as $note ):
191
- $user = get_userdata($note['author']);
192
  ?>
193
  <div>
194
- <?php echo date(get_option('date_format'), $note['timestamp']) .' - '. $user->display_name; ?> <?php _e('wrote','dbem'); ?>:
195
  <p style="background:#efefef; padding:5px;"><?php echo nl2br($note['note']); ?></p>
196
  </div>
197
  <?php endforeach; ?>
@@ -202,11 +339,12 @@ function em_bookings_single(){
202
  </form>
203
  </div>
204
  </div>
 
205
  </div>
206
  </div>
207
  </div>
208
  <br style="clear:both;" />
209
- <?php do_action('em_bookings_single_footer'); ?>
210
  </div>
211
  <?php
212
 
@@ -216,7 +354,20 @@ function em_bookings_single(){
216
  * Shows all bookings made by one person.
217
  */
218
  function em_bookings_person(){
219
- global $EM_Person;
 
 
 
 
 
 
 
 
 
 
 
 
 
220
  ?>
221
  <div class='wrap'>
222
  <div id='icon-users' class='icon32'>
@@ -224,8 +375,12 @@ function em_bookings_person(){
224
  </div>
225
  <h2>
226
  <?php _e('Manage Person\'s Booking', 'dbem'); ?>
227
- <a href="admin.php?page=events-manager-bookings&action=person_delete&person_id=<?php echo $EM_Person->id; ?>" onclick="if( !confirm('<?php _e('Are you sure you want to delete this person? All bookings corresponding to this person will be deleted and this is not reversible.','dbem') ?>') ){ return false; }" class="button add-new-h2"><?php _e('Delete Person','dbem') ?></a>
 
 
228
  </h2>
 
 
229
  <div id="poststuff" class="metabox-holder has-right-sidebar">
230
  <div id="post-body">
231
  <div id="post-body-content">
@@ -234,55 +389,34 @@ function em_bookings_person(){
234
  <?php _e ( 'Personal Details', 'dbem' ); ?>
235
  </h3>
236
  <div class="inside">
237
- <?php em_person_edit_form(); ?>
238
  </div>
239
  </div>
240
  </div>
241
  </div>
242
  </div>
243
  <br style="clear:both;" />
 
244
  <h3><?php _e('Past And Present Bookings','dbem'); ?></h3>
245
  <?php em_bookings_person_table(); ?>
 
246
  </div>
247
  <?php
248
  }
249
 
250
- function em_bookings_edit_form(){
251
- global $EM_Booking;
252
- $EM_Event = new EM_Event($EM_Booking->event_id);
253
- $localised_start_date = date_i18n('D d M Y', $EM_Event->start);
254
- $localised_end_date = date_i18n('D d M Y', $EM_Event->end);
255
- ?>
256
- <form action="" method="post" id="em-person-form">
257
- <h4>Event Details</h4>
258
- <table>
259
- <tr><td><strong><?php _e('Name','dbem'); ?></strong></td><td><a class="row-title" href="<?php bloginfo ( 'wpurl' )?>/wp-admin/admin.php?page=events-manager-bookings&amp;event_id=<?php echo $EM_Event->id ?>"><?php echo ($EM_Event->name); ?></a></td></tr>
260
- <tr>
261
- <td><strong><?php _e('Date/Time','dbem'); ?>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</strong></td>
262
- <td>
263
- <?php echo $localised_start_date; ?>
264
- <?php echo ($localised_end_date != $localised_start_date) ? " - $localised_end_date":'' ?>
265
- <?php echo substr ( $EM_Event->start_time, 0, 5 ) . " - " . substr ( $EM_Event->end_time, 0, 5 ); ?>
266
- </td>
267
- </tr>
268
- </table>
269
- <h4>Personal Details</h4>
270
- <table>
271
- <tr><td><strong><?php _e('Name','dbem'); ?> </strong></td><td><a href="<?php bloginfo ( 'wpurl' )?>/wp-admin/admin.php?page=events-manager-bookings&amp;person_id=<?php echo $EM_Booking->person_id; ?>"><?php echo $EM_Booking->person->name ?></a></td></tr>
272
- <tr><td><strong><?php _e('Phone','dbem'); ?> </strong></td><td><?php echo $EM_Booking->person->phone; ?></td></tr>
273
- <tr><td><strong><?php _e('E-mail','dbem'); ?>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</strong></td><td><?php echo $EM_Booking->person->email; ?></td></tr>
274
- </table>
275
- <h4>Booking Details</h4>
276
- <table>
277
- <tr><td><strong><?php _e('Spaces','dbem'); ?> </strong></td><td><input type="text" name="booking_seats" value="<?php echo $EM_Booking->seats; ?>" /></td></tr>
278
- <tr><td><strong><?php _e('Comment','dbem'); ?>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</strong></td><td><textarea name="booking_comment"><?php echo $EM_Booking->comment; ?></textarea></td></tr>
279
- </table>
280
- <p class="submit">
281
- <input type="submit" name="events_update" value="<?php _e ( 'Save' ); ?> &raquo;" />
282
- </p>
283
- <input type="hidden" name="action" value="bookings_edit" />
284
- <input type="hidden" name="booking_id" value="<?php echo $EM_Booking->id; ?>" />
285
- </form>
286
- <?php
287
- }
288
  ?>
6
  function em_admin_actions_bookings() {
7
  global $dbem_form_add_message;
8
  global $dbem_form_delete_message;
9
+ global $wpdb, $EM_Booking, $EM_Event, $EM_Notices;
10
 
11
+ if( is_object($EM_Booking) && !empty($_REQUEST['action']) && $EM_Booking->can_manage('manage_bookings','manage_others_bookings') ) {
12
+ if( $_REQUEST['action'] == 'bookings_add_note' ){
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
  $EM_Booking->add_note($_REQUEST['booking_note']);
14
  function em_booking_save_notification(){ global $EM_Booking; ?><div class="updated"><p><strong><?php echo $EM_Booking->feedback_message; ?></strong></p></div><?php }
15
  add_action ( 'admin_notices', 'em_booking_save_notification' );
16
  }
17
+ }
18
+ if( is_object($EM_Event) && !empty($_REQUEST['action']) ){
19
+ if( $_REQUEST['action'] == 'bookings_export_csv' && wp_verify_nonce($_REQUEST['_wpnonce'],'bookings_export_csv') ){
20
  $EM_Event->get_bookings()->export_csv();
21
  exit();
22
  }
28
  * Decide what content to show in the bookings section.
29
  */
30
  function em_bookings_page(){
31
+ global $action;
32
  //First any actions take priority
33
+ if( !empty($_REQUEST['action']) && substr($_REQUEST['action'],0,7) != 'booking' ){ //actions not starting with booking_
34
+ do_action('em_bookings_'.$action);
35
+ }elseif( !empty($_REQUEST['booking_id']) ){
36
  em_bookings_single();
37
  }elseif( !empty($_REQUEST['person_id']) ){
38
  em_bookings_person();
39
  }elseif( !empty($_REQUEST['event_id']) ){
40
  em_bookings_event();
41
+ }elseif( !empty($_REQUEST['ticket_id']) ){
42
+ em_bookings_ticket();
43
  }else{
44
  em_bookings_dashboard();
45
  }
49
  * Generates the bookings dashboard, showing information on all events
50
  */
51
  function em_bookings_dashboard(){
52
+ global $EM_Notices;
53
  ?>
54
  <div class='wrap'>
55
  <div id='icon-users' class='icon32'>
58
  <h2>
59
  <?php _e('Event Bookings Dashboard', 'dbem'); ?>
60
  </h2>
61
+ <?php echo $EM_Notices; ?>
62
+ <?php if( get_option('dbem_bookings_approval')): ?>
63
  <h2><?php _e('Pending Bookings','dbem'); ?></h2>
64
  <?php em_bookings_pending_table(); ?>
65
  <?php endif; ?>
66
  <h2><?php _e('Events With Bookings Enabled','dbem'); ?></h2>
67
  <?php em_bookings_events_table(); ?>
68
+ <?php do_action('em_bookings_dashboard'); ?>
69
  </div>
70
  <?php
71
  }
74
  * Shows all booking data for a single event
75
  */
76
  function em_bookings_event(){
77
+ global $EM_Event,$EM_Person,$EM_Notices;
78
  //check that user can access this page
79
+ if( is_object($EM_Event) && !$EM_Event->can_manage('manage_bookings','manage_others_bookings') ){
80
  ?>
81
  <div class="wrap"><h2><?php _e('Unauthorized Access','dbem'); ?></h2><p><?php _e('You do not have the rights to manage this event.','dbem'); ?></p></div>
82
  <?php
91
  </div>
92
  <h2>
93
  <?php echo sprintf(__('Manage %s Bookings', 'dbem'), "'{$EM_Event->name}'"); ?>
94
+ <a href="<?php echo $EM_Event->output('#_EDITEVENTURL'); ?>" class="button add-new-h2"><?php _e('View/Edit Event','dbem') ?></a>
95
+ <?php do_action('em_admin_event_booking_options_buttons'); ?>
96
  </h2>
97
+ <?php echo $EM_Notices; ?>
98
+ <div><a href='<?php echo EM_ADMIN_URL ."&amp;page=events-manager-bookings&action=bookings_export_csv&_wpnonce=".wp_create_nonce('bookings_export_csv')."&event_id=".$EM_Event->id ?>'><?php _e('export csv','dbem')?></a></div>
99
  <div>
100
  <p><strong><?php _e('Event Name','dbem'); ?></strong> : <?php echo ($EM_Event->name); ?></p>
101
+ <p><strong><?php _e('Availability','dbem'); ?></strong> : <?php echo $EM_Event->get_bookings()->get_booked_spaces() . '/'. $EM_Event->get_spaces() ." ". __('Spaces confirmed','dbem'); ?></p>
102
  <p>
103
  <strong><?php _e('Date','dbem'); ?></strong> :
104
  <?php echo $localised_start_date; ?>
107
  </p>
108
  <p>
109
  <strong><?php _e('Location','dbem'); ?></strong> :
110
+ <a class="row-title" href="<?php echo admin_url(); ?>post.php?action=edit&amp;post=<?php echo $EM_Event->get_location()->post_id ?>"><?php echo ($EM_Event->get_location()->name); ?></a>
111
  </p>
112
  </div>
113
+ <?php if( get_option('dbem_bookings_approval')): ?>
114
  <h2><?php _e('Pending Bookings','dbem'); ?></h2>
115
  <?php em_bookings_pending_table(); ?>
116
  <?php endif; ?>
120
  <?php em_bookings_rejected_table(); ?>
121
  <h2><?php _e('Cancelled Bookings','dbem'); ?></h2>
122
  <?php em_bookings_cancelled_table(); ?>
123
+ <?php do_action('em_bookings_event_footer', $EM_Event); ?>
124
  </div>
125
  <?php
126
  }
127
 
128
+ /**
129
+ * Shows a ticket view
130
+ */
131
+ function em_bookings_ticket(){
132
+ global $EM_Ticket,$EM_Notices;
133
+ $EM_Event = $EM_Ticket->get_event();
134
+ //check that user can access this page
135
+ if( is_object($EM_Ticket) && !$EM_Ticket->can_manage() ){
136
+ ?>
137
+ <div class="wrap"><h2><?php _e('Unauthorized Access','dbem'); ?></h2><p><?php _e('You do not have the rights to manage this ticket.','dbem'); ?></p></div>
138
+ <?php
139
+ return false;
140
+ }
141
+ ?>
142
+ <div class='wrap'>
143
+ <div id='icon-users' class='icon32'>
144
+ <br/>
145
+ </div>
146
+ <h2>
147
+ <?php echo sprintf(__('Ticket for %s', 'dbem'), "'{$EM_Event->name}'"); ?>
148
+ <a href="<?php echo EM_ADMIN_URL; ?>&amp;page=events-manager-event&event_id=<?php echo $EM_Event->id; ?>" class="button add-new-h2"><?php _e('View/Edit Event','dbem') ?></a>
149
+ <a href="<?php echo EM_ADMIN_URL; ?>&amp;page=events-manager-bookings&event_id=<?php echo $EM_Event->id; ?>" class="button add-new-h2"><?php _e('View Event Bookings','dbem') ?></a>
150
+ </h2>
151
+ <?php echo $EM_Notices; ?>
152
+ <div>
153
+ <table>
154
+ <tr><td><?php echo __('Name','dbem'); ?></td><td></td><td><?php echo $EM_Ticket->name; ?></td></tr>
155
+ <tr><td><?php echo __('Description','dbem'); ?>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</td><td></td><td><?php echo ($EM_Ticket->description) ? $EM_Ticket->description : '-'; ?></td></tr>
156
+ <tr><td><?php echo __('Price','dbem'); ?></td><td></td><td><?php echo ($EM_Ticket->price) ? $EM_Ticket->price : '-'; ?></td></tr>
157
+ <tr><td><?php echo __('Spaces','dbem'); ?></td><td></td><td><?php echo ($EM_Ticket->spaces) ? $EM_Ticket->spaces : '-'; ?></td></tr>
158
+ <tr><td><?php echo __('Min','dbem'); ?></td><td></td><td><?php echo ($EM_Ticket->min) ? $EM_Ticket->min : '-'; ?></td></tr>
159
+ <tr><td><?php echo __('Max','dbem'); ?></td><td></td><td><?php echo ($EM_Ticket->max) ? $EM_Ticket->max : '-'; ?></td></tr>
160
+ <tr><td><?php echo __('Start','dbem'); ?></td><td></td><td><?php echo ($EM_Ticket->start) ? $EM_Ticket->start : '-'; ?></td></tr>
161
+ <tr><td><?php echo __('End','dbem'); ?></td><td></td><td><?php echo ($EM_Ticket->end) ? $EM_Ticket->end : '-'; ?></td></tr>
162
+ <?php do_action('em_booking_admin_ticket_row', $EM_Ticket); ?>
163
+ </table>
164
+ </div>
165
+ <?php if( get_option('dbem_bookings_approval')): ?>
166
+ <h2><?php _e('Pending Bookings','dbem'); ?></h2>
167
+ <?php em_bookings_pending_table(); ?>
168
+ <?php endif; ?>
169
+ <h2><?php _e('Confirmed Bookings','dbem'); ?></h2>
170
+ <?php em_bookings_confirmed_table(); ?>
171
+ <h2><?php _e('Rejected Bookings','dbem'); ?></h2>
172
+ <?php em_bookings_rejected_table(); ?>
173
+ <h2><?php _e('Cancelled Bookings','dbem'); ?></h2>
174
+ <?php em_bookings_cancelled_table(); ?>
175
+ <?php do_action('em_bookings_ticket_footer', $EM_Ticket); ?>
176
+ </div>
177
+ <?php
178
+ }
179
+
180
  /**
181
  * Shows a single booking for a single person.
182
  */
183
  function em_bookings_single(){
184
+ global $EM_Booking, $EM_Notices;
185
  //check that user can access this page
186
  if( is_object($EM_Booking) && !$EM_Booking->can_manage() ){
187
  ?>
197
  <h2>
198
  <?php _e('Edit Booking', 'dbem'); ?>
199
  </h2>
200
+ <?php echo $EM_Notices; ?>
201
+ <div id="poststuff" class="metabox-holder">
202
  <div id="post-body">
203
  <div id="post-body-content">
204
+ <div id="em-booking-details" class="stuffbox">
205
+ <h3>
206
+ <?php _e ( 'Event Details', 'dbem' ); ?>
207
+ </h3>
208
+ <div class="inside">
209
+ <?php
210
+ $EM_Event = $EM_Booking->get_event();
211
+ $localised_start_date = date_i18n('D d M Y', $EM_Event->start);
212
+ $localised_end_date = date_i18n('D d M Y', $EM_Event->end);
213
+ ?>
214
+ <table>
215
+ <tr><td><strong><?php _e('Name','dbem'); ?></strong></td><td><a class="row-title" href="<?php echo EM_ADMIN_URL; ?>&amp;page=events-manager-bookings&amp;event_id=<?php echo $EM_Event->id ?>"><?php echo ($EM_Event->name); ?></a></td></tr>
216
+ <tr>
217
+ <td><strong><?php _e('Date/Time','dbem'); ?>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</strong></td>
218
+ <td>
219
+ <?php echo $localised_start_date; ?>
220
+ <?php echo ($localised_end_date != $localised_start_date) ? " - $localised_end_date":'' ?>
221
+ <?php echo substr ( $EM_Event->start_time, 0, 5 ) . " - " . substr ( $EM_Event->end_time, 0, 5 ); ?>
222
+ </td>
223
+ </tr>
224
+ </table>
225
+ </div>
226
+ </div>
227
+ <div id="em-booking-details" class="stuffbox">
228
+ <h3>
229
+ <?php _e ( 'Personal Details', 'dbem' ); ?>
230
+ </h3>
231
+ <div class="inside">
232
+ <?php echo $EM_Booking->get_person()->display_summary(); ?>
233
+ </div>
234
+ </div>
235
+ <div id="em-booking-details" class="stuffbox">
236
  <h3>
237
  <?php _e ( 'Booking Details', 'dbem' ); ?>
238
  </h3>
239
  <div class="inside">
240
+ <?php
241
+ $EM_Event = $EM_Booking->get_event();
242
+ $localised_start_date = date_i18n('D d M Y', $EM_Event->start);
243
+ $localised_end_date = date_i18n('D d M Y', $EM_Event->end);
244
+ $shown_tickets = array();
245
+ ?>
246
+ <p><strong><?php _e('Status','dbem'); ?> : </strong><?php echo $EM_Booking->get_status(); ?></p>
247
+ <form action="" method="post">
248
+ <table class="em-tickets-bookings-table" cellspacing="0" cellpadding="0">
249
+ <thead>
250
+ <tr>
251
+ <th><?php _e('Ticket Type','dbem'); ?></th>
252
+ <th><?php _e('Spaces','dbem'); ?></th>
253
+ <th><?php _e('Price','dbem'); ?></th>
254
+ </tr>
255
+ </thead>
256
+ <tbody>
257
+ <?php foreach($EM_Booking->get_tickets_bookings()->tickets_bookings as $EM_Ticket_Booking): ?>
258
+ <tr>
259
+ <td class="ticket-type"><a class="row-title" href="<?php echo EM_ADMIN_URL; ?>&amp;page=events-manager-bookings&amp;ticket_id=<?php echo $EM_Ticket_Booking->get_ticket()->id ?>"><?php echo $EM_Ticket_Booking->get_ticket()->name ?></a></td>
260
+ <td>
261
+ <input name="em_tickets[<?php echo $EM_Ticket_Booking->get_ticket()->id; ?>][spaces]" class="em-ticket-select" value="<?php echo $EM_Ticket_Booking->get_spaces(); ?>" />
262
+ </td>
263
+ <td><?php echo $EM_Ticket_Booking->get_price(true,true); ?></td>
264
+ </tr>
265
+ <?php $shown_tickets[] = $EM_Ticket_Booking->ticket_id; ?>
266
+ <?php endforeach; ?>
267
+ <?php if( count($shown_tickets) < count($EM_Event->get_bookings()->get_tickets()->tickets)): ?><tr>
268
+ <?php foreach($EM_Event->get_bookings()->get_tickets()->tickets as $EM_Ticket): ?>
269
+ <?php if( !in_array($EM_Ticket->id, $shown_tickets) ): ?>
270
+ <tr>
271
+ <td class="ticket-type"><a class="row-title" href="<?php echo EM_ADMIN_URL; ?>&amp;page=events-manager-bookings&amp;ticket_id=<?php echo $EM_Ticket->id ?>"><?php echo $EM_Ticket->name ?></a></td>
272
+ <td>
273
+ <input name="em_tickets[<?php echo $EM_Ticket->id; ?>][spaces]" class="em-ticket-select" value="0" />
274
+ </td>
275
+ <td><?php echo em_get_currency_symbol() ?>0.00</td>
276
+ </tr>
277
+ <?php endif; ?>
278
+ <?php endforeach; ?>
279
+ <?php endif; ?>
280
+ </tbody>
281
+ <tfoot>
282
+ <tr>
283
+ <th><?php _e('Totals','dbem'); ?></th>
284
+ <th><?php echo $EM_Booking->get_spaces(); ?></th>
285
+ <th><?php echo $EM_Booking->get_price(true, true); ?></th>
286
+ </tr>
287
+ <?php if( !get_option('dbem_bookings_tax_auto_add') && is_numeric(get_option('dbem_bookings_tax')) && get_option('dbem_bookings_tax') > 0 ): ?>
288
+ <tr>
289
+ <th><?php _e('Tax','dbem'); ?></th>
290
+ <th><?php echo get_option('dbem_bookings_tax') ?>%</th>
291
+ <th><?php echo em_get_currency_symbol().number_format($EM_Booking->get_price() * (get_option('dbem_bookings_tax')/100),2); ?></th>
292
+ </tr>
293
+ <tr>
294
+ <th><?php _e('Total (inc. tax)','dbem'); ?></th>
295
+ <th>&nbsp;</th>
296
+ <th><?php echo em_get_currency_symbol().number_format($EM_Booking->get_price()* (1 + get_option('dbem_bookings_tax')/100),2); ?></th>
297
+ </tr>
298
+ <?php endif; ?>
299
+ </tfoot>
300
+ </table>
301
+ <p>
302
+ <input type="submit" class="em-booking-submit" id="em-booking-submit" value="<?php _e('Modify Booking', 'dbem'); ?>" />
303
+ <input type='hidden' name='action' value='booking_save'/>
304
+ <input type='hidden' name='booking_id' value='<?php echo $EM_Booking->booking_id; ?>'/>
305
+ <input type='hidden' name='event_id' value='<?php echo $EM_Event->id; ?>'/>
306
+ <input type='hidden' name='_wpnonce' value='<?php echo wp_create_nonce('booking_save'); ?>'/>
307
+ <em><?php _e('<strong>Note:</strong> ticket availability not taken into account (i.e. you can overbook). Confirmation email is not resent automatically.','dbem'); ?></em>
308
+ </p>
309
+ <table cellspacing="0" cellpadding="0">
310
+ <?php if( !get_option('em_booking_form_custom') ): ?>
311
+ <tr><td><strong><?php _e('Comment','dbem'); ?>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</strong></td><td><?php echo $EM_Booking->booking_comment; ?></td></tr>
312
+ <?php foreach( $EM_Booking->get_custom() as $custom_option ){
313
+ ?><tr><td><strong><?php echo $custom_option['name'] ?></strong></td><td><?php echo esc_html($custom_option['value']); ?></td></tr><?php
314
+ } ?>
315
+ <?php else: do_action('em_bookings_single_custom',$EM_Booking); ?>
316
+ <?php endif; ?>
317
+ </table>
318
+ </form>
319
  </div>
320
+ </div>
321
+ <div id="em-booking-notes" class="stuffbox">
 
 
 
 
 
 
 
322
  <h3>
323
  <?php _e ( 'Booking Notes', 'dbem' ); ?>
324
  </h3>
325
  <div class="inside">
326
  <p><?php _e('You can add private notes below for internal reference that only event managers will see.','dbem'); ?></p>
327
  <?php foreach( $EM_Booking->notes as $note ):
328
+ $user = new EM_Person($note['author']);
329
  ?>
330
  <div>
331
+ <?php echo date(get_option('date_format'), $note['timestamp']) .' - '. $user->get_name(); ?> <?php _e('wrote','dbem'); ?>:
332
  <p style="background:#efefef; padding:5px;"><?php echo nl2br($note['note']); ?></p>
333
  </div>
334
  <?php endforeach; ?>
339
  </form>
340
  </div>
341
  </div>
342
+ <?php do_action('em_bookings_single_metabox_footer', $EM_Booking); ?>
343
  </div>
344
  </div>
345
  </div>
346
  <br style="clear:both;" />
347
+ <?php do_action('em_bookings_single_footer', $EM_Booking); ?>
348
  </div>
349
  <?php
350
 
354
  * Shows all bookings made by one person.
355
  */
356
  function em_bookings_person(){
357
+ global $EM_Person, $EM_Notices;
358
+ $EM_Person->get_bookings();
359
+ $has_booking = false;
360
+ foreach($EM_Person->get_bookings() as $EM_Booking){
361
+ if($EM_Booking->can_manage('manage_bookings','manage_others_bookings')){
362
+ $has_booking = true;
363
+ }
364
+ }
365
+ if( !$has_booking ){
366
+ ?>
367
+ <div class="wrap"><h2><?php _e('Unauthorized Access','dbem'); ?></h2><p><?php _e('You do not have the rights to manage this event.','dbem'); ?></p></div>
368
+ <?php
369
+ return false;
370
+ }
371
  ?>
372
  <div class='wrap'>
373
  <div id='icon-users' class='icon32'>
375
  </div>
376
  <h2>
377
  <?php _e('Manage Person\'s Booking', 'dbem'); ?>
378
+ <?php if( current_user_can('edit_users') ) : ?>
379
+ <a href="user-edit.php?user_id=<?php echo $EM_Person->ID; ?>" class="button add-new-h2"><?php _e('Edit User','dbem') ?></a>
380
+ <?php endif; ?>
381
  </h2>
382
+ <?php echo $EM_Notices; ?>
383
+ <?php do_action('em_bookings_person_header'); ?>
384
  <div id="poststuff" class="metabox-holder has-right-sidebar">
385
  <div id="post-body">
386
  <div id="post-body-content">
389
  <?php _e ( 'Personal Details', 'dbem' ); ?>
390
  </h3>
391
  <div class="inside">
392
+ <?php echo $EM_Person->display_summary(); ?>
393
  </div>
394
  </div>
395
  </div>
396
  </div>
397
  </div>
398
  <br style="clear:both;" />
399
+ <?php do_action('em_bookings_person_body_1'); ?>
400
  <h3><?php _e('Past And Present Bookings','dbem'); ?></h3>
401
  <?php em_bookings_person_table(); ?>
402
+ <?php do_action('em_bookings_person_footer', $EM_Person); ?>
403
  </div>
404
  <?php
405
  }
406
 
407
+ function em_printable_booking_report() {
408
+ global $EM_Event;
409
+ //check that user can access this page
410
+ if( isset($_GET['page']) && $_GET['page']=='events-manager-bookings' && isset($_GET['action']) && $_GET['action'] == 'bookings_report' && is_object($EM_Event)){
411
+ if( is_object($EM_Event) && !$EM_Event->can_manage('edit_events','edit_others_events') ){
412
+ ?>
413
+ <div class="wrap"><h2><?php _e('Unauthorized Access','dbem'); ?></h2><p><?php _e('You do not have the rights to manage this event.','dbem'); ?></p></div>
414
+ <?php
415
+ return false;
416
+ }
417
+ em_locate_template('templates/bookings-event-printable.php', true);
418
+ die();
419
+ }
420
+ }
421
+ add_action('admin_init', 'em_printable_booking_report');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
422
  ?>
admin/em-categories.php DELETED
@@ -1,177 +0,0 @@
1
- <?php
2
- function em_admin_categories_page() {
3
- global $wpdb, $EM_Category;
4
-
5
- if( !empty($_REQUEST['action']) ){
6
- if( $_REQUEST['action'] == "save") {
7
- // save (add/update) category
8
- if( empty($EM_Category) || !is_object($EM_Category) ){
9
- $EM_Category = new EM_Category(); //blank category
10
- $success_message = __('The category has been added.', 'dbem');
11
- }else{
12
- $success_message = __('The category has been updated.', 'dbem');
13
- }
14
- $EM_Category->get_post();
15
- if ( $EM_Category->validate() ) {
16
- $EM_Category->save(); //FIXME better handling of db write fails when saving category
17
- em_categories_table_layout($success_message);
18
- } else {
19
- ?>
20
- <div id='message' class='error '>
21
- <p>
22
- <strong><?php _e( "Ach, there's a problem here:", "dbem" ) ?></strong><br /><br /><?php echo implode('<br />', $EM_Category->errors); ?>
23
- </p>
24
- </div>
25
- <?php
26
- em_categories_edit_layout();
27
- }
28
- } elseif( $_REQUEST['action'] == "edit" ){
29
- em_categories_edit_layout();
30
- } elseif( $_REQUEST['action'] == "delete" ){
31
- //delelte category
32
- EM_Categories::delete($_REQUEST['categories']);
33
- //FIXME no result verification when deleting various categories
34
- $message = __('Categories Deleted', "dbem" );
35
- em_categories_table_layout($message);
36
- }
37
- }else{
38
- em_categories_table_layout($message);
39
- }
40
- }
41
-
42
- function em_categories_table_layout($message = "") {
43
- $categories = EM_Categories::get();
44
- $destination = get_bloginfo('url')."/wp-admin/admin.php";
45
- ?>
46
- <div class='wrap nosubsub'>
47
- <div id='icon-edit' class='icon32'>
48
- <br/>
49
- </div>
50
- <h2><?php echo __('Categories', 'dbem') ?></h2>
51
-
52
- <?php if($message != "") : ?>
53
- <div id='message' class='updated fade below-h2' style='background-color: rgb(255, 251, 204);'>
54
- <p><?php echo $message ?></p>
55
- </div>
56
- <?php endif; ?>
57
-
58
- <div id='col-container'>
59
- <!-- begin col-right -->
60
- <div id='col-right'>
61
- <div class='col-wrap'>
62
- <form id='bookings-filter' method='post' action='<?php echo get_bloginfo('wpurl') ?>/wp-admin/admin.php?page=events-manager-categories'>
63
- <input type='hidden' name='action' value='delete'/>
64
- <?php if (count($categories)>0) : ?>
65
- <table class='widefat'>
66
- <thead>
67
- <tr>
68
- <th class='manage-column column-cb check-column' scope='col'><input type='checkbox' class='select-all' value='1'/></th>
69
- <th><?php echo __('ID', 'dbem') ?></th>
70
- <th><?php echo __('Name', 'dbem') ?></th>
71
- </tr>
72
- </thead>
73
- <tfoot>
74
- <tr>
75
- <th class='manage-column column-cb check-column' scope='col'><input type='checkbox' class='select-all' value='1'/></th>
76
- <th><?php echo __('ID', 'dbem') ?></th>
77
- <th><?php echo __('Name', 'dbem') ?></th>
78
- </tr>
79
- </tfoot>
80
- <tbody>
81
- <?php foreach ($categories as $EM_Category) : ?>
82
- <tr>
83
- <td><input type='checkbox' class ='row-selector' value='<?php echo $EM_Category->id ?>' name='categories[]'/></td>
84
- <td><a href='<?php echo get_bloginfo('wpurl') ?>/wp-admin/admin.php?page=events-manager-categories&amp;action=edit&amp;category_id=<?php echo $EM_Category->id ?>'><?php echo htmlspecialchars($EM_Category->id, ENT_QUOTES); ?></a></td>
85
- <td><a href='<?php echo get_bloginfo('wpurl') ?>/wp-admin/admin.php?page=events-manager-categories&amp;action=edit&amp;category_id=<?php echo $EM_Category->id ?>'><?php echo htmlspecialchars($EM_Category->name, ENT_QUOTES); ?></a></td>
86
- </tr>
87
- <?php endforeach; ?>
88
- </tbody>
89
-
90
- </table>
91
-
92
- <div class='tablenav'>
93
- <div class='alignleft actions'>
94
- <input class='button-secondary action' type='submit' name='doaction2' value='Delete'/>
95
- <br class='clear'/>
96
- </div>
97
- <br class='clear'/>
98
- </div>
99
- <?php else: ?>
100
- <p><?php echo __('No categories have been inserted yet!', 'dbem'); ?></p>
101
- <?php endif; ?>
102
- </form>
103
- </div>
104
- </div>
105
- <!-- end col-right -->
106
-
107
- <!-- begin col-left -->
108
- <div id='col-left'>
109
- <div class='col-wrap'>
110
- <div class='form-wrap'>
111
- <div id='ajax-response'>
112
- <h3><?php echo __('Add category', 'dbem') ?></h3>
113
- <form name='add' id='add' method='post' action='admin.php?page=events-manager-categories' class='add:the-list: validate'>
114
- <input type='hidden' name='action' value='save' />
115
- <div class='form-field form-required'>
116
- <label for='category_name'><?php echo __('Category name', 'dbem') ?></label>
117
- <input id='category-name' name='category_name' id='category_name' type='text' size='40' />
118
- <p><?php echo __('The name of the category', 'dbem'); ?></p>
119
- </div>
120
- <p class='submit'><input type='submit' class='button' name='submit' value='<?php echo __('Add category', 'dbem') ?>' /></p>
121
- </form>
122
- </div>
123
- </div>
124
- </div>
125
- </div>
126
- <!-- end col-left -->
127
- </div>
128
- </div>
129
- <?php
130
- }
131
-
132
-
133
- function em_categories_edit_layout($message = "") {
134
- global $EM_Category;
135
- if( !is_object($EM_Category) ){
136
- $EM_Category = new EM_Category();
137
- }
138
- //check that user can access this page
139
- if( is_object($EM_Category) && !$EM_Category->can_manage() ){
140
- ?>
141
- <div class="wrap"><h2><?php _e('Unauthorized Access','dbem'); ?></h2><p><?php _e('You do not have the rights to manage this event.','dbem'); ?></p></div>
142
- <?php
143
- return;
144
- }
145
- ?>
146
- <div class='wrap'>
147
- <div id='icon-edit' class='icon32'>
148
- <br/>
149
- </div>
150
-
151
- <h2><?php echo __('Edit category', 'dbem') ?></h2>
152
-
153
- <?php if($message != "") : ?>
154
- <div id='message' class='updated fade below-h2' style='background-color: rgb(255, 251, 204);'>
155
- <p><?php echo $message ?></p>
156
- </div>
157
- <?php endif; ?>
158
-
159
- <div id='ajax-response'></div>
160
-
161
- <form name='editcat' id='editcat' method='post' action='admin.php?page=events-manager-categories' class='validate'>
162
- <input type='hidden' name='action' value='save' />
163
- <input type='hidden' name='category_id' value='<?php echo $EM_Category->id ?>'/>
164
-
165
- <table class='form-table'>
166
- <tr class='form-field form-required'>
167
- <th scope='row' valign='top'><label for='category_name'><?php echo __('Category name', 'dbem') ?></label></th>
168
- <td><input name='category_name' id='category-name' type='text' value='<?php echo $EM_Category->name ?>' size='40' /><br />
169
- <?php echo __('The name of the category', 'dbem') ?></td>
170
- </tr>
171
- </table>
172
- <p class='submit'><input type='submit' class='button-primary' name='submit' value='<?php echo __('Update category', 'dbem') ?>' /></p>
173
- </form>
174
- </div>
175
- <?php
176
- }
177
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
admin/em-docs.php CHANGED
@@ -1,7 +1,8 @@
1
  <?php
2
 
3
  function em_docs_init(){
4
- if( class_exists('EM_Event') ){
 
5
  add_action('wp_head', 'emd_head');
6
  //Generate the docs
7
  global $EM_Documentation;
@@ -12,153 +13,216 @@ function em_docs_init(){
12
  $EM_Documentation = array(
13
  'arguments' => array(
14
  'events' => array(
15
- 'limit' => array( 'default'=>'See the events lists limit option on the settings page.' ),
16
- 'orderby' => array( 'desc'=>'Choose what fields to order your results by. You can supply a single field or multiple comma-seperated fields (e.g. "start_date,name").', 'default'=>'See the event lists ordering option on the settings page.', 'args'=>'name, start_date, start_time, end_date, end_time'),
17
- 'order' => array( 'default'=>'See the event lists ordering option on the settings page.' )
 
 
 
 
 
 
 
 
 
 
 
 
18
  ),
19
  'locations' => array(
20
- 'eventful' => array( 'desc'=>'If set to 1 will only show locations that have at least one event occurring during the scope.', 'default' => 0),
21
- 'eventless' => array( 'desc'=>'If set to 1 will only show locations that have no events occurring during the scope.', 'default' => 0),
22
- 'orderby' => array('desc'=>'Choose what fields to order your results by. You can supply a single field or multiple comma-seperated fields (e.g. "start_date,name").', 'default'=>'name', 'args' => 'name, address, town'),
23
- 'scope' => array( 'default' => 'all')
 
 
 
 
 
24
  ),
25
  'calendar' => array(
26
- 'full' => array( 'desc'=>'If set to 1 it will display a full calendar that shows event names.', 'default' => 0),
27
- 'long_events' => array( 'desc'=>'If set to 1, will show events that last longer than a day.', 'default' => 0),
28
- 'order' => array( 'desc'=>'Same as for events.' ),
29
  'scope' => array( 'default' => 'future')
30
  ),
31
  //The object is commonly shared by all, so entries above overwrite entries here
32
  'general' => array(
33
- 'limit' => array( 'desc'=>'Limits the amount of values returned to this number.', 'default'=>'0 (no limit)'),
34
- 'scope' => array( 'desc'=>'Choose the time frame of events to show. Accepted values are "future", "past" or "all" events. Additionally you can supply dates (in format of YYYY-MM-DD), either single for events on a specific date or two dates seperated by a comma (e.g. 2010-12-25,2010-12-31) for events ocurring between these dates.', 'default'=>'future'),
35
- 'order' => array( 'desc'=>'Indicates the order of the events. Choose between ASC (ascending) and DESC (descending).', 'default'=>'ASC'),
36
- 'orderby' => array( 'desc'=>'Choose what fields to order your results by. You can supply a single field or multiple comma-seperated fields (e.g. "start_date,name"). See specific instances (e.g. events, locations, etc.) for field names.', 'default'=>0),
37
- 'format' => array( 'desc'=>'If you are displaying some information with the shortcode or function (e.g. listing events), you can supply the html and placeholders here.', 'default'=>'The relevant default format will be taken from the settings page.'),
38
- 'event' => array( 'desc'=>'Supply a single id or comma-seperated ids (e.g. "1,2,3") to limit the search to events with these id(s).', 'default'=>0),
39
- 'category' => array( 'desc'=>'Supply a single id or comma-seperated ids (e.g. "1,2,3") to limit the search to events in these categories.', 'default'=>0),
40
- 'location' => array( 'desc'=>'Supply a single id or comma-seperated ids to limit the search to these locations (or events in these locations).', 'default'=>0),
41
- 'offset' => array( 'desc'=>'For example, if you have ten results, if you set this to 5, only the last 5 results will be returned. Useful for pagination.', 'default'=>0),
42
- 'recurrence' => array( 'desc'=>'If set to 1, will show only events that are recurring (i.e. events that are repeated over different dates).', 'default'=>0),
43
- 'recurring' => array( 'desc'=>'If set to 1, will only show recurring event templates. Only useful if you know what you\'re doing, use recurrence if you want events that are recurrences.', 'default'=>0),
44
- 'month' => array( 'desc'=>'If set to a month (1 to 12) only events that start or end during this month/year will be retured. Must be used in conjunction with year', 'default'=>''),
45
- 'year' => array( 'desc'=>'If set to a year (e.g. 2010) only events that start or end during this year/month will be returned. Must be used in conjunction with year', 'default'=>''),
46
- 'array' => array( 'desc'=>'If you supply this as an argument, the returned data will be in an array, no objects (only useful wen using PHP, not shortcodes)', 'default'=>0),
47
- 'pagination' => array('desc'=>'When using a function or shortcode that outputs items (e.g. [events_list] for events, [locations_list] for locations), if the number of items supercede the limit of items to show, setting this to 1 will show page links under the list.', 'default'=>0)
 
48
  )
49
  ),
50
  'placeholders' => array(
51
  'events' => array(
52
  'Event Details' => array(
53
  'placeholders' => array(
54
- '#_NAME' => array( 'desc' => 'Displays the name of the event.' ),
55
- '#_NOTES' => array( 'desc' => 'Shows the description of the event.' ),
56
- '#_EXCERPT' => array( 'desc' => 'If you added a <a href="http://en.support.wordpress.com/splitting-content/more-tag/">more tag</a> to your event description, only the content before this tag will show (currently, no read more link is added).' ),
57
- '#_EVENTID' => array( 'desc' => 'Shows the event\'s corresponding ID number in the database table.' )
 
 
 
 
58
  )
59
- ),
60
- 'Category Details' => array(
61
- 'placeholders' => array(
62
- '#_CATEGORYNAME' => array( 'desc' => 'Shows the category name of the event.' ),
63
- '#_CATEGORYID' => array( 'desc' => 'Shows the category ID of the event.' )
64
- )
65
- ),
66
  'Time' => array(
67
  'desc' => '',
68
  'placeholders' => array(
69
- '#_24HSTARTTIME' => array( 'desc' => 'Displays the start time in a 24 hours format (e.g. 16:30).' ),
70
- '#_24HENDTIME' => array( 'desc' => 'Displays the end time in a 24 hours format (e.g. 18:30).' ),
71
- '#_12HSTARTTIME' => array( 'desc' => 'Displays the start time in a 12 hours format (e.g. 4:30 PM).' ),
72
- '#_12HENDTIME' => array( 'desc' => 'Displays the end time in a 12 hours format (e.g. 6:30 PM).' )
73
  )
74
  ),
75
  'Custom Date/Time Formatting' => array(
76
- 'desc' => 'Events Manager allows extremely flexible date formatting by using <a href="http://www.php.net/manual/en/function.date.php">PHP date syntax format characters</a> along with placeholders.',
77
  'placeholders' => array(
78
- '# or #@' => array( 'desc' => 'Prepend <code>#</code> or <code>#@</code> before a valid PHP date syntax format character to show start and end date/time information respectively (e.g. <code>#F</code> will show the starting month name like "January", #@h shows the end hour).' ),
79
- '#{x} or #@{x}' => array( 'desc' => 'You can also create a date format without prepending # to each character by wrapping a valid php date() format in <code>#{}</code> or <code>#@{}</code> (e.g. <code>#_{d/m/Y}</code>). If there is no end date (or is same as start date), the value is not shown. This is useful if you want to show event end dates only on events that are longer than on day, e.g. <code>#j #M #Y #@_{ \u\n\t\i\l j M Y}</code>.' ),
80
  )
81
  ),
82
  'Links' => array(
83
  'placeholders' => array(
84
- '#_EVENTURL' => array( 'desc' => 'Simply prints the event URL. You can use this placeholder to build your own customised links.' ),
85
- '#_EVENTLINK' => array( 'desc' => 'Displays the event name with a link to the event page.' ),
86
- '#_EDITEVENTLINK' => array( 'desc' => 'Inserts a link to the edit event page, only if a user is logged in and is allowed to edit the event.' )
 
 
87
  )
88
  ),
89
  'Custom Attributes' => array(
90
- 'desc' => 'Events Manager allows you to create dynamic attributes to your events, which act as extra information fields for your events (e.g. "Dress Code"). For more information see <a href="http://wp-events-plugin.com/documentation/categories-and-attributes/">our online documentation</a> for more info on attributes.',
91
  'placeholders' => array(
92
- '#_ATT{key}{alternative text}' => array('desc'=>'This key will appear as an option when adding attributes to your event. The second braces are optional and will appear if the attribute is not defined or left blank for that event.')
 
 
93
  )
94
  ),
95
- 'Bookings/RSVP' => array(
96
- 'desc' => 'These placeholders will only show if RSVP is enabled for the given event and in the events manager settings page. Spaces placeholders will default to 0',
97
  'placeholders' => array(
98
- '#_ADDBOOKINGFORM' => array( 'desc' => 'Adds a form which allows the visitors to register for an event.' ),
99
- '#_REMOVEBOOKINGFORM' => array( 'desc' => 'Adds a form which allows the visitors to remove their booking.' ),
100
- '#_BOOKINGFORM' => array( 'desc' => 'Adds a both booking forms (add and remove).' ),
101
- '#_AVAILABLESPACES' => array( 'desc' => 'Shows available spaces for the event.' ),
102
- '#_BOOKEDSPACES' => array( 'desc' => 'Shows the amount of currently booked seats for the event.' ),
103
- '#_SPACES' => array( 'desc' => 'Shows the total spaces for the event.' )
 
 
 
104
  )
105
  ),
106
  'Contact Details' => array(
107
- 'desc' => 'The values here are taken from the chosen contact for the specific event, or the default contact in the settings page.',
 
 
 
 
 
 
 
 
 
 
 
 
 
 
108
  'placeholders' => array(
109
- '#_CONTACTNAME' => array( 'desc' => 'Name of the contact person for this event (as shown in the dropdown when adding an event).' ),
110
- '#_CONTACTUSERNAME' => array( 'desc' => 'Contact person\'s username.' ),
111
- '#_CONTACTEMAIL' => array( 'desc' => 'E-mail of the contact person for this event.' ),
112
- '#_CONTACTPHONE' => array( 'desc' => 'Phone number of the contact person for this event. Can be set in the user profile page.' ),
113
- '#_CONTACTAVATAR' => array( 'desc' => 'Contact person\'s avatar.' ),
114
- '#_CONTACTPROFILELINK' => array( 'desc' => 'Contact person\'s "Profile" link. Only works with BuddyPress enabled.' ),
115
- '#_CONTACTPROFILEURL' => array( 'desc' => 'Contact person\'s profile url. Only works with BuddyPress enabled.' ),
116
- '#_CONTACTID' => array( 'desc' => 'Contact person\'s wordpress user ID.')
117
  )
118
  ),
 
 
 
 
 
 
 
 
119
  ),
120
  'locations' => array(
121
  'Location Details' => array(
122
  'desc' => '',
123
  'placeholders' => array(
124
- '#_LOCATIONNAME' => array( 'desc' => 'Displays the location name.' ),
125
- '#_LOCATIONADDRESS' => array( 'desc' => 'Displays the address.' ),
126
- '#_LOCATIONTOWN' => array( 'desc' => 'Displays the town.' ),
127
- '#_LOCATIONMAP' => array( 'desc' => 'Displays a google map showing where the event is located (Will not show if maps are disabled in the settings page)' ),
128
- '#_LOCATIONNOTES' => array( 'desc' => 'Shows the location description.' ),
129
- '#_LOCATIONEXCERPT' => array( 'desc' => 'If you added a <a href="http://en.support.wordpress.com/splitting-content/more-tag/">more tag</a> to your location description, only the content before this tag will show (currently, no read more link is added).' ),
130
- '#_LOCATIONIMAGE' => array( 'desc' => 'Shows the location image.' ),
131
- '#_LOCATIONID' => array( 'desc' => 'Displays the location ID number.' )
 
 
 
 
 
 
132
  )
133
  ),
134
  'Links' => array(
135
  'placeholders' => array(
136
- '#_LOCATIONURL' => array( 'desc' => 'Simply prints the location URL. You can use this placeholder to build your own customised links.' ),
137
- '#_LOCATIONLINK' => array( 'desc' => 'Displays the location name with a link to the location page.' )
138
  )
139
  ),
140
  'Related Events' => array(
141
- 'desc' => 'You can show lists of other events that are being held at this location. The formatting of the list is the same as a normal events list.',
142
  'placeholders' => array(
143
- '#_LOCATIONPASTEVENTS' => array( 'desc' => 'Will show a list of all past events at this location.' ),
144
- '#_LOCATIONNEXTEVENTS' => array( 'desc' => 'Will show a list of all future events at this location.' ),
145
- '#_LOCATIONALLEVENTS' => array( 'desc' => 'Will show a list of all events at this location.' )
146
  )
147
  ),
148
  ),
149
  'bookings' => array(
150
  'Booking Person Information' => array(
151
- 'desc' => 'When a specific booking is displayed (on screen and on email), you can use these placeholders to show specific information about the booking. For contact details of the contact of this event, see the events placeholders.',
152
  'placeholders' => array(
153
- '#_BOOKINGNAME' => array( 'desc' => 'Name of person who made the booking.' ),
154
- '#_BOOKINGEMAIL' => array( 'desc' => 'Email of person who made the booking.' ),
155
- '#_BOOKINGPHONE' => array( 'desc' => 'Phone number of person who made the booking.' ),
156
- '#_BOOKINGSPACES' => array( 'desc' => 'Number of spaces the person has booked.' ),
157
- '#_BOOKINGCOMMENT' => array( 'desc' => 'Any specific comments made by the person who made the booking.' )
 
 
 
 
 
 
 
 
 
 
 
 
158
  )
159
  )
160
  ),
161
- )
 
 
162
  );
163
  }
164
  }
@@ -175,7 +239,7 @@ function em_docs_placeholders($atts){
175
  foreach($data as $sectionTitle => $details) : ?>
176
  <div>
177
  <h3><?php echo $sectionTitle; ?></h3>
178
- <?php if($details['desc'] != ''): ?>
179
  <p><?php echo $details['desc']; ?></p>
180
  <?php endif; ?>
181
  <dl>
1
  <?php
2
 
3
  function em_docs_init(){
4
+ global $pagenow;
5
+ if( $pagenow == 'edit.php' && !empty($_GET['page']) && $_GET['page']=='events-manager-help' && class_exists('EM_Event') ){
6
  add_action('wp_head', 'emd_head');
7
  //Generate the docs
8
  global $EM_Documentation;
13
  $EM_Documentation = array(
14
  'arguments' => array(
15
  'events' => array(
16
+ 'search' => array( 'desc'=> __('Do a search for this string within event name, details and location address.', 'dbem') ),
17
+ 'limit' => array( 'desc'=> __('See the events lists limit option on the settings page.', 'dbem') ),
18
+ 'orderby' => array( 'desc'=> __('Choose what fields to order your results by. You can supply a single field or multiple comma-seperated fields (e.g. "start_date,name").', 'dbem'), 'default'=> __('See the event lists ordering option on the settings page.', 'dbem'), 'args'=>'name, start_date, start_time, end_date, end_time'),
19
+ 'order' => array( 'desc'=> __('See the event lists ordering option on the settings page.', 'dbem') ),
20
+ 'bookings' => array( 'desc'=> __('Include only events with bookings enabled. Use \'user\' to show events a logged in user has booked.', 'dbem') ),
21
+ 'status' => array( 'desc' => __('Limit search to events with a spefic status (1 is active, 0 is pending approval)', 'dbem')),
22
+ 'blog' => array( 'desc' => __('Limit search to events created in a specific blog (MultiSite only)', 'dbem')),
23
+ 'group' => array( 'desc' => __('Limit search to events belonging to a specific group id (BuddyPress only). Using \'my\' will show events belonging to groups the logged in user is a member of.', 'dbem')),
24
+ 'town' => array( 'desc'=> __('Search for events in this town (no partial matches, case sensitive).', 'dbem'), 'default' => __('none','dbem')),
25
+ 'state' => array( 'desc'=> __('Search for events in this state (no partial matches, case sensitive).', 'dbem'), 'default' => __('none','dbem')),
26
+ 'region' => array( 'desc'=> __('Search for events in this region (no partial matches, case sensitive).', 'dbem'), 'default' => __('none','dbem')),
27
+ 'country' => array( 'desc'=> __('Search for events in this country (no partial matches, case sensitive).', 'dbem'), 'default' => __('none','dbem')),
28
+ 'postcode' => array( 'desc'=> __('Search for events in this postcode (no partial matches, case sensitive).', 'dbem'), 'default' => __('none','dbem')),
29
+ 'format_header' => array( 'desc' => __('When displaying event lists, you can supply specific HTML to replace the default header from the settings page.', 'dbem')),
30
+ 'format_footer' => array( 'desc' => __('When displaying event lists, you can supply specific HTML to replace the default footer from the settings page.', 'dbem')),
31
  ),
32
  'locations' => array(
33
+ 'eventful' => array( 'desc'=> __('If set to 1 will only show locations that have at least one event occurring during the scope.', 'dbem'), 'default' => 0),
34
+ 'eventless' => array( 'desc'=> __('If set to 1 will only show locations that have no events occurring during the scope.', 'dbem'), 'default' => 0),
35
+ 'orderby' => array('desc'=> __('Choose what fields to order your results by. You can supply a single field or multiple comma-seperated fields (e.g. "start_date,name").', 'dbem'), 'default'=>'name', 'args' => 'name, address, town'),
36
+ 'scope' => array( 'default' => 'all'),
37
+ 'town' => array( 'desc'=> __('Search for locations in this town (no partial matches, case sensitive).', 'dbem'), 'default' => __('none','dbem')),
38
+ 'state' => array( 'desc'=> __('Search for locations in this state (no partial matches, case sensitive).', 'dbem'), 'default' => __('none','dbem')),
39
+ 'region' => array( 'desc'=> __('Search for locations in this region (no partial matches, case sensitive).', 'dbem'), 'default' => __('none','dbem')),
40
+ 'country' => array( 'desc'=> __('Search for locations in this country (no partial matches, case sensitive).', 'dbem'), 'default' => __('none','dbem')),
41
+ 'postcode' => array( 'desc'=> __('Search for locations in this postcode (no partial matches, case sensitive).', 'dbem'), 'default' => __('none','dbem'))
42
  ),
43
  'calendar' => array(
44
+ 'full' => array( 'desc'=> __('If set to 1 it will display a full calendar that shows event names.', 'dbem'), 'default' => 0),
45
+ 'long_events' => array( 'desc'=> __('If set to 1, will show events that last longer than a day.', 'dbem'), 'default' => 0),
46
+ 'order' => array( 'desc'=> __('Same as for events.', 'dbem') ),
47
  'scope' => array( 'default' => 'future')
48
  ),
49
  //The object is commonly shared by all, so entries above overwrite entries here
50
  'general' => array(
51
+ 'limit' => array( 'desc'=> __('Limits the amount of values returned to this number.', 'dbem'), 'default'=>'0 (no limit)'),
52
+ 'scope' => array( 'desc'=> __('Choose the time frame of events to show. Accepted values are "future", "past", "today", "tomorrow", "month", "next-month", "1-months", "2-months", "3-months", "6-months", "12-months" or "all" events. Additionally you can supply dates (in format of YYYY-MM-DD), either single for events on a specific date or two dates seperated by a comma (e.g. 2010-12-25,2010-12-31) for events ocurring between these dates.', 'dbem'), 'default'=>'future'),
53
+ 'order' => array( 'desc'=> __('Indicates the order of the events. Choose between ASC (ascending) and DESC (descending).', 'dbem'), 'default'=>'ASC'),
54
+ 'orderby' => array( 'desc'=> __('Choose what fields to order your results by. You can supply a single field or multiple comma-seperated fields (e.g. "start_date,name"). See specific instances (e.g. events, locations, etc.) for field names.', 'dbem'), 'default'=>0),
55
+ 'format' => array( 'desc'=> __('If you are displaying some information with the shortcode or function (e.g. listing events), you can supply the html and placeholders here.', 'dbem'), 'default'=> __('The relevant default format will be taken from the settings page.', 'dbem')),
56
+ 'event' => array( 'desc'=> __('Supply a single id or comma-seperated ids (e.g. "1,2,3") to limit the search to events with these id(s).', 'dbem'), 'default'=>0),
57
+ 'category' => array( 'desc'=> __('Supply a single id or comma-seperated ids (e.g. "1,2,3") to limit the search to events in these categories.', 'dbem'), 'default'=>0),
58
+ 'location' => array( 'desc'=> __('Supply a single id or comma-seperated ids to limit the search to these locations (or events in these locations).', 'dbem'), 'default'=>0),
59
+ 'offset' => array( 'desc'=> __('For example, if you have ten results, if you set this to 5, only the last 5 results will be returned. Useful for pagination.', 'dbem'), 'default'=>0),
60
+ 'recurrence' => array( 'desc'=> __('If set to 1, will show only events that are recurring (i.e. events that are repeated over different dates).', 'dbem'), 'default'=>0),
61
+ 'recurring' => array( 'desc'=> __('If set to 1, will only show recurring event templates. Only useful if you know what you\'re doing, use recurrence if you want events that are recurrences.', 'dbem'), 'default'=>0),
62
+ 'month' => array( 'desc'=> __('If set to a month (1 to 12) only events that start or end during this month/year will be retured. Must be used in conjunction with year and does not work as intended if used with scope.', 'dbem'), 'default'=>''),
63
+ 'year' => array( 'desc'=> __('If set to a year (e.g. 2010) only events that start or end during this year/month will be returned. Does not work as intended if used with scope.', 'dbem'), 'default'=>''),
64
+ 'array' => array( 'desc'=> __('If you supply this as an argument, the returned data will be in an array, no objects (only useful wen using PHP, not shortcodes)', 'dbem'), 'default'=>0),
65
+ 'pagination' => array('desc'=> __('When using a function or shortcode that outputs items (e.g. [events_list] for events, [locations_list] for locations), if the number of items supercede the limit of items to show, setting this to 1 will show page links under the list.', 'dbem'), 'default'=>0),
66
+ 'owner' => array('desc'=> __('Limits returned results to a specific owner, identified by their usaer id (e.g. list events or locations owned by user)', 'dbem'), 'default'=>0)
67
  )
68
  ),
69
  'placeholders' => array(
70
  'events' => array(
71
  'Event Details' => array(
72
  'placeholders' => array(
73
+ '#_NAME' => array( 'desc' => __('Displays the name of the event.', 'dbem') ),
74
+ '#_NOTES' => array( 'desc' => __('Shows the description of the event.', 'dbem') ),
75
+ '#_EXCERPT' => array( 'desc' => __('If you added a <a href="http://en.support.wordpress.com/splitting-content/more-tag/">more tag</a> to your event description, only the content before this tag will show (currently, no read more link is added).', 'dbem') ),
76
+ '#_EVENTID' => array( 'desc' => __('Shows the event corresponding ID number in the database table.', 'dbem') ),
77
+ '#_EVENTIMAGE' => array( 'desc' => __('Shows the event image, if available.', 'dbem') ),
78
+ '#_EVENTIMAGE{x,y}' => array( 'desc' => __('Shows the event image thumbnail, x and y are width and height respectively, both being numbers e.g. <code>#_EVENTIMAGE{100,100}</code>', 'dbem') ),
79
+ '#_EVENTIMAGEURL' => array( 'desc' => __('Shows the event image url, if available.', 'dbem') ),
80
+ '#_CATEGORIES' => array( 'desc' => __('Shows a list of category links this event belongs to.', 'dbem') ),
81
  )
82
+ ),
 
 
 
 
 
 
83
  'Time' => array(
84
  'desc' => '',
85
  'placeholders' => array(
86
+ '#_24HSTARTTIME' => array( 'desc' => __('Displays the start time in a 24 hours format (e.g. 16:30).', 'dbem') ),
87
+ '#_24HENDTIME' => array( 'desc' => __('Displays the end time in a 24 hours format (e.g. 18:30).', 'dbem') ),
88
+ '#_12HSTARTTIME' => array( 'desc' => __('Displays the start time in a 12 hours format (e.g. 4:30 PM).', 'dbem') ),
89
+ '#_12HENDTIME' => array( 'desc' => __('Displays the end time in a 12 hours format (e.g. 6:30 PM).', 'dbem') )
90
  )
91
  ),
92
  'Custom Date/Time Formatting' => array(
93
+ 'desc' => __('Events Manager allows extremely flexible date formatting by using <a href="http://www.php.net/manual/en/function.date.php">PHP date syntax format characters</a> along with placeholders.', 'dbem'),
94
  'placeholders' => array(
95
+ '# or #@' => array( 'desc' => __('Prepend <code>#</code> or <code>#@</code> before a valid PHP date syntax format character to show start and end date/time information respectively (e.g. <code>#F</code> will show the starting month name like "January", #@h shows the end hour).', 'dbem') ),
96
+ '#{x} or #@{x}' => array( 'desc' => __('You can also create a date format without prepending # to each character by wrapping a valid php date() format in <code>#{}</code> or <code>#@{}</code> (e.g. <code>#_{d/m/Y}</code>). If there is no end date (or is same as start date), the value is not shown. This is useful if you want to show event end dates only on events that are longer than on day, e.g. <code>#j #M #Y #@_{ \u\n\t\i\l j M Y}</code>.', 'dbem') ),
97
  )
98
  ),
99
  'Links' => array(
100
  'placeholders' => array(
101
+ '#_EVENTURL' => array( 'desc' => __('Simply prints the event URL. You can use this placeholder to build your own customised links.', 'dbem') ),
102
+ '#_EVENTIMAGEURL' => array( 'desc' => __('Shows the event image url, if available.', 'dbem') ),
103
+ '#_EVENTLINK' => array( 'desc' => __('Displays the event name with a link to the event page.', 'dbem') ),
104
+ '#_EDITEVENTLINK' => array( 'desc' => __('Inserts a link to the admin or buddypress (if activated) edit event page, only if a user is logged in and is allowed to edit the event.', 'dbem') ),
105
+ '#_EDITEVENTURL' => array( 'desc' => __('Inserts a url to the admin or buddypress (if activated) edit event page, only if a user is logged in and is allowed to edit the event.', 'dbem') )
106
  )
107
  ),
108
  'Custom Attributes' => array(
109
+ 'desc' => __('Events Manager allows you to create dynamic attributes to your events, which act as extra information fields for your events (e.g. "Dress Code"). For more information see <a href="http://wp-events-plugin.com/documentation/categories-and-attributes/">our online documentation</a> for more info on attributes.', 'dbem'),
110
  'placeholders' => array(
111
+ '#_ATT{key}' => array('desc'=> __('This key will appear as an option when adding attributes to your event.', 'dbem')),
112
+ '#_ATT{key}{alternative text}' => array('desc'=> __('This key will appear as an option when adding attributes to your event. The text in the second braces will appear if the attribute is not defined or left blank for that event.', 'dbem')),
113
+ '#_ATT{key}{option 1|option 2|option 3|etc.}' => array('desc'=> __('This key will appear as an option when adding attributes to your event. The second braces are optional and will use a select box with these values as input. If no valid value is defined, the first option is used.', 'dbem')),
114
  )
115
  ),
116
+ 'Bookings' => array(
117
+ 'desc' => __('These placeholders will only show if bookings are enabled for the given event and in the events manager settings page. Spaces placeholders will default to 0', 'dbem'),
118
  'placeholders' => array(
119
+ '#_BOOKINGFORM' => array( 'desc' => __('Adds a booking forms for this event.', 'dbem') ),
120
+ '#_AVAILABLESPACES' => array( 'desc' => __('Shows available spaces for the event.', 'dbem') ),
121
+ '#_BOOKEDSPACES' => array( 'desc' => __('Shows the amount of currently booked spaces for the event.', 'dbem') ),
122
+ '#_PENDINGSPACES' => array( 'desc' => __('Shows the amount of pending spaces for the event.', 'dbem') ),
123
+ '#_SPACES' => array( 'desc' => __('Shows the total spaces for the event.', 'dbem') ),
124
+ '#_ATTENDEES' => array( 'desc' => __('Shows the list of user avatars attending events.', 'dbem') ),
125
+ '#_BOOKINGBUTTON' => array( 'desc' => __('A single button that will appear to logged in users, if they click on it, they apply for a booking. This button will only display if there is one ticket.', 'dbem') ),
126
+ '#_BOOKINGSURL' => array( 'desc' => __('Shows the url to the admin or buddypress (if activated) bookings management page for this event. Only shown if user is logged in and able to manage bookings.', 'dbem') ),
127
+ '#_BOOKINGSLINK' => array( 'desc' => __('Shows a link to the admin or buddypress (if activated) bookings management page for this event. Only shown if user is logged in and able to manage bookings.', 'dbem') )
128
  )
129
  ),
130
  'Contact Details' => array(
131
+ 'desc' => __('The values here are taken from the chosen contact for the specific event, or the default contact in the settings page.', 'dbem'),
132
+ 'placeholders' => array(
133
+ '#_CONTACTNAME' => array( 'desc' => __('Name of the contact person for this event (as shown in the dropdown when adding an event).', 'dbem') ),
134
+ '#_CONTACTUSERNAME' => array( 'desc' => __('Contact person\'s username.', 'dbem') ),
135
+ '#_CONTACTEMAIL' => array( 'desc' => __('E-mail of the contact person for this event.', 'dbem') ),
136
+ '#_CONTACTPHONE' => array( 'desc' => __('Phone number of the contact person for this event. Can be set in the user profile page.', 'dbem') ),
137
+ '#_CONTACTAVATAR' => array( 'desc' => __('Contact person\'s avatar.', 'dbem') ),
138
+ '#_CONTACTPROFILELINK' => array( 'desc' => __('Contact person\'s "Profile" link. Only works with BuddyPress enabled.', 'dbem') ),
139
+ '#_CONTACTPROFILEURL' => array( 'desc' => __('Contact person\'s profile url. Only works with BuddyPress enabled.', 'dbem') ),
140
+ '#_CONTACTID' => array( 'desc' => __('Contact person\'s WordPress user ID.', 'dbem'))
141
+ )
142
+ ),
143
+ ),
144
+ 'categories' => array(
145
+ 'Category Details' => array(
146
  'placeholders' => array(
147
+ '#_CATEGORYNAME' => array( 'desc' => __('Shows the category name of the event.', 'dbem') ),
148
+ '#_CATEGORYID' => array( 'desc' => __('Shows the category ID of the event.', 'dbem') ),
149
+ '#_CATEGORYIMAGE' => array( 'desc' => __('Shows the event image, if available.', 'dbem') ),
150
+ '#_CATEGORYIMAGE{x,y}' => array( 'desc' => __('Shows the category image thumbnail, x and y are width and height respectively, both being numbers e.g. <code>#_CATEGORYIMAGE{100,100}</code>', 'dbem') ),
151
+ '#_CATEGORYIMAGEURL' => array( 'desc' => __('Shows the category image url, if available.', 'dbem') ),
152
+ '#_CATEGORYNOTES' => array( 'desc' => __('Shows the location description.', 'dbem') )
 
 
153
  )
154
  ),
155
+ 'Related Events' => array(
156
+ 'desc' => __('You can show lists of other events belonging to this category. The formatting of the list is the same as a normal events list.', 'dbem'),
157
+ 'placeholders' => array(
158
+ '#_CATEGORYPASTEVENTS' => array( 'desc' => __('Will show a list of all past events at this category.', 'dbem') ),
159
+ '#_CATEGORYNEXTEVENTS' => array( 'desc' => __('Will show a list of all future events at this category.', 'dbem') ),
160
+ '#_CATEGORYALLEVENTS' => array( 'desc' => __('Will show a list of all events at this category.', 'dbem') )
161
+ )
162
+ )
163
  ),
164
  'locations' => array(
165
  'Location Details' => array(
166
  'desc' => '',
167
  'placeholders' => array(
168
+ '#_LOCATIONID' => array( 'desc' => __('Displays the location ID number.', 'dbem') ),
169
+ '#_LOCATIONNAME' => array( 'desc' => __('Displays the location name.', 'dbem') ),
170
+ '#_LOCATIONADDRESS' => array( 'desc' => __('Displays the address.', 'dbem') ),
171
+ '#_LOCATIONTOWN' => array( 'desc' => __('Displays the town.', 'dbem') ),
172
+ '#_LOCATIONSTATE' => array( 'desc' => __('Displays the state/county.', 'dbem') ),
173
+ '#_LOCATIONPOSTCODE' => array( 'desc' => __('Displays the postcode.', 'dbem') ),
174
+ '#_LOCATIONREGION' => array( 'desc' => __('Displays the region.', 'dbem') ),
175
+ '#_LOCATIONCOUNTRY' => array( 'desc' => __('Displays the country.', 'dbem') ),
176
+ '#_LOCATIONMAP' => array( 'desc' => __('Displays a google map showing where the event is located (Will not show if maps are disabled in the settings page)', 'dbem') ),
177
+ '#_LOCATIONNOTES' => array( 'desc' => __('Shows the location description.', 'dbem') ),
178
+ '#_LOCATIONEXCERPT' => array( 'desc' => __('If you added a <a href="http://en.support.wordpress.com/splitting-content/more-tag/">more tag</a> to your location description, only the content before this tag will show (currently, no read more link is added).', 'dbem') ),
179
+ '#_LOCATIONIMAGE' => array( 'desc' => __('Shows the location image.', 'dbem') ),
180
+ '#_LOCATIONIMAGE{x,y}' => array( 'desc' => __('Shows the location image thumbnail, x and y are width and height respectively, both being numbers e.g. <code>#_LOCATIONIMAGE{100,100}</code>', 'dbem') ),
181
+ '#_LOCATIONIMAGEURL' => array( 'desc' => __('Shows the cattegory image url, if available.', 'dbem') )
182
  )
183
  ),
184
  'Links' => array(
185
  'placeholders' => array(
186
+ '#_LOCATIONURL' => array( 'desc' => __('Simply prints the location URL. You can use this placeholder to build your own customised links.', 'dbem') ),
187
+ '#_LOCATIONLINK' => array( 'desc' => __('Displays the location name with a link to the location page.', 'dbem') )
188
  )
189
  ),
190
  'Related Events' => array(
191
+ 'desc' => __('You can show lists of other events that are being held at this location. The formatting of the list is the same as a normal events list.', 'dbem'),
192
  'placeholders' => array(
193
+ '#_LOCATIONPASTEVENTS' => array( 'desc' => __('Will show a list of all past events at this location.', 'dbem') ),
194
+ '#_LOCATIONNEXTEVENTS' => array( 'desc' => __('Will show a list of all future events at this location.', 'dbem') ),
195
+ '#_LOCATIONALLEVENTS' => array( 'desc' => __('Will show a list of all events at this location.', 'dbem') )
196
  )
197
  ),
198
  ),
199
  'bookings' => array(
200
  'Booking Person Information' => array(
201
+ 'desc' => __('When a specific booking is displayed (on screen and on email), you can use these placeholders to show specific information about the booking. For contact details of the contact of this event, see the events placeholders.', 'dbem'),
202
  'placeholders' => array(
203
+ '#_BOOKINGNAME' => array( 'desc' => __('Name of person who made the booking.', 'dbem') ),
204
+ '#_BOOKINGEMAIL' => array( 'desc' => __('Email of person who made the booking.', 'dbem') ),
205
+ '#_BOOKINGPHONE' => array( 'desc' => __('Phone number of person who made the booking.', 'dbem') ),
206
+ '#_BOOKINGSPACES' => array( 'desc' => __('Number of spaces the person has booked.', 'dbem') ),
207
+ '#_BOOKINGCOMMENT' => array( 'desc' => __('Any specific comments made by the person who made the booking.', 'dbem') ),
208
+ '#_BOOKINGTICKETNAME' => array( 'desc' => __('Name of the ticket booked. Useful in single ticket mode, if multiple tickets are booked a random ticket is used.', 'dbem') ),
209
+ '#_BOOKINGTICKETDESCRIPTION' => array( 'desc' => __('Description of the ticket booked. Useful in single ticket mode, if multiple tickets are booked a random ticket is used.', 'dbem') ),
210
+ '#_BOOKINGTICKETPRICE' => array( 'desc' => __('Booked ticket price with currency symbol (e.g. $ 10.00). Useful in single ticket mode, if multiple tickets are booked a random ticket is used.', 'dbem') ),
211
+ '#_BOOKINGTICKETS' => array( 'desc' => __('A list of booked tickets. You can modify this by using template files and modifying templates/emails/bookingtickets.php', 'dbem') ),
212
+ '#_BOOKINGFORMCUSTOM{field_id}' => array( 'desc' => sprintf(__('(<a href="%s">pro only</a>) Shows booking form custom fields. The field_id value must match that of your custom booking form field.', 'dbem'),'http://wp-events-plugin.com/upgrade/') ),
213
+ '#_BOOKINGFORMCUSTOMREG{field_id}' => array( 'desc' => sprintf(__('(<a href="%s">pro only</a>) Shows booking form custom fields that are used for guest user registration. The field_id value must match that of your custom booking form field.', 'dbem'),'http://wp-events-plugin.com/upgrade/') )
214
+ )
215
+ ),
216
+ 'Links' => array(
217
+ 'desc' => __('People are able to manage their bookings. Below are some placeholder which automatically provides correctly formatted urls', 'dbem'),
218
+ 'placeholders' => array(
219
+ '#_BOOKINGLISTURL' => array( 'desc' => __('URL to page showing that users booked events.', 'dbem') )
220
  )
221
  )
222
  ),
223
+ ),
224
+ //TODO add capabilites explanations
225
+ 'capabilities' => array()
226
  );
227
  }
228
  }
239
  foreach($data as $sectionTitle => $details) : ?>
240
  <div>
241
  <h3><?php echo $sectionTitle; ?></h3>
242
+ <?php if( !empty($details['desc']) ): ?>
243
  <p><?php echo $details['desc']; ?></p>
244
  <?php endif; ?>
245
  <dl>
admin/em-event.php DELETED
@@ -1,627 +0,0 @@
1
- <?php
2
- function em_admin_event_actions(){
3
- if( current_user_can(EM_MIN_CAPABILITY) && !empty($_GET['page']) && $_GET['page'] == 'events-manager-event' && !empty($_REQUEST ['action']) ){
4
- global $wpdb;
5
- global $EM_Event;
6
-
7
- //if dealing with new event, we still want an event object
8
- if( !is_object($EM_Event) ){
9
- $EM_Event = new EM_Event();
10
- }
11
-
12
- // UPDATE or CREATE action
13
- if ($_REQUEST['action'] == 'save') {
14
- $validation = $EM_Event->get_post();
15
- if ( $validation ) { //EM_Event gets the event if submitted via POST and validates it (safer than to depend on JS)
16
- //Save
17
- if( $EM_Event->save() ) {
18
- $page = !empty($_REQUEST['pno']) ? $_REQUEST['pno']:'';
19
- $scope = !empty($_REQUEST['scope']) ? $_REQUEST['scope']:'';
20
- wp_redirect( get_bloginfo('wpurl').'/wp-admin/admin.php?page=events-manager&p='.$page.'&scope='.$scope.'&message='.urlencode($EM_Event->feedback_message));
21
- }
22
- }//errors added automatically to event global object
23
- }
24
-
25
- //Copy the event
26
- if ($_REQUEST['action'] == 'duplicate') {
27
- global $EZSQL_ERROR;
28
- $EM_Event = $EM_Event->duplicate();
29
- if( $EM_Event === false ){
30
- $redirect_url = em_add_get_params($_SERVER['HTTP_REFERER'], array('error' => __('There was an error duplicating the event. Try again maybe?', 'dbem'), 'message'=>''), false);
31
- wp_redirect($redirect_url);
32
- }else{
33
- $page = !empty($_REQUEST['pno']) ? $_REQUEST['pno']:'';
34
- $scope = !empty($_REQUEST['scope']) ? $_REQUEST['scope']:'';
35
- wp_redirect( get_bloginfo('wpurl').'/wp-admin/admin.php?page=events-manager-event&event_id='.$EM_Event->id.'&p='.$page.'&scope='.$scope.'&message='.urlencode($EM_Event->feedback_message));
36
- }
37
- }
38
- }
39
- }
40
- add_action('admin_init', 'em_admin_event_actions');
41
-
42
- /**
43
- * Generates Event Admin page, for adding and updating a single (or recurring) event.
44
- * @param $title
45
- * @return null
46
- */
47
- function em_admin_event_page() {
48
- global $EM_Event, $current_user;
49
- global $localised_date_formats;
50
-
51
- //check that user can access this page
52
- if( is_object($EM_Event) && !$EM_Event->can_manage() ){
53
- ?>
54
- <div class="wrap"><h2><?php _e('Unauthorized Access','dbem'); ?></h2><p><?php _e('You do not have the rights to manage this event.','dbem'); ?></p></div>
55
- <?php
56
- return false;
57
- }
58
-
59
- if( is_object($EM_Event) && $EM_Event->id > 0 ){
60
- if($EM_Event->is_recurring()){
61
- $title = __( "Reschedule", 'dbem' )." '{$EM_Event->name}'";
62
- }else{
63
- $title = __ ( "Edit Event", 'dbem' ) . " '" . $EM_Event->name . "'";
64
- }
65
- } else {
66
- $EM_Event = ( is_object($EM_Event) && get_class($EM_Event) == 'EM_Event') ? $EM_Event : new EM_Event();
67
- $title = __ ( "Insert New Event", 'dbem' );
68
- //Give a default location & category
69
- $default_cat = get_option('dbem_default_category');
70
- $default_loc = get_option('dbem_default_location');
71
- if( is_numeric($default_cat) && $default_cat > 0 ){
72
- $EM_Event->category_id = $default_cat;
73
- $EM_Event->category = new EM_Category($default_cat);
74
- }
75
- if( is_numeric($default_loc) && $default_loc > 0 && ( empty($EM_Event->location->id) && empty($EM_Event->location->name) && empty($EM_Event->location->address) && empty($EM_Event->location->town) ) ){
76
- $EM_Event->location_id = $default_loc;
77
- $EM_Event->location = new EM_Location($default_loc);
78
- }
79
- }
80
-
81
- $use_select_for_locations = get_option('dbem_use_select_for_locations');
82
- // change prefix according to event/recurrence
83
- $pref = "event_";
84
-
85
- $locale_code = substr ( get_locale (), 0, 2 );
86
- $localised_date_format = $localised_date_formats[$locale_code];
87
-
88
- //FIXME time useage is very flimsy imho
89
- $hours_locale_regexp = "H:i";
90
- // Setting 12 hours format for those countries using it
91
- if (preg_match ( "/en|sk|zh|us|uk/", $locale_code ))
92
- $hours_locale_regexp = "h:iA";
93
-
94
- $days_names = array (1 => __ ( 'Mon' ), 2 => __ ( 'Tue' ), 3 => __ ( 'Wed' ), 4 => __ ( 'Thu' ), 5 => __ ( 'Fri' ), 6 => __ ( 'Sat' ), 0 => __ ( 'Sun' ) );
95
- ?>
96
- <?php if ( count($EM_Event->errors) > 0 || !empty($_GET['error']) ) : ?>
97
- <div id='message' class='error '>
98
- <p>
99
- <?php if( count($EM_Event->errors) ){ ?>
100
- <strong><?php echo __( "Ach, there's a problem here:", "dbem" ) ?></strong><br /><br />
101
- <?php echo implode('<br />', $EM_Event->errors); ?>
102
- <?php } else { echo $_GET['error']; } ?>
103
- </p>
104
- </div>
105
- <?php endif; ?>
106
- <?php if ( !empty($EM_Event->feedback_message) || !empty($_GET['message']) ) : ?>
107
- <div id='message' class='updated fade'>
108
- <p><?php echo !empty($EM_Event->feedback_message) ? $EM_Event->feedback_message : $_GET['message']; ?></p>
109
- </div>
110
- <?php endif; ?>
111
- <form id="event-form" method="post" action="">
112
- <div class="wrap">
113
- <div id="icon-events" class="icon32"><br /></div>
114
- <h2><?php echo $title; ?></h2>
115
- <?php if ( $EM_Event->is_recurrence() || $EM_Event->is_recurring() ) : ?>
116
- <p id='recurrence_warning'>
117
- <?php
118
- //TODO better warning system when changing a recurring event (e.g. when removing recurrences).
119
- if ( $EM_Event->is_recurring() ) {
120
- _e ( 'WARNING: This is a recurring event.', 'dbem' );
121
- echo "<br />";
122
- _e ( 'Modifying these data all the events linked to this recurrence will be rescheduled', 'dbem' );
123
- echo " ";
124
- _e ( 'and all booking information will be deleted!', 'dbem' );
125
- } elseif ( $EM_Event->is_recurrence() ) {
126
- //TODO Terminology confusing with methods, maybe worth changing?
127
- _e ( 'WARNING: This is a recurrence.', 'dbem' );
128
- echo "<br />";
129
- _e ( 'If you change these data and save, this will become an independent event.', 'dbem' );
130
- }
131
- ?>
132
- </p>
133
- <?php endif; ?>
134
- <div id="poststuff" class="metabox-holder has-right-sidebar">
135
- <!-- SIDEBAR -->
136
- <div id="side-info-column" class='inner-sidebar'>
137
- <div id='side-sortables'>
138
- <?php if(get_option('dbem_recurrence_enabled')) : ?>
139
- <!-- START recurrence postbox -->
140
- <div class="postbox ">
141
- <div class="handlediv" title="Fare clic per cambiare."><br />
142
- </div>
143
- <h3 class='hndle'><span>
144
- <?php _e ( "Recurrence", 'dbem' ); ?>
145
- </span></h3>
146
- <div class="inside">
147
- <?php //TODO add js warning if rescheduling, since all bookings are deleted ?>
148
- <?php if ( !$EM_Event->id || $EM_Event->is_recurring() ) : ?>
149
- <p>
150
- <input id="event-recurrence" type="checkbox" name="repeated_event" value="1" <?php echo ( $EM_Event->is_recurring() ) ? 'checked="checked"':'' ; ?> />
151
- <?php _e ( 'Repeated event', 'dbem' ); ?>
152
- </p>
153
- <div id="event_recurrence_pattern">
154
- <p>
155
- Frequency:
156
- <select id="recurrence-frequency" name="recurrence_freq">
157
- <?php
158
- $freq_options = array ("daily" => __ ( 'Daily', 'dbem' ), "weekly" => __ ( 'Weekly', 'dbem' ), "monthly" => __ ( 'Monthly', 'dbem' ) );
159
- em_option_items ( $freq_options, $EM_Event->freq );
160
- ?>
161
- </select>
162
- </p>
163
- <p>
164
- <?php _e ( 'Every', 'dbem' )?>
165
- <input id="recurrence-interval" name='recurrence_interval' size='2' value='<?php echo $EM_Event->interval ; ?>' />
166
- <span class='interval-desc' id="interval-daily-singular">
167
- <?php _e ( 'day', 'dbem' )?>
168
- </span> <span class='interval-desc' id="interval-daily-plural">
169
- <?php _e ( 'days', 'dbem' ) ?>
170
- </span> <span class='interval-desc' id="interval-weekly-singular">
171
- <?php _e ( 'week', 'dbem' )?>
172
- </span> <span class='interval-desc' id="interval-weekly-plural">
173
- <?php _e ( 'weeks', 'dbem' )?>
174
- </span> <span class='interval-desc' id="interval-monthly-singular">
175
- <?php _e ( 'month', 'dbem' )?>
176
- </span> <span class='interval-desc' id="interval-monthly-plural">
177
- <?php _e ( 'months', 'dbem' )?>
178
- </span>
179
- </p>
180
- <p class="alternate-selector" id="weekly-selector">
181
- <?php
182
- $saved_bydays = ($EM_Event->is_recurring()) ? explode ( ",", $EM_Event->byday ) : array();
183
- em_checkbox_items ( 'recurrence_bydays[]', $days_names, $saved_bydays );
184
- ?>
185
- </p>
186
- <p class="alternate-selector" id="monthly-selector">
187
- <?php _e ( 'Every', 'dbem' )?>
188
- <select id="monthly-modifier" name="recurrence_byweekno">
189
- <?php
190
- $weekno_options = array ("1" => __ ( 'first', 'dbem' ), '2' => __ ( 'second', 'dbem' ), '3' => __ ( 'third', 'dbem' ), '4' => __ ( 'fourth', 'dbem' ), '-1' => __ ( 'last', 'dbem' ) );
191
- em_option_items ( $weekno_options, $EM_Event->byweekno );
192
- ?>
193
- </select>
194
- <select id="recurrence-weekday" name="recurrence_byday">
195
- <?php em_option_items ( $days_names, $EM_Event->byday ); ?>
196
- </select>
197
- &nbsp;
198
- </p>
199
- </div>
200
- <p id="recurrence-tip">
201
- <?php _e ( 'Check if your event happens more than once according to a regular pattern', 'dbem' )?>
202
- </p>
203
- <?php elseif( $EM_Event->is_recurrence() ) : ?>
204
- <p>
205
- <?php echo $EM_Event->get_recurrence_description(); ?>
206
- <br />
207
- <a href="<?php bloginfo ( 'wpurl' )?>/wp-admin/admin.php?page=events-manager-event&amp;event_id=<?php echo $EM_Event->recurrence_id; ?>">
208
- <?php _e ( 'Reschedule', 'dbem' ); ?>
209
- </a>
210
- <input type="hidden" name="recurrence_id" value="<?php echo $EM_Event->recurrence_id; ?>" />
211
- </p>
212
- <?php else : ?>
213
- <p><?php _e ( 'This is\'t a recurrent event', 'dbem' ) ?></p>
214
- <?php endif; ?>
215
- </div>
216
- </div>
217
- <!-- END recurrence postbox -->
218
- <?php endif; ?>
219
- <?php if(get_option('dbem_rsvp_enabled')) : ?>
220
- <!-- START RSVP -->
221
- <?php if ( em_verify_admin() ): ?>
222
- <div class="postbox ">
223
- <div class="handlediv" title="Fare clic per cambiare."><br />
224
- </div>
225
- <h3 class='hndle'><span>
226
- <?php _e ( 'Contact Person', 'dbem' ); ?>
227
- </span></h3>
228
- <div class="inside">
229
- <p><?php _e('Contact','dbem'); ?>
230
- <?php
231
- wp_dropdown_users ( array ('name' => 'event_contactperson_id', 'show_option_none' => __ ( "Select...", 'dbem' ), 'selected' => $EM_Event->contactperson_id ) );
232
- ?>
233
- </p>
234
- </div>
235
- </div>
236
- <?php else: ?>
237
- <input type="hidden" name="event_contactperson_id" value="<?php get_current_user_id() ?>" />
238
- <?php endif; ?>
239
- <div class="postbox ">
240
- <div class="handlediv" title="Fare clic per cambiare."><br />
241
- </div>
242
- <h3 class='hndle'><span><?php _e('RSVP','dbem'); ?></span></h3>
243
- <div class="inside">
244
- <p>
245
- <input id="rsvp-checkbox" name='event_rsvp' value='1' type='checkbox' <?php echo ($EM_Event->rsvp) ? 'checked="checked"' : ''; ?> />
246
- <?php _e ( 'Enable registration for this event', 'dbem' )?>
247
- </p>
248
- <div id='rsvp-data'>
249
- <?php
250
- if ($EM_Event->contactperson_id != NULL){
251
- $selected = $EM_Event->contactperson_id;
252
- }else{
253
- $selected = '0';
254
- }
255
- ?>
256
- <p>
257
- <?php _e ( 'Spaces','dbem' ); ?> :
258
- <input id="seats-input" type="text" name="event_seats" size='5' value="<?php echo $EM_Event->seats ?>" />
259
- </p>
260
- <!-- START RSVP Stats -->
261
- <?php
262
- if ($EM_Event->rsvp ) {
263
- $available_seats = $EM_Event->get_bookings()->get_available_seats();
264
- $booked_seats = $EM_Event->get_bookings()->get_booked_seats();
265
-
266
- if ( count($EM_Event->get_bookings()->bookings) > 0 ) {
267
- ?>
268
- <div class='wrap'>
269
- <p><strong><?php echo __('Available Spaces','dbem').': '.$EM_Event->get_bookings()->get_available_seats(); ?></strong></p>
270
- <p><strong><?php echo __('Confirmed Spaces','dbem').': '.$EM_Event->get_bookings()->get_booked_seats(); ?></strong></p>
271
- <p><strong><?php echo __('Pending Spaces','dbem').': '.$EM_Event->get_bookings()->get_pending_seats(); ?></strong></p>
272
- </div>
273
-
274
- <br class='clear'/>
275
-
276
- <div id='major-publishing-actions'>
277
- <div id='publishing-action'>
278
- <a id='printable' href='<?php echo get_bloginfo('wpurl') . "/wp-admin/admin.php?page=events-manager-bookings&event_id=".$EM_Event->id ?>'><?php _e('manage bookings','dbem')?></a><br />
279
- <a target='_blank' href='<?php echo get_bloginfo('wpurl') . "/wp-admin/admin.php?page=events-manager-bookings&action=bookings_report&event_id=".$EM_Event->id ?>'><?php _e('printable view','dbem')?></a>
280
- <a href='<?php echo get_bloginfo('wpurl') . "/wp-admin/admin.php?page=events-manager-bookings&action=export_csv&event_id=".$EM_Event->id ?>'><?php _e('export csv','dbem')?></a>
281
- <br class='clear'/>
282
- </div>
283
- <br class='clear'/>
284
- </div>
285
- <?php
286
- } else {
287
- ?>
288
- <p><em><?php _e('No responses yet!')?></em></p>
289
- <?php
290
- }
291
- }
292
- ?>
293
- <!-- END RSVP Stats -->
294
- </div>
295
- </div>
296
- </div>
297
- <!-- END RSVP -->
298
- <?php endif; ?>
299
- <?php if(get_option('dbem_categories_enabled')) :?>
300
- <!-- START Categories -->
301
- <div class="postbox ">
302
- <div class="handlediv" title="Fare clic per cambiare."><br />
303
- </div>
304
- <h3 class='hndle'><span>
305
- <?php _e ( 'Category', 'dbem' ); ?>
306
- </span></h3>
307
- <div class="inside">
308
- <?php $categories = EM_Categories::get(array('orderby'=>'category_name')); ?>
309
- <?php if( count($categories) > 0 ): ?>
310
- <p><?php _e ( 'Category:', 'dbem' ); ?>
311
- <select name="event_category_id">
312
- <option value="" <?php echo ($EM_Event->category_id == '') ? "selected='selected'":'' ?>><?php _e('no category','dbem') ?></option>
313
- <?php
314
- foreach ( $categories as $EM_Category ){
315
- $selected = ($EM_Category->id == $EM_Event->category_id) ? "selected='selected'": '';
316
- ?>
317
- <option value="<?php echo $EM_Category->id ?>" <?php echo $selected ?>>
318
- <?php echo $EM_Category->name ?>
319
- </option>
320
- <?php
321
- }
322
- ?>
323
- </select>
324
- </p>
325
- <?php else: ?>
326
- <p><?php sprintf(__('No categories available, <a href="%s">create one here first</a>','dbem'), get_bloginfo('wpurl').'/wp-admin/admin.php?page=events-manager-categories'); ?></p>
327
- <?php endif; ?>
328
- </div>
329
- </div>
330
- <!-- END Categories -->
331
- <?php endif; ?>
332
- </div>
333
- </div>
334
- <!-- END OF SIDEBAR -->
335
- <div id="post-body">
336
- <div id="post-body-content">
337
- <div id="event_name" class="stuffbox">
338
- <h3>
339
- <?php _e ( 'Name', 'dbem' ); ?>
340
- </h3>
341
- <div class="inside">
342
- <input type="text" name="event_name" id="event-name" value="<?php echo htmlspecialchars($EM_Event->name,ENT_QUOTES); ?>" />
343
- <br />
344
- <?php _e ( 'The event name. Example: Birthday party', 'dbem' )?>
345
- </div>
346
- </div>
347
- <div id="event_start_date" class="stuffbox">
348
- <h3 id='event-date-title'>
349
- <?php _e ( 'Event date', 'dbem' ); ?>
350
- </h3>
351
- <h3 id='recurrence-dates-title'>
352
- <?php _e ( 'Recurrence dates', 'dbem' ); ?>
353
- </h3>
354
- <div class="inside">
355
- <input id="localised-date" type="text" name="localised_event_date" style="display: none;" />
356
- <input id="date-to-submit" type="text" name="event_start_date" value="<?php echo $EM_Event->start_date ?>" style="background: #FCFFAA" />
357
- <input id="localised-end-date" type="text" name="localised_event_end_date" style="display: none;" />
358
- <input id="end-date-to-submit" type="text" name="event_end_date" value="<?php echo $EM_Event->end_date ?>" style="background: #FCFFAA" />
359
- <br />
360
- <span id='event-date-explanation'>
361
- <?php
362
- _e ( 'The event date.', 'dbem' );
363
- /* Marcus Begin Edit */
364
- echo " ";
365
- _e ( 'When not reoccurring, this event spans between the beginning and end date.', 'dbem' );
366
- /* Marcus End Edit */
367
- ?>
368
- </span>
369
- <span id='recurrence-dates-explanation'>
370
- <?php _e ( 'The recurrence beginning and end date.', 'dbem' ); ?>
371
- </span>
372
- </div>
373
- </div>
374
- <div id="event_end_day" class="stuffbox">
375
- <h3>
376
- <?php _e ( 'Event time', 'dbem' ); ?>
377
- </h3>
378
- <div class="inside">
379
- <input id="start-time" type="text" size="8" maxlength="8" name="event_start_time" value="<?php echo date( $hours_locale_regexp, strtotime($EM_Event->start_time) ); ?>" />
380
- -
381
- <input id="end-time" type="text" size="8" maxlength="8" name="event_end_time" value="<?php echo date( $hours_locale_regexp, strtotime($EM_Event->end_time) ); ?>" />
382
- <br />
383
- <?php _e ( 'The time of the event beginning and end', 'dbem' )?>.
384
- </div>
385
- </div>
386
- <div id="location_coordinates" class="stuffbox" style='display: none;'>
387
- <h3>
388
- <?php _e ( 'Coordinates', 'dbem' ); ?>
389
- </h3>
390
- <div class="inside">
391
- <input id='location-latitude' name='location_latitude' type='text' value='<?php echo $EM_Event->latitude; ?>' size='15' />
392
- -
393
- <input id='location-longitude' name='location_longitude' type='text' value='<?php echo $EM_Event->longitude; ?>' size='15' />
394
- </div>
395
- </div>
396
- <div id="location_info" class="stuffbox">
397
- <h3>
398
- <?php _e ( 'Location', 'dbem' ); ?>
399
- </h3>
400
- <div class="inside">
401
- <table id="dbem-location-data">
402
- <tr>
403
- <td style="padding-right:20px">
404
- <table>
405
- <?php if($use_select_for_locations) : ?>
406
- <tr>
407
- <th><?php _e('Location:','dbem') ?></th>
408
- <td>
409
- <select name="location-select-id" id='location-select-id' size="1">
410
- <?php
411
- $locations = EM_Locations::get();
412
- foreach($locations as $location) {
413
- $selected = "";
414
- if( is_object($EM_Event->location) ) {
415
- if ($EM_Event->location->id == $location->id)
416
- $selected = "selected='selected' ";
417
- }
418
- ?>
419
- <option value="<?php echo $location->id ?>" title="<?php echo "{$location->latitude},{$location->longitude}" ?>" <?php echo $selected ?>><?php echo $location->name; ?></option>
420
- <?php
421
- }
422
- ?>
423
- </select>
424
- <p><?php _e ( 'The name of the location where the event takes place. You can use the name of a venue, a square, etc', 'dbem' )?></p>
425
- </td>
426
- </tr>
427
- <?php else : ?>
428
- <tr>
429
- <th><?php _e ( 'Name:' )?></th>
430
- <td>
431
- <input id="location-name" type="text" name="location_name" value="<?php echo htmlspecialchars($EM_Event->location->name, ENT_QUOTES); ?>" />
432
- <p><?php _e ( 'Select a location for your event', 'dbem' )?></p>
433
- </td>
434
- </tr>
435
- <tr>
436
- <th><?php _e ( 'Address:' )?>&nbsp;</th>
437
- <td>
438
- <input id="location-address" type="text" name="location_address" value="<?php echo htmlspecialchars($EM_Event->location->address, ENT_QUOTES); ; ?>" />
439
- <p><?php _e ( 'The address of the location where the event takes place. Example: 21, Dominick Street', 'dbem' )?></p>
440
- </td>
441
- </tr>
442
- <tr>
443
- <th><?php _e ( 'Town:' )?>&nbsp;</th>
444
- <td>
445
- <input id="location-town" type="text" name="location_town" value="<?php echo htmlspecialchars($EM_Event->location->town, ENT_QUOTES); ?>" />
446
- <p><?php _e ( 'The town where the location is located. If you\'re using the Google Map integration and want to avoid geotagging ambiguities include the country in the town field. Example: Verona, Italy.', 'dbem' )?></p>
447
- </td>
448
- </tr>
449
- <?php endif; ?>
450
- </table>
451
- </td>
452
- <?php if ( get_option ( 'dbem_gmap_is_active' ) ) : ?>
453
- <td width="400">
454
- <div id='em-map-404' style='width: 400px; vertical-align:middle; text-align: center;'>
455
- <p><em><?php _e ( 'Location not found', 'dbem' ); ?></em></p>
456
- </div>
457
- <div id='em-map' style='width: 400px; height: 300px; display: none;'></div>
458
- </td>
459
- <?php endif; ?>
460
- </tr>
461
- </table>
462
- </div>
463
- </div>
464
- <div id="event_notes" class="postbox">
465
- <h3>
466
- <?php _e ( 'Details', 'dbem' ); ?>
467
- </h3>
468
- <div class="inside">
469
- <div id="<?php echo user_can_richedit() ? 'postdivrich' : 'postdiv'; ?>" class="postarea">
470
- <?php the_editor($EM_Event->notes ); ?>
471
- </div>
472
- <br />
473
- <?php _e ( 'Details about the event', 'dbem' )?>
474
- </div>
475
- </div>
476
-
477
- <?php if(get_option('dbem_attributes_enabled')) : ?>
478
- <div id="event_attributes" class="postbox">
479
- <h3>
480
- <?php _e ( 'Attributes', 'dbem' ); ?>
481
- </h3>
482
- <div class="inside">
483
- <?php
484
- //We also get a list of attribute names and create a ddm list (since placeholders are fixed)
485
- $formats =
486
- get_option ( 'dbem_event_list_item_format' ).
487
- get_option ( 'dbem_event_page_title_format' ).
488
- get_option ( 'dbem_full_calendar_event_format' ).
489
- get_option ( 'dbem_location_baloon_format' ).
490
- get_option ( 'dbem_location_event_list_item_format' ).
491
- get_option ( 'dbem_location_page_title_format' ).
492
- get_option ( 'dbem_map_text_format' ).
493
- get_option ( 'dbem_rss_description_format' ).
494
- get_option ( 'dbem_rss_title_format' ).
495
- get_option ( 'dbem_single_event_format' ).
496
- get_option ( 'dbem_single_location_format' ).
497
- get_option ( 'dbem_placeholders_custom' );
498
- //We now have one long string of formats, get all the attribute placeholders
499
- preg_match_all('/#_ATT\{.+?\}(\{.+?\})?/', $formats, $placeholders);
500
- //Now grab all the unique attributes we can use in our event.
501
- $attributes = array();
502
- foreach($placeholders[0] as $result) {
503
- $attribute = substr( substr($result, 0, strpos($result, '}')), 6 );
504
- if( !in_array($attribute, $attributes) ){
505
- $attributes[] = $attribute ;
506
- }
507
- }
508
- ?>
509
- <div class="wrap">
510
- <?php if( count( $attributes ) > 0 ) : ?>
511
- <h2>Attributes</h2>
512
- <p>Add attributes here</p>
513
- <table class="form-table">
514
- <thead>
515
- <tr valign="top">
516
- <td><strong>Attribute Name</strong></td>
517
- <td><strong>Value</strong></td>
518
- </tr>
519
- </thead>
520
- <tfoot>
521
- <tr valign="top">
522
- <td colspan="3"><a href="#" id="mtm_add_tag">Add new tag</a></td>
523
- </tr>
524
- </tfoot>
525
- <tbody id="mtm_body">
526
- <?php
527
- $count = 1;
528
- if( is_array($EM_Event->attributes) and count($EM_Event->attributes) > 0){
529
- foreach( $EM_Event->attributes as $name => $value){
530
- ?>
531
- <tr valign="top" id="mtm_<?php echo $count ?>">
532
- <td scope="row">
533
- <select name="mtm_<?php echo $count ?>_ref">
534
- <?php
535
- if( !in_array($name, $attributes) ){
536
- echo "<option value='$name'>$name (".__('Not defined in templates', 'dbem').")</option>";
537
- }
538
- foreach( $attributes as $attribute ){
539
- if( $attribute == $name ) {
540
- echo "<option selected='selected'>$attribute</option>";
541
- }else{
542
- echo "<option>$attribute</option>";
543
- }
544
- }
545
- ?>
546
- </select>
547
- <a href="#" rel="<?php echo $count ?>">Remove</a>
548
- </td>
549
- <td>
550
- <input type="text" name="mtm_<?php echo $count ?>_name" value="<?php echo htmlspecialchars($value, ENT_QUOTES); ?>" />
551
- </td>
552
- </tr>
553
- <?php
554
- $count++;
555
- }
556
- }else{
557
- ?>
558
- <tr valign="top" id="mtm_<?php echo $count ?>">
559
- <td scope="row">
560
- <select name="mtm_<?php echo $count ?>_ref">
561
- <?php
562
- foreach( $attributes as $attribute ){
563
- echo "<option>$attribute</option>";
564
- }
565
- ?>
566
- </select>
567
- <a href="#" rel="<?php echo $count ?>">Remove</a>
568
- </td>
569
- <td>
570
- <input type="text" name="mtm_<?php echo $count ?>_name" />
571
- </td>
572
- </tr>
573
- <?php
574
- }
575
- ?>
576
- </tbody>
577
- </table>
578
- <?php else : ?>
579
- <p>
580
- <?php _e('In order to use attributes, you must define some in your templates, otherwise they\'ll never show. Go to Events > Settings to add attribute placeholders.', 'dbem'); ?>
581
- </p>
582
- <script>
583
- jQuery(document).ready(function($){ $('#event_attributes').addClass('closed'); });
584
- </script>
585
- <?php endif; ?>
586
- </div>
587
- </div>
588
- </div>
589
- <?php endif; ?>
590
- </div>
591
- <p class="submit">
592
- <input type="submit" name="events_update" value="<?php _e ( 'Submit Event', 'dbem' ); ?> &raquo;" />
593
- </p>
594
- <input type="hidden" name="p" value="<?php echo ( !empty($_REQUEST['pno']) ) ? $_REQUEST['pno']:''; ?>" /><a>
595
- <input type="hidden" name="scope" value="<?php echo ( !empty($_REQUEST['scope']) ) ? $_REQUEST['scope']:'' ?>" /></a>
596
- <input type="hidden" name="action" value="save" />
597
- </div>
598
- </div>
599
- </div>
600
- </form>
601
- <script type="text/javascript">
602
- jQuery(document).ready( function($) {
603
- <?php if( $EM_Event->is_recurring() ): ?>
604
- //Recurrence Warnings
605
- $('#event_form').submit( function(event){
606
- confirmation = confirm('<?php _e('Are you sure you want to reschedule this recurring event? If you do this, you will lose all booking information and the old recurring events will be deleted.', 'dbem'); ?>');
607
- if( confirmation == false ){
608
- event.preventDefault();
609
- }
610
- });
611
- <?php endif; ?>
612
- <?php if( $EM_Event->rsvp == 1 ): ?>
613
- //RSVP Warning
614
- $('#rsvp-checkbox').click( function(event){
615
- if( !this.checked ){
616
- confirmation = confirm('<?php _e('Are you sure you want to disable bookings? If you do this and save, you will lose all previous bookings. If you wish to prevent further bookings, reduce the number of seats available to the amount of bookings you currently have', 'dbem'); ?>');
617
- if( confirmation == false ){
618
- event.preventDefault();
619
- }
620
- }
621
- });
622
- <?php endif; ?>
623
- });
624
- </script>
625
- <?php
626
- }
627
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
admin/em-events.php DELETED
@@ -1,242 +0,0 @@
1
- <?php
2
-
3
- /**
4
- * Determines whether to show event page or events page, and saves any updates to the event or events
5
- * @return null
6
- */
7
- function em_admin_events_page() {
8
- //TODO Simplify panel for events, use form flags to detect certain actions (e.g. submitted, etc)
9
- global $wpdb;
10
- global $EM_Event;
11
- $action = ( !empty($_GET ['action']) ) ? $_GET ['action']:'';
12
- $order = ( !empty($_GET ['order']) ) ? $_GET ['order']:'ASC';
13
- $limit = ( !empty($_GET['limit']) ) ? $_GET['limit'] : 20;//Default limit
14
- $page = ( !empty($_GET['pno']) ) ? $_GET['pno']:1;
15
- $offset = ( $page > 1 ) ? ($page-1)*$limit : 0;
16
- $scope_names = array (
17
- 'past' => __ ( 'Past events', 'dbem' ),
18
- 'all' => __ ( 'All events', 'dbem' ),
19
- 'future' => __ ( 'Future events', 'dbem' )
20
- );
21
- $scope = ( !empty($_GET ['scope']) && array_key_exists($_GET ['scope'], $scope_names) ) ? $_GET ['scope']:'future';
22
- $selectedEvents = ( !empty($_GET ['events']) ) ? $_GET ['events']:'';
23
-
24
- // DELETE action
25
- if ( $action == 'deleteEvents' && EM_Object::array_is_numeric($selectedEvents) ) {
26
- EM_Events::delete( $selectedEvents );
27
- }
28
-
29
- // No action, only showing the events list
30
- switch ($scope) {
31
- case "past" :
32
- $title = __ ( 'Past Events', 'dbem' );
33
- break;
34
- case "all" :
35
- $title = __ ( 'All Events', 'dbem' );
36
- break;
37
- default :
38
- $title = __ ( 'Future Events', 'dbem' );
39
- $scope = "future";
40
- }
41
- $args = array('scope'=>$scope, 'limit'=>0, 'order'=>$order );
42
-
43
- if( !get_option('dbem_permissions_events') && !em_verify_admin() ){
44
- $args['owner'] = get_current_user_id();
45
- }
46
-
47
- $events = EM_Events::get( $args );
48
- $events_count = count ( $events );
49
-
50
- $use_events_end = get_option ( 'dbem_use_event_end' );
51
- ?>
52
- <div class="wrap">
53
- <div id="icon-events" class="icon32"><br />
54
- </div>
55
- <h2>
56
- <?php echo $title; ?>
57
- <a href="admin.php?page=events-manager-event" class="button add-new-h2"><?php _e('Add New','dbem'); ?></a>
58
- </h2>
59
- <?php
60
- $link = array ();
61
- $link ['past'] = "<a href='" . get_bloginfo ( 'wpurl' ) . "/wp-admin/admin.php?page=events-manager&amp;scope=past&amp;order=desc'>" . __ ( 'Past events', 'dbem' ) . "</a>";
62
- $link ['all'] = " <a href='" . get_bloginfo ( 'wpurl' ) . "/wp-admin/admin.php?page=events-manager&amp;scope=all&amp;order=desc'>" . __ ( 'All events', 'dbem' ) . "</a>";
63
- $link ['future'] = " <a href='" . get_bloginfo ( 'wpurl' ) . "/wp-admin/admin.php?page=events-manager&amp;scope=future'>" . __ ( 'Future events', 'dbem' ) . "</a>";
64
- ?>
65
- <?php if ( !empty($_GET['error']) ) : ?>
66
- <div id='message' class='error'>
67
- <p><?php echo $_GET['error']; ?></p>
68
- </div>
69
- <?php endif; ?>
70
- <?php if ( !empty($_GET['message']) ) : ?>
71
- <div id='message' class='updated fade'>
72
- <p><?php echo $_GET['message']; ?></p>
73
- </div>
74
- <?php endif; ?>
75
- <form id="posts-filter" action="" method="get"><input type='hidden' name='page' value='events-manager' />
76
- <ul class="subsubsub">
77
- <li><a href='#' class="current"><?php _e ( 'Total', 'dbem' ); ?> <span class="count">(<?php echo (count ( $events )); ?>)</span></a></li>
78
- </ul>
79
- <p class="search-box">
80
- <label class="screen-reader-text" for="post-search-input"><?php _e('Search Events','dbem'); ?>:</label>
81
- <input type="text" id="post-search-input" name="em_search" value="<?php echo (!empty($_GET['em_search'])) ? $_GET['em_search']:''; ?>" />
82
- <input type="submit" value="<?php _e('Search Events','dbem'); ?>" class="button" />
83
- </p>
84
- <div class="tablenav">
85
-
86
- <div class="alignleft actions">
87
- <select name="action">
88
- <option value="-1" selected="selected"><?php _e ( 'Bulk Actions' ); ?></option>
89
- <option value="deleteEvents"><?php _e ( 'Delete selected','dbem' ); ?></option>
90
- </select>
91
- <input type="submit" value="<?php _e ( 'Apply' ); ?>" name="doaction2" id="doaction2" class="button-secondary action" />
92
- <select name="scope">
93
- <?php
94
- foreach ( $scope_names as $key => $value ) {
95
- $selected = "";
96
- if ($key == $scope)
97
- $selected = "selected='selected'";
98
- echo "<option value='$key' $selected>$value</option> ";
99
- }
100
- ?>
101
- </select>
102
- <input id="post-query-submit" class="button-secondary" type="submit" value="<?php _e ( 'Filter' )?>" />
103
- </div>
104
- <!--
105
- <div class="view-switch">
106
- <a href="/wp-admin/edit.php?mode=list"><img class="current" id="view-switch-list" src="http://wordpress.lan/wp-includes/images/blank.gif" width="20" height="20" title="List View" alt="List View" name="view-switch-list" /></a> <a href="/wp-admin/edit.php?mode=excerpt"><img id="view-switch-excerpt" src="http://wordpress.lan/wp-includes/images/blank.gif" width="20" height="20" title="Excerpt View" alt="Excerpt View" name="view-switch-excerpt" /></a>
107
- </div>
108
- -->
109
- <?php
110
- if ( $events_count >= $limit ) {
111
- $page_link_template = em_add_get_params($_SERVER['REQUEST_URI'], array('pno'=>'%PAGE%'));
112
- $events_nav = em_admin_paginate( $page_link_template, $events_count, $limit, $page, 5);
113
- echo $events_nav;
114
- }
115
- ?>
116
- <br class="clear" />
117
- </div>
118
-
119
- <?php
120
- if (empty ( $events )) {
121
- // TODO localize
122
- _e ( 'no events','dbem' );
123
- } else {
124
- ?>
125
-
126
- <table class="widefat">
127
- <thead>
128
- <tr>
129
- <th class='manage-column column-cb check-column' scope='col'>
130
- <input class='select-all' type="checkbox" value='1' />
131
- </th>
132
- <th><?php _e ( 'Name', 'dbem' ); ?></th>
133
- <th>&nbsp;</th>
134
- <th><?php _e ( 'Location', 'dbem' ); ?></th>
135
- <th colspan="2"><?php _e ( 'Date and time', 'dbem' ); ?></th>
136
- </tr>
137
- </thead>
138
- <tbody>
139
- <?php
140
- $rowno = 0;
141
- $event_count = 0;
142
- foreach ( $events as $event ) {
143
- /* @var $event EM_Event */
144
- if( ($rowno < $limit || empty($limit)) && ($event_count >= $offset || $offset === 0) ) {
145
- $rowno++;
146
- $class = ($rowno % 2) ? ' class="alternate"' : '';
147
- // FIXME set to american
148
- $localised_start_date = date_i18n('D d M Y', $event->start);
149
- $localised_end_date = date_i18n('D d M Y', $event->end);
150
- $style = "";
151
- $today = date ( "Y-m-d" );
152
- $location_summary = "<b>" . $event->location->name . "</b><br/>" . $event->location->address . " - " . $event->location->town;
153
- $category = new EM_Category($event->category_id);
154
-
155
- if ($event->start_date < $today && $event->end_date < $today){
156
- $style = "style ='background-color: #FADDB7;'";
157
- }
158
- ?>
159
- <tr <?php echo "$class $style"; ?>>
160
-
161
- <td>
162
- <input type='checkbox' class='row-selector' value='<?php echo $event->id; ?>' name='events[]' />
163
- </td>
164
- <td>
165
- <strong>
166
- <a class="row-title" href="<?php bloginfo ( 'wpurl' )?>/wp-admin/admin.php?page=events-manager-event&amp;event_id=<?php echo $event->id ?>&amp;scope=<?php echo $scope ?>&amp;p=<?php echo $page ?>"><?php echo ($event->name); ?></a>
167
- </strong>
168
- <?php if( is_object($category) ) : ?>
169
- <br/><span title='<?php echo __( 'Category', 'dbem' ).": ".$category->name ?>'><?php echo $category->name ?></span>
170
- <?php endif; ?>
171
- <?php
172
- if( get_option('dbem_rsvp_enabled') == 1 && $event->rsvp == 1 ){
173
- ?>
174
- <br/>
175
- <a href="<?php bloginfo ( 'wpurl' )?>/wp-admin/admin.php?page=events-manager-bookings&amp;event_id=<?php echo $event->id ?>"><?php echo __("Bookings",'dbem'); ?></a> &ndash;
176
- <?php _e("Booked",'dbem'); ?>: <?php echo $event->get_bookings()->get_booked_seats()."/".$event->seats; ?>
177
- <?php if( get_option('dbem_bookings_approval') == 1 ): ?>
178
- | <?php _e("Pending",'dbem') ?>: <?php echo $event->get_bookings()->get_pending_seats(); ?>
179
- <?php endif;
180
- }
181
- ?>
182
- </td>
183
- <td>
184
- <a href="<?php bloginfo ( 'wpurl' )?>/wp-admin/admin.php?page=events-manager-event&amp;action=duplicate&amp;event_id=<?php echo $event->id; ?>&amp;scope=<?php echo $scope ?>&amp;p=<?php echo $page ?>" title="<?php _e ( 'Duplicate this event', 'dbem' ); ?>">
185
- <strong>+</strong>
186
- </a>
187
- </td>
188
- <td>
189
- <?php echo $location_summary; ?>
190
- </td>
191
-
192
- <td>
193
- <?php echo $localised_start_date; ?>
194
- <?php echo ($localised_end_date != $localised_start_date) ? " - $localised_end_date":'' ?>
195
- <br />
196
- <?php
197
- //TODO Should 00:00 - 00:00 be treated as an all day event?
198
- echo substr ( $event->start_time, 0, 5 ) . " - " . substr ( $event->end_time, 0, 5 );
199
- ?>
200
- </td>
201
- <td>
202
- <?php
203
- if ( $event->is_recurrence() ) {
204
- ?>
205
- <strong>
206
- <?php echo $event->get_recurrence_description(); ?> <br />
207
- <a href="<?php bloginfo ( 'wpurl' )?>/wp-admin/admin.php?page=events-manager-event&amp;event_id=<?php echo $event->recurrence_id ?>&amp;scope=<?php echo $scope ?>&amp;p=<?php echo $page ?>"><?php _e ( 'Reschedule', 'dbem' ); ?></a>
208
- </strong>
209
- <?php
210
- }
211
- ?>
212
- </td>
213
- </tr>
214
- <?php
215
- }
216
- $event_count++;
217
- }
218
- ?>
219
- </tbody>
220
- </table>
221
- <?php
222
- } // end of table
223
- ?>
224
- <div class='tablenav'>
225
- <div class="alignleft actions">
226
- <br class='clear' />
227
- </div>
228
- <?php if ( $events_count >= $limit ) : ?>
229
- <div class="tablenav-pages">
230
- <?php
231
- echo $events_nav;
232
- ?>
233
- </div>
234
- <?php endif; ?>
235
- <br class='clear' />
236
- </div>
237
- </form>
238
- </div>
239
- <?php
240
- }
241
-
242
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
admin/em-help.php CHANGED
@@ -8,20 +8,37 @@ function em_admin_help_page(){
8
  <div class="wrap">
9
  <div id="icon-events" class="icon32"><br /></div>
10
  <h2><?php _e('Getting Help for Events Manager','dbem'); ?></h2>
11
- <p>
12
- For further information on using this plugin, please view the <a href="http://wp-events-plugin.com/documentation/">documentation pages</a>. If you can't find what you're looking for in the documentation, you may find help on our <a href="http://wp-events-plugin.com/forums/">support forums</a>.
13
- </p>
14
  <div class="em-docs">
 
 
 
 
 
 
 
 
 
 
 
 
 
15
  <h2><?php _e('Placeholders for customizing event pages','dbem'); ?></h2>
16
- <p><?php echo sprintf( __("In the <a href='%s'>settings page</a>, you'll find various textboxes where you can edit how event information looks, such as for event and location lists. Using the placeholders below, you can choose what information should be displayed.",'dbem'), 'admin.php?page=events-manager-options'); ?></p>
17
- <h3><a name="event-placeholders"><?php _e('Event Related Placeholders','dbem'); ?></a></h3>
 
18
  <?php echo em_docs_placeholders( array('type'=>'events') ); ?>
19
- <h3><a name="location-placeholders"><?php _e('Location Related Placeholders','dbem'); ?></a></h3>
 
 
 
 
20
  <?php echo em_docs_placeholders( array('type'=>'locations') ); ?>
21
- <h3><a name="booking-placeholders"><?php _e('Booking Related Placeholders','dbem'); ?></a></h3>
 
22
  <?php echo em_docs_placeholders( array('type'=>'bookings') ); ?>
23
  </div>
24
  <?php
 
25
  //Is this a previously imported installation?
26
  $old_table_name = $wpdb->prefix.'dbem_events';
27
  if( $wpdb->get_var("SHOW TABLES LIKE '$old_table_name'") == $old_table_name ){
@@ -33,7 +50,7 @@ function em_admin_help_page(){
33
  <p>If something went wrong with the update to version 3 read on:</p>
34
  <h4>Scenario 1: the plugin is working, but for some reason the old events weren't imported</h4>
35
  <p>You can safely reimport your old events from the previous tables without any risk of deleting them. However, if you click the link below <b>YOU WILL OVERWRITE ANY NEW EVENTS YOU CREATED IN VERSION 3</b></p>
36
- <p><a onclick="return confirm('Are you sure you want to do this? Any new changes made since updating will be overwritten by your old ones, and this cannot be undone');" href="<?php echo wp_nonce_url( get_bloginfo('wpurl').'/wp-admin/admin.php?page=events-manager-help&em_reimport=1', 'em_reimport' ) ?>">Reimport Events from version 2</a></p>
37
  <h4>Scenario 2: the plugin is not working, I want to go back to version 2!</h4>
38
  <p>You can safely downgrade and will not lose any information.</p>
39
  <ol>
8
  <div class="wrap">
9
  <div id="icon-events" class="icon32"><br /></div>
10
  <h2><?php _e('Getting Help for Events Manager','dbem'); ?></h2>
 
 
 
11
  <div class="em-docs">
12
+ <h2>Where To Get Help</h3>
13
+ <p>
14
+ This page is only a small portion of the event documentation which is here for quick reference. If you're just starting out, we recommend you visit the following places for further support:
15
+ </p>
16
+ <ol>
17
+ <li>New users are strongly encouraged to have a look at our <a href="http://wp-events-plugin.com/documentation/getting-started/">getting started page</a>.</li>
18
+ <li>Browse the other documentation pages and <a href="http://wp-events-plugin.com/tutorials/">tutorials</a>.</li>
19
+ <li>View the <a href="http://wp-events-plugin.com/documentation/faq/">FAQ</a> for general questions and <a href="http://wp-events-plugin.com/documentation/troubleshooting/">Troubleshooting</a> for common issues. These are regularly updated with recent issues.</li>
20
+ <li>Rather than trying to contact us directly, we request you use the <a href="http://wordpress.org/tags/events-manager?forum_id=10">support forums</a> as others may be experiencing the same issues as you. For faster support via private member forums and extra features please consider <a href="http://wp-events-plugin.com/events-manager-pro/">upgrading to pro</a>.</li>
21
+ </ol>
22
+ <p>
23
+ If you can't find what you're looking for in the documentation, you may find help on our <a href="http://wp-events-plugin.com/forums/">support forums</a>.
24
+ </p>
25
  <h2><?php _e('Placeholders for customizing event pages','dbem'); ?></h2>
26
+ <p><?php echo sprintf( __("In the <a href='%s'>settings page</a>, you'll find various textboxes where you can edit how event information looks, such as for event and location lists. Using the placeholders below, you can choose what information should be displayed.",'dbem'), EM_ADMIN_URL .'&amp;events-manager-options'); ?></p>
27
+ <a name="event-placeholders"></a>
28
+ <h3 style="margin-top:20px;"><?php _e('Event Related Placeholders','dbem'); ?></h3>
29
  <?php echo em_docs_placeholders( array('type'=>'events') ); ?>
30
+ <a name="category-placeholders"></a>
31
+ <h3><?php _e('Category Related Placeholders','dbem'); ?></h3>
32
+ <?php echo em_docs_placeholders( array('type'=>'categories') ); ?>
33
+ <a name="location-placeholders"></a>
34
+ <h3><?php _e('Location Related Placeholders','dbem'); ?></h3>
35
  <?php echo em_docs_placeholders( array('type'=>'locations') ); ?>
36
+ <a name="booking-placeholders"></a>
37
+ <h3><?php _e('Booking Related Placeholders','dbem'); ?></h3>
38
  <?php echo em_docs_placeholders( array('type'=>'bookings') ); ?>
39
  </div>
40
  <?php
41
+
42
  //Is this a previously imported installation?
43
  $old_table_name = $wpdb->prefix.'dbem_events';
44
  if( $wpdb->get_var("SHOW TABLES LIKE '$old_table_name'") == $old_table_name ){
50
  <p>If something went wrong with the update to version 3 read on:</p>
51
  <h4>Scenario 1: the plugin is working, but for some reason the old events weren't imported</h4>
52
  <p>You can safely reimport your old events from the previous tables without any risk of deleting them. However, if you click the link below <b>YOU WILL OVERWRITE ANY NEW EVENTS YOU CREATED IN VERSION 3</b></p>
53
+ <p><a onclick="return confirm('Are you sure you want to do this? Any new changes made since updating will be overwritten by your old ones, and this cannot be undone');" href="<?php echo wp_nonce_url( EM_ADMIN_URL .'&amp;events-manager-help&em_reimport=1', 'em_reimport' ) ?>">Reimport Events from version 2</a></p>
54
  <h4>Scenario 2: the plugin is not working, I want to go back to version 2!</h4>
55
  <p>You can safely downgrade and will not lose any information.</p>
56
  <ol>
admin/em-locations-search.php CHANGED
@@ -3,20 +3,24 @@
3
  * This page will search for either a specific location via GET "id" variable
4
  * or will search for events by name via the GET "q" variable.
5
  */
 
6
  require_once('../../../../wp-load.php');
7
  global $wpdb;
8
 
9
- $locations_table = $wpdb->prefix . EM_LOCATIONS_TABLE;
10
- $location_cond = ( get_option('dbem_permissions_locations') < 1 && !em_verify_admin() ) ? "AND location_owner=".get_current_user_id() : '';
11
 
12
  $term = (isset($_GET['term'])) ? '%'.$_GET['term'].'%' : '%'.$_GET['q'].'%';
13
  $sql = $wpdb->prepare("
14
  SELECT
 
15
  Concat( location_name, ', ', location_address, ', ', location_town) AS `label`,
16
  location_name AS `value`,
17
  location_address AS `address`,
18
  location_town AS `town`,
19
- location_id AS `id`
 
 
20
  FROM $locations_table
21
  WHERE ( `location_name` LIKE %s ) $location_cond LIMIT 10
22
  ", $term);
3
  * This page will search for either a specific location via GET "id" variable
4
  * or will search for events by name via the GET "q" variable.
5
  */
6
+ //FIXME just plug loc search into ajax catcher
7
  require_once('../../../../wp-load.php');
8
  global $wpdb;
9
 
10
+ $locations_table = EM_LOCATIONS_TABLE;
11
+ $location_cond = ( !current_user_can('edit_others_locations') && !current_user_can('read_others_locations') ) ? "AND location_owner=".get_current_user_id() : '';
12
 
13
  $term = (isset($_GET['term'])) ? '%'.$_GET['term'].'%' : '%'.$_GET['q'].'%';
14
  $sql = $wpdb->prepare("
15
  SELECT
16
+ location_id AS `id`,
17
  Concat( location_name, ', ', location_address, ', ', location_town) AS `label`,
18
  location_name AS `value`,
19
  location_address AS `address`,
20
  location_town AS `town`,
21
+ location_state AS `state`,
22
+ location_postcode AS `postcode`,
23
+ location_country AS `country`
24
  FROM $locations_table
25
  WHERE ( `location_name` LIKE %s ) $location_cond LIMIT 10
26
  ", $term);
admin/em-locations.php DELETED
@@ -1,268 +0,0 @@
1
- <?php
2
- /**
3
- * Looks at the request values, saves/updates and then displays the right menu in the admin
4
- * @return null
5
- */
6
- function em_admin_locations_page() {
7
- //TODO EM_Location is globalized, use it fully here
8
- global $EM_Location;
9
- //Take actions
10
- if( !empty($_REQUEST['action']) || !empty($_REQUEST['location_id']) ){
11
- if( $_REQUEST['action'] == "edit" || $_REQUEST['action'] == "add" ) {
12
- //edit/add location
13
- em_admin_location();
14
- } elseif( $_REQUEST['action'] == "delete" ){
15
- //delelte location
16
- $locations = $_REQUEST['locations'];
17
- foreach($locations as $location_id) {
18
- $EM_Location = new EM_Location($location_id);
19
- $EM_Location->delete();
20
- }
21
- em_admin_locations(__('Locations Deleted', "dbem" ));
22
- } elseif( $_REQUEST['action'] == "save") {
23
- // save (add/update) location
24
- if( empty($EM_Location) || !is_object($EM_Location) ){
25
- $EM_Location = new EM_Location(); //blank location
26
- $success_message = __('The location has been added.', 'dbem');
27
- }else{
28
- $success_message = __('The location has been updated.', 'dbem');
29
- }
30
- $EM_Location->get_post();
31
- $validation_result = $EM_Location->validate();
32
- if ( $validation_result ) {
33
- $EM_Location->save(); //FIXME better handling of db write fails when saving location
34
- em_admin_locations($success_message);
35
- } else {
36
- ?>
37
- <div id='message' class='error '>
38
- <p>
39
- <strong><?php _e( "Ach, there's a problem here:", "dbem" ) ?></strong><br /><br /><?php echo implode('<br />', $EM_Location->errors); ?>
40
- </p>
41
- </div>
42
- <?php
43
- unset($EM_Location);
44
- em_admin_location();
45
- }
46
- }
47
- } else {
48
- // no action, just a locations list
49
- em_admin_locations();
50
- }
51
- }
52
-
53
- function em_admin_locations($message='', $fill_fields = false) {
54
- $limit = ( !empty($_REQUEST['limit']) ) ? $_REQUEST['limit'] : 20;//Default limit
55
- $page = ( !empty($_REQUEST['pno']) ) ? $_REQUEST['pno']:1;
56
- $offset = ( $page > 1 ) ? ($page-1)*$limit : 0;
57
- $locations = EM_Locations::get();
58
- $locations_count = count($locations);
59
- ?>
60
- <div class='wrap'>
61
- <div id='icon-edit' class='icon32'>
62
- <br/>
63
- </div>
64
- <h2>
65
- <?php _e('Locations', 'dbem'); ?>
66
- <a href="admin.php?page=events-manager-locations&action=add" class="button add-new-h2"><?php _e('Add New') ?></a>
67
- </h2>
68
-
69
- <?php if($message != "") : ?>
70
- <div id='message' class='updated fade below-h2'>
71
- <p><?php echo $message ?></p>
72
- </div>
73
- <?php endif; ?>
74
-
75
- <form id='bookings-filter' method='post' action=''>
76
- <input type='hidden' name='page' value='locations'/>
77
- <input type='hidden' name='limit' value='<?php echo $limit ?>' />
78
- <input type='hidden' name='p' value='<?php echo $page ?>' />
79
- <?php if ( $locations_count > 0 ) : ?>
80
- <div class='tablenav'>
81
- <div class="alignleft actions">
82
- <select name="action">
83
- <option value="" selected="selected"><?php _e ( 'Bulk Actions' ); ?></option>
84
- <option value="delete"><?php _e ( 'Delete selected','dbem' ); ?></option>
85
- </select>
86
- <input type="submit" value="<?php _e ( 'Apply' ); ?>" id="doaction2" class="button-secondary action" />
87
- <?php
88
- //Pagination (if needed/requested)
89
- if( $locations_count >= $limit ){
90
- //Show the pagination links (unless there's less than 10 events
91
- $page_link_template = preg_replace('/(&|\?)p=\d+/i','',$_SERVER['REQUEST_URI']);
92
- $page_link_template = em_add_get_params($page_link_template, array('pno'=>'%PAGE%'));
93
- $locations_nav = em_paginate( $page_link_template, $locations_count, $limit, $page);
94
- echo $locations_nav;
95
- }
96
- ?>
97
- </div>
98
- </div>
99
- <table class='widefat'>
100
- <thead>
101
- <tr>
102
- <th class='manage-column column-cb check-column' scope='col'><input type='checkbox' class='select-all' value='1'/></th>
103
- <th><?php _e('Name', 'dbem') ?></th>
104
- <th><?php _e('Address', 'dbem') ?></th>
105
- <th><?php _e('Town', 'dbem') ?></th>
106
- </tr>
107
- </thead>
108
- <tfoot>
109
- <tr>
110
- <th class='manage-column column-cb check-column' scope='col'><input type='checkbox' class='select-all' value='1'/></th>
111
- <th><?php _e('Name', 'dbem') ?></th>
112
- <th><?php _e('Address', 'dbem') ?></th>
113
- <th><?php _e('Town', 'dbem') ?></th>
114
- </tr>
115
- </tfoot>
116
- <tbody>
117
- <?php $i = 1; ?>
118
- <?php foreach ($locations as $EM_Location) : ?>
119
- <?php if( $i >= $offset && $i <= $offset+$limit ): ?>
120
- <tr>
121
- <td><input type='checkbox' class ='row-selector' value='<?php echo $EM_Location->id ?>' name='locations[]'/></td>
122
- <td><a href='admin.php?page=events-manager-locations&amp;action=edit&amp;location_id=<?php echo $EM_Location->id ?>'><?php echo $EM_Location->name ?></a></td>
123
- <td><?php echo $EM_Location->address ?></td>
124
- <td><?php echo $EM_Location->town ?></td>
125
- </tr>
126
- <?php endif; ?>
127
- <?php $i++; ?>
128
- <?php endforeach; ?>
129
- </tbody>
130
- </table>
131
- <?php else: ?>
132
- <p><?php _e('No venues have been inserted yet!', 'dbem') ?></p>
133
- <?php endif; ?>
134
- </form>
135
- </div>
136
- <?php
137
- }
138
-
139
- function em_admin_location($message = "") {
140
- global $EM_Location, $EM_Event;
141
- //check that user can access this page
142
- if( is_object($EM_Location) && !$EM_Location->can_manage() ){
143
- ?>
144
- <div class="wrap"><h2><?php _e('Unauthorized Access','dbem'); ?></h2><p><?php _e('You do not have the rights to manage this location.','dbem'); ?></p></div>
145
- <?php
146
- return false;
147
- }
148
- if( empty($EM_Location) || !is_object($EM_Location) ){
149
- $title = __('Add location', 'dbem');
150
- $EM_Location = new EM_Location();
151
- }else{
152
- $title = __('Edit location', 'dbem');
153
- }
154
- ?>
155
- <form enctype='multipart/form-data' name='editcat' id='locationForm' method='post' action='admin.php?page=events-manager-locations' class='validate'>
156
- <input type='hidden' name='action' value='save' />
157
- <input type='hidden' name='location_id' value='<?php echo $EM_Location->id ?>'/>
158
- <div class='wrap'>
159
- <div id='icon-edit' class='icon32'>
160
- <br/>
161
- </div>
162
- <h2><?php echo $title ?></h2>
163
-
164
- <?php if($message != "") : ?>
165
- <div id='message' class='updated fade below-h2' style='background-color: rgb(255, 251, 204);'>
166
- <p><?php echo $message ?></p>
167
- </div>
168
- <?php endif; ?>
169
- <div id='ajax-response'></div>
170
-
171
- <div id="poststuff" class="metabox-holder">
172
- <div id="post-body">
173
- <div id="post-body-content">
174
- <div id="location_name" class="stuffbox">
175
- <h3>
176
- <?php _e ( 'Location Name', 'dbem' ); ?>
177
- </h3>
178
- <div class="inside">
179
- <input name='location_name' id='location-name' type='text' value='<?php echo htmlspecialchars($EM_Location->name, ENT_QUOTES); ?>' size='40' />
180
- <br />
181
- <?php _e('The name of the location', 'dbem') ?>
182
- </div>
183
- </div>
184
- <div id="location_coordinates" class="stuffbox" style='display: none;'>
185
- <h3>
186
- <?php _e ( 'Coordinates', 'dbem' ); ?>
187
- </h3>
188
- <div class="inside">
189
- <input id='location-latitude' name='location_latitude' type='text' value='<?php echo $EM_Location->latitude; ?>' size='15' />
190
- -
191
- <input id='location-longitude' name='location_longitude' type='text' value='<?php echo $EM_Location->longitude; ?>' size='15' />
192
- </div>
193
- </div>
194
- <div id="location_info" class="stuffbox">
195
- <h3>
196
- <?php _e ( 'Location', 'dbem' ); ?>
197
- </h3>
198
- <div class="inside">
199
- <table id="dbem-location-data">
200
- <tr>
201
- <td style="padding-right:20px">
202
- <table>
203
- <tr>
204
- <th><?php _e ( 'Address:' )?>&nbsp;</th>
205
- <td>
206
- <input id="location-address" type="text" name="location_address" value="<?php echo htmlspecialchars($EM_Location->address, ENT_QUOTES); ; ?>" />
207
- <p><?php _e ( 'The address of the location where the event takes place. Example: 21, Dominick Street', 'dbem' )?></p>
208
- </td>
209
- </tr>
210
- <tr>
211
- <th><?php _e ( 'Town:' )?>&nbsp;</th>
212
- <td>
213
- <input id="location-town" type="text" name="location_town" value="<?php echo htmlspecialchars($EM_Location->town, ENT_QUOTES); ?>" />
214
- <p><?php _e ( 'The town where the location is located. If you\'re using the Google Map integration and want to avoid geotagging ambiguities include the country in the town field. Example: Verona, Italy.', 'dbem' )?></p>
215
- </td>
216
- </tr>
217
- </table>
218
- </td>
219
- <?php if ( get_option ( 'dbem_gmap_is_active' ) ) : ?>
220
- <td width="400">
221
- <div id='em-map-404' style='width: 400px; vertical-align:middle; text-align: center;'>
222
- <p><em><?php _e ( 'Location not found', 'dbem' ); ?></em></p>
223
- </div>
224
- <div id='em-map' style='width: 400px; height: 300px; display: none;'></div>
225
- </td>
226
- <?php endif; ?>
227
- </tr>
228
- </table>
229
- </div>
230
- </div>
231
-
232
- <div id="location_description" class="postbox">
233
- <h3>
234
- <?php _e ( 'Details', 'dbem' ); ?>
235
- </h3>
236
- <div class="inside">
237
- <div id="<?php echo user_can_richedit() ? 'postdivrich' : 'postdiv'; ?>" class="postarea">
238
- <?php the_editor($EM_Location->description ); ?>
239
- </div>
240
- <br />
241
- <?php _e ( 'Details about the location', 'dbem' )?>
242
- </div>
243
- </div>
244
-
245
- <div id="location_description" class="stuffbox">
246
- <h3>
247
- <?php _e ( 'Location image', 'dbem' ); ?>
248
- </h3>
249
- <div class="inside" style="padding:10px;">
250
- <?php if ($EM_Location->image_url != '') : ?>
251
- <img src='<?php echo $EM_Location->image_url; ?>' alt='<?php echo $EM_Location->name ?>'/>
252
- <?php else : ?>
253
- <?php _e('No image uploaded for this location yet', 'debm') ?>
254
- <?php endif; ?>
255
- <br /><br />
256
- <label for='location_image'><?php _e('Upload/change picture', 'dbem') ?></label> <input id='location-image' name='location_image' id='location_image' type='file' size='40' />
257
- </div>
258
- </div>
259
- </div>
260
- </div>
261
- </div>
262
- <p class='submit'><input type='submit' class='button-primary' name='submit' value='<?php _e('Update location', 'dbem') ?>' /></p>
263
- </div>
264
- </form>
265
- <?php
266
- }
267
-
268
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
admin/em-ms-locations.php ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Looks at the request values, saves/updates and then displays the right menu in the admin
4
+ * @return null
5
+ */
6
+ function em_admin_ms_locations() {
7
+ //TODO EM_Location is globalized, use it fully here
8
+ global $EM_Location;
9
+ EM_Object::ms_global_switch();
10
+ //Take actions
11
+ if( !empty($_REQUEST['action']) && ($_REQUEST['action'] == "edit" || $_REQUEST['action'] == "location_save")) {
12
+ em_admin_location();
13
+ } else {
14
+ // no action, just a locations list
15
+ em_admin_locations();
16
+ }
17
+ EM_Object::ms_global_switch_back();
18
+ }
19
+
20
+ function em_admin_locations($message='', $fill_fields = false) {
21
+ global $current_site;
22
+ ?>
23
+ <div class='wrap'>
24
+ <div id='icon-edit' class='icon32'>
25
+ <br/>
26
+ </div>
27
+ <h2>
28
+ <?php _e('Locations', 'dbem'); ?>
29
+ <span><a href="<?php echo em_add_get_params($_SERVER['REQUEST_URI'], array('action'=>'edit')); ?>" class="button add-new-h2"><?php _e('Add New','dbem'); ?></a></span>
30
+ </h2>
31
+ <?php em_locate_template('tables/locations.php',true, array('url' => $_SERVER['REQUEST_URI'])); ?>
32
+ </div>
33
+ <?php
34
+ }
35
+
36
+ function em_admin_location($message = "") {
37
+ global $EM_Location, $EM_Notices;
38
+ if( empty($EM_Location) || !is_object($EM_Location) ){
39
+ $title = __('Add location', 'dbem');
40
+ $EM_Location = new EM_Location();
41
+ }else{
42
+ $title = __('Edit location', 'dbem');
43
+ }
44
+ ?>
45
+ <div class='wrap'>
46
+ <div id='icon-edit' class='icon32'>
47
+ <br/>
48
+ </div>
49
+ <h2><?php echo $title ?></h2>
50
+ <?php em_locate_template('forms/location-editor.php', true); ?>
51
+ </div>
52
+ <?php
53
+ }
54
+
55
+ ?>
admin/em-ms-options.php ADDED
@@ -0,0 +1,213 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ function em_ms_upgrade( $blog_id ){
3
+ ?>
4
+ <div class="wrap">
5
+ <div id='icon-options-general' class='icon32'><br /></div>
6
+ <h2><?php _e('Update Network'); ?></h2>
7
+ <?php
8
+ if( $_REQUEST['action'] == 'upgrade' && check_admin_referer('em_ms_ugrade_'.get_current_user_id()) ){
9
+ global $current_site,$wpdb;
10
+ $blog_ids = $wpdb->get_col('SELECT blog_id FROM '.$wpdb->blogs.' WHERE site_id='.$current_site->blog_id);
11
+ foreach($blog_ids as $blog_id){
12
+ switch_to_blog($blog_id);
13
+ if( EM_VERSION > get_option('dbem_version', 0) ){
14
+ require_once( dirname(__FILE__).'/../em-install.php');
15
+ em_install();
16
+ echo "<p>Upgraded - ".get_bloginfo('blogname')."</p>";
17
+ }
18
+ restore_current_blog();
19
+ }
20
+ echo "<p>Done Upgrading</p>";
21
+ }else{
22
+ ?>
23
+ <form action="" method="post">
24
+ <p><?php _e('To update your network blogs with the latest Events Manager automatically, click the update button below.'); ?></p>
25
+ <input type="hidden" name="_wpnonce" value="<?php echo wp_create_nonce('em_ms_ugrade_'.get_current_user_id()); ?>" />
26
+ <input type="hidden" name="action" value="upgrade" />
27
+ <input type="submit" value="<?php _e('Update','dbem'); ?>" />
28
+ </form>
29
+ <?php
30
+ }
31
+ ?>
32
+ </div>
33
+ <?php
34
+ }
35
+
36
+ /**
37
+ * Displays network-related options in the network admin section
38
+ * @uses em_options_save() to save settings
39
+ */
40
+ function em_ms_admin_options_page() {
41
+ global $wpdb,$EM_Notices;
42
+ //Check for uninstall/reset request
43
+ if( !empty($_REQUEST['action']) && $_REQUEST['action'] == 'uninstall' ){
44
+ em_admin_options_uninstall_page();
45
+ return;
46
+ }
47
+ if( !empty($_REQUEST['action']) && $_REQUEST['action'] == 'reset' ){
48
+ em_admin_options_reset_page();
49
+ return;
50
+ }
51
+ //TODO place all options into an array
52
+ $events_placeholders = '<a href="'.EM_ADMIN_URL .'&amp;events-manager-help#event-placeholders">'. __('Event Related Placeholders','dbem') .'</a>';
53
+ $locations_placeholders = '<a href="'.EM_ADMIN_URL .'&amp;events-manager-help#location-placeholders">'. __('Location Related Placeholders','dbem') .'</a>';
54
+ $bookings_placeholders = '<a href="'.EM_ADMIN_URL .'&amp;events-manager-help#booking-placeholders">'. __('Booking Related Placeholders','dbem') .'</a>';
55
+ $categories_placeholders = '<a href="'.EM_ADMIN_URL .'&amp;events-manager-help#category-placeholders">'. __('Category Related Placeholders','dbem') .'</a>';
56
+ $events_placeholder_tip = " ". sprintf(__('This accepts %s and %s placeholders.','dbem'),$events_placeholders, $locations_placeholders);
57
+ $locations_placeholder_tip = " ". sprintf(__('This accepts %s placeholders.','dbem'), $locations_placeholders);
58
+ $categories_placeholder_tip = " ". sprintf(__('This accepts %s placeholders.','dbem'), $categories_placeholders);
59
+ $bookings_placeholder_tip = " ". sprintf(__('This accepts %s, %s and %s placeholders.','dbem'), $bookings_placeholders, $events_placeholders, $locations_placeholders);
60
+
61
+ $save_button = '<tr><th>&nbsp;</th><td><p class="submit" style="margin:0px; padding:0px; text-align:right;"><input type="submit" id="dbem_options_submit" name="Submit" value="'. __( 'Save Changes', 'dbem') .' ('. __('All','dbem') .')" /></p></ts></td></tr>';
62
+ //Do some multisite checking here for reuse
63
+ ?>
64
+ <script type="text/javascript" charset="utf-8">
65
+ jQuery(document).ready(function($){
66
+ var close_text = '<?php _e('Collapse All','dbem'); ?>';
67
+ var open_text = '<?php _e('Expand All','dbem'); ?>';
68
+ var open_close = $('<a href="#" style="display:block; float:right; clear:right; margin:10px;">'+open_text+'</a>');
69
+ $('#em-options-title').before(open_close);
70
+ open_close.click( function(e){
71
+ e.preventDefault();
72
+ if($(this).text() == close_text){
73
+ $(".postbox").addClass('closed');
74
+ $(this).text(open_text);
75
+ }else{
76
+ $(".postbox").removeClass('closed');
77
+ $(this).text(close_text);
78
+ }
79
+ });
80
+ $(".postbox > h3").click(function(){ $(this).parent().toggleClass('closed'); });
81
+ $(".postbox").addClass('closed');
82
+ //MS Mode selection hiders
83
+ $('input[name="dbem_ms_global_table"]').change(function(){ //global
84
+ if( $('input:radio[name="dbem_ms_global_table"]:checked').val() == 1 ){
85
+ $("tbody.em-global-options").show();
86
+ $('input:radio[name="dbem_ms_mainblog_locations"]:checked').trigger('change');
87
+ }else{
88
+ $("tbody.em-global-options").hide();
89
+ }
90
+ }).first().trigger('change');
91
+ //events
92
+ $('input[name="dbem_ms_global_events"]').change(function(){
93
+ if( $('input:radio[name="dbem_ms_global_events"]:checked').val() == 1 ){
94
+ $("tr#dbem_ms_global_events_links_row").show();
95
+ $('input:radio[name="dbem_ms_global_events_links"]:checked').trigger('change');
96
+ }else{
97
+ $("tr#dbem_ms_global_events_links_row, tr#dbem_ms_events_slug_row").hide();
98
+ }
99
+ }).first().trigger('change');
100
+ $('input[name="dbem_ms_global_events_links"]').change(function(){
101
+ if( $('input:radio[name="dbem_ms_global_events_links"]:checked').val() == 1 ){
102
+ $("tr#dbem_ms_events_slug_row").hide();
103
+ }else{
104
+ $("tr#dbem_ms_events_slug_row").show();
105
+ }
106
+ }).first().trigger('change');
107
+ //locations
108
+ $('input[name="dbem_ms_mainblog_locations"]').change(function(){
109
+ if( $('input:radio[name="dbem_ms_mainblog_locations"]:checked').val() == 1 ){
110
+ $("tbody.em-global-locations").hide();
111
+ }else{
112
+ $("tbody.em-global-locations").show();
113
+ }
114
+ }).first().trigger('change');
115
+ $('input[name="dbem_ms_global_locations"]').change(function(){
116
+ if( $('input:radio[name="dbem_ms_global_locations"]:checked').val() == 1 ){
117
+ $("tr#dbem_ms_global_locations_links_row").show();
118
+ $('input:radio[name="dbem_ms_global_locations_links"]:checked').trigger('change');
119
+ }else{
120
+ $("tr#dbem_ms_global_locations_links_row, tr#dbem_ms_locations_slug_row").hide();
121
+ }
122
+ }).first().trigger('change');
123
+ $('input[name="dbem_ms_global_locations_links"]').change(function(){
124
+ if( $('input:radio[name="dbem_ms_global_locations_links"]:checked').val() == 1 ){
125
+ $("tr#dbem_ms_locations_slug_row").hide();
126
+ }else{
127
+ $("tr#dbem_ms_locations_slug_row").show();
128
+ }
129
+ });
130
+ });
131
+ </script>
132
+ <style type="text/css">.postbox h3 { cursor:pointer; }</style>
133
+ <div class="wrap">
134
+ <div id='icon-options-general' class='icon32'><br /></div>
135
+ <h2 class="nav-tab-wrapper">
136
+ <a href="#" id="em-menu-general" class="nav-tab nav-tab-active"><?php _e('General','dbem'); ?></a>
137
+ </h2>
138
+ <h3 id="em-options-title"><?php _e ( 'Event Manager Options', 'dbem' ); ?></h3>
139
+ <?php echo $EM_Notices; ?>
140
+ <form id="em-options-form" method="post" action="">
141
+ <div class="metabox-holder">
142
+ <!-- // TODO Move style in css -->
143
+ <div class='postbox-container' style='width: 99.5%'>
144
+ <div id="">
145
+
146
+ <div class="em-menu-general em-menu-group">
147
+ <div class="postbox " >
148
+ <div class="handlediv" title="<?php __('Click to toggle', 'dbem'); ?>"><br /></div><h3><span><?php _e ( 'Multi Site Options', 'dbem' ); ?></span></h3>
149
+ <div class="inside">
150
+ <table class="form-table">
151
+ <?php
152
+ em_options_radio_binary ( __( 'Enable global tables mode?', 'dbem'), 'dbem_ms_global_table', __( 'Setting this to yes will make all events save in the main site event tables (EM must also be activated). This allows you to share events across different blogs, such as showing events in your network whilst allowing users to display and manage their events within their own blog. Bear in mind that activating this will mean old events created on the sub-blogs will not be accessible anymore, and if you switch back they will be but new events created during global events mode will only remain on the main site.','dbem' ) );
153
+ ?>
154
+ <tbody class="em-global-options">
155
+ <?php
156
+ global $current_site;
157
+ $global_slug_tip = __('%s belonging to other sub-sites will have an extra slug preppended to it so that your main site can differentiate between its own %s and those belonging to other sites in your network.');
158
+ $global_link_tip = __( 'When displaying global %s on the main site you have the option of users viewing the %s details on the main site or being directed to the sub-site.','dbem' );
159
+ $global_post_tip = __( 'Displays %s from all sites on the network by default. You can still restrict %s by blog using shortcodes and template tags coupled with the <code>blog</code> attribute. Requires global tables to be turned on.','dbem');
160
+ $global_link_tip2 = __('You <strong>must</strong> have assigned a %s page in your <a href="%s">main blog settings</a> for this to work.');
161
+ $options_page_link = get_admin_url($current_site->blog_id, 'edit.php?post_type=event&page=events-manager-options#pages');
162
+ ?><tr><td><strong><?php echo sprintf(__('%s Options','dbem'),__('Event','dbem')); ?></strong></td></tr><?php
163
+ em_options_radio_binary ( sprintf(__( 'Display global events on main blog?', 'dbem'), __('events','dbem')), 'dbem_ms_global_events', sprintf($global_post_tip, __('events','dbem'), __('events','dbem')) );
164
+ em_options_radio_binary ( sprintf(__( 'Link sub-site %s directly to sub-site?', 'dbem'), __('events','dbem')), 'dbem_ms_global_events_links', sprintf($global_link_tip, __('events','dbem'), __('event','dbem')).sprintf($global_link_tip2, __('event','dbem'), $options_page_link) );
165
+ em_options_input_text ( sprintf(__( 'Global %s slug', 'dbem' ),__('event','dbem')), 'dbem_ms_events_slug', sprintf($global_slug_tip, __('Events','dbem'), __('events','dbem')).__('Example:','dbem').'<code>http://yoursite.com/events/<strong>event</strong>/subsite-event-slug/', EM_EVENT_SLUG );
166
+ ?><tr><td><strong><?php echo sprintf(__('%s Options','dbem'),__('Location','dbem')); ?></strong></td></tr><?php
167
+ em_options_radio_binary ( sprintf(__( 'Locations on main blog?', 'dbem'), __('locations','dbem')), 'dbem_ms_mainblog_locations', __('If you would prefer all your locations to belong to your main blog, users in sub-sites will still be able to create locations, but the actual locations are created and reside in the main blog.','dbem') );
168
+ ?>
169
+ </tbody>
170
+ <tbody class="em-global-options em-global-locations">
171
+ <?php
172
+ em_options_radio_binary ( sprintf(__( 'Display global %s on main blog?', 'dbem'), __('locations','dbem')), 'dbem_ms_global_locations', sprintf($global_post_tip, __('locations','dbem'), __('locations','dbem')) );
173
+ em_options_radio_binary ( sprintf(__( 'Link sub-site %s directly to sub-site?', 'dbem'), __('locations','dbem')), 'dbem_ms_global_locations_links', sprintf($global_link_tip, __('locations','dbem'), __('location','dbem')).sprintf($global_link_tip2, __('location','dbem'), $options_page_link) );
174
+ em_options_input_text ( sprintf(__( 'Global %s slug', 'dbem' ),__('event','dbem')), 'dbem_ms_locations_slug', sprintf($global_slug_tip, __('Locations','dbem'), __('locations','dbem')).__('Example:','dbem').'<code>http://yoursite.com/locations/<strong>location</strong>/subsite-location-slug/', EM_LOCATION_SLUG );
175
+ ?>
176
+ </tbody>
177
+ <?php echo $save_button; ?>
178
+ </table>
179
+
180
+ </div> <!-- . inside -->
181
+ </div> <!-- .postbox -->
182
+
183
+ <?php
184
+ //including shared MS/non-MS boxes
185
+ em_admin_option_box_caps();
186
+ em_admin_option_box_image_sizes();
187
+ em_admin_option_box_email();
188
+ em_admin_option_box_anon_events();
189
+ em_admin_option_box_uninstall();
190
+ ?>
191
+
192
+ <?php do_action('em_ms_options_page_footer'); ?>
193
+ </div> <!-- .em-menu-general -->
194
+
195
+ <div class="em-menu-pages em-menu-group" style="display:none;">
196
+
197
+ </div> <!-- .em-menu-pages -->
198
+
199
+ <p class="submit">
200
+ <input type="submit" id="dbem_options_submit" name="Submit" value="<?php _e ( 'Save Changes' )?>" />
201
+ <input type="hidden" name="em-submitted" value="1" />
202
+ <input type="hidden" name="_wpnonce" value="<?php echo wp_create_nonce('events-manager-options'); ?>" />
203
+ </p>
204
+
205
+ </div> <!-- .metabox-sortables -->
206
+ </div> <!-- .postbox-container -->
207
+
208
+ </div> <!-- .metabox-holder -->
209
+ </form>
210
+ </div>
211
+ <?php
212
+ }
213
+ ?>
admin/em-options.php CHANGED
@@ -2,7 +2,12 @@
2
 
3
  //Function composing the options subpanel
4
  function em_options_save(){
5
- if( current_user_can('activate_plugins') && !empty($_POST['em-submitted']) ){
 
 
 
 
 
6
  //Build the array of options here
7
  $post = $_POST;
8
  foreach ($_POST as $postKey => $postValue){
@@ -13,40 +18,170 @@ function em_options_save(){
13
  //Do nothing, keep old setting.
14
  }else{
15
  //TODO slashes being added?
16
- //$postValue = EM_Object::sanitize($postValue)
17
  update_option($postKey, stripslashes($postValue));
18
  }
19
  }
20
  }
21
- function em_options_saved_notice(){
22
- ?>
23
- <div class="updated"><p><strong><?php _e('Changes saved.'); ?></strong></p></div>
24
- <?php
 
 
 
 
 
 
 
 
25
  }
26
- add_action ( 'admin_notices', 'em_options_saved_notice' );
27
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
  }
29
- add_action('admin_head', 'em_options_save');
30
-
31
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
 
33
  function em_admin_options_page() {
 
 
 
 
 
 
 
 
 
 
34
  //TODO place all options into an array
35
- $events_placeholders = '<a href="admin.php?page=events-manager-help#event-placeholders">'. __('Event Related Placeholders','dbem') .'</a>';
36
- $locations_placeholders = '<a href="admin.php?page=events-manager-help#location-placeholders">'. __('Location Related Placeholders','dbem') .'</a>';
37
- $bookings_placeholders = '<a href="admin.php?page=events-manager-help#booking-placeholders">'. __('Booking Related Placeholders','dbem') .'</a>';
 
38
  $events_placeholder_tip = " ". sprintf(__('This accepts %s and %s placeholders.','dbem'),$events_placeholders, $locations_placeholders);
39
  $locations_placeholder_tip = " ". sprintf(__('This accepts %s placeholders.','dbem'), $locations_placeholders);
 
40
  $bookings_placeholder_tip = " ". sprintf(__('This accepts %s, %s and %s placeholders.','dbem'), $bookings_placeholders, $events_placeholders, $locations_placeholders);
41
 
42
- $save_button = '<tr><th>&nbsp;</th><td><p class="submit" style="margin:0px; padding:0px; text-align:right;"><input type="submit" id="dbem_options_submit" name="Submit" value="'. __( 'Save Changes' ) .' ('. __('All','dbem') .')" /></p></ts></td></tr>';
43
- ?>
 
44
  <script type="text/javascript" charset="utf-8">
45
  jQuery(document).ready(function($){
 
46
  var close_text = '<?php _e('Collapse All','dbem'); ?>';
47
  var open_text = '<?php _e('Expand All','dbem'); ?>';
48
- var open_close = $('<a href="#" style="display:block; float:right; clear:right; margin:10px;">'+close_text+'</a>');
49
- $('#icon-options-general').after(open_close);
50
  open_close.click( function(e){
51
  e.preventDefault();
52
  if($(this).text() == close_text){
@@ -57,103 +192,328 @@ function em_admin_options_page() {
57
  $(this).text(close_text);
58
  }
59
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60
  //For rewrite titles
61
  $('input:radio[name=dbem_disable_title_rewrites]').live('change',function(){
62
  checked_check = $('input:radio[name=dbem_disable_title_rewrites]:checked');
63
  if( checked_check.val() == 1 ){
64
  $('#dbem_title_html_row').show();
65
  }else{
66
- $('#dbem_title_html_row').hide();
67
  }
68
  });
69
  $('input:radio[name=dbem_disable_title_rewrites]').trigger('change');
70
-
71
  });
72
  </script>
73
- <div class="wrap">
74
- <div id='icon-options-general' class='icon32'><br />
75
- </div>
76
- <h2><?php _e ( 'Event Manager Options', 'dbem' ); ?></h2>
77
-
78
- <form id="dbem_options_form" method="post" action="">
79
-
 
 
 
 
 
 
 
 
80
  <div class="metabox-holder">
81
  <!-- // TODO Move style in css -->
82
  <div class='postbox-container' style='width: 99.5%'>
83
- <div id="" class="meta-box-sortables" >
84
 
85
- <div class="postbox " >
86
- <div class="handlediv" title="<?php __('Click to toggle'); ?>"><br /></div><h3 class='hndle'><span><?php _e ( 'General options', 'dbem' ); ?> </span></h3>
87
- <div class="inside">
88
- <table class="form-table">
89
- <?php
90
- em_options_radio_binary ( __( 'Use dropdown for locations?' ), 'dbem_use_select_for_locations', __( 'Select yes to select location from a drow-down menu; location selection will be faster, but you will lose the ability to insert locations with events','dbem' ) );
91
- em_options_radio_binary ( __( 'Use recurrence?' ), 'dbem_recurrence_enabled', __( 'Select yes to enable the recurrence features feature','dbem' ) );
92
- em_options_radio_binary ( __( 'Use RSVP?' ), 'dbem_rsvp_enabled', __( 'Select yes to enable the RSVP feature','dbem' ) );
93
- em_options_radio_binary ( __( 'Use categories?' ), 'dbem_categories_enabled', __( 'Select yes to enable the category features','dbem' ) );
94
- em_options_radio_binary ( __( 'Use attributes?' ), 'dbem_attributes_enabled', __( 'Select yes to enable the attributes feature','dbem' ) );
95
-
96
- /*default category*/
97
- $category_options = array();
98
- $category_options[0] = __('no default category','dbem');
99
- $EM_Categories = EM_Categories::get();
100
- foreach($EM_Categories as $EM_Category){
101
- $category_options[$EM_Category->id] = $EM_Category->name;
102
- }
103
- em_options_select ( __( 'Default Category' ), 'dbem_default_category', $category_options, __( 'This option allows you to select the default category when adding an event.','dbem' )." ".__('(not applicable with event ownership on presently, coming soon!)','dbem') );
104
-
105
- /*default location*/
106
- $location_options = array();
107
- $location_options[0] = __('no default location','dbem');
108
- $EM_Locations = EM_Locations::get();
109
- foreach($EM_Locations as $EM_Location){
110
- $location_options[$EM_Location->id] = $EM_Location->name;
111
- }
112
- em_options_select ( __( 'Default Location' ), 'dbem_default_location', $location_options, __( 'This option allows you to select the default location when adding an event.','dbem' )." ".__('(not applicable with event ownership on presently, coming soon!)','dbem') );
113
-
114
- em_options_textarea ( __( 'Custom Placeholders', 'dbem' ), 'dbem_placeholders_custom', sprintf(__( "You can add custom placeholders here, one per line in this format <code>#_ATT{key}</code>. They will not appear on event pages unless you insert them into another template below, but you may want to store extra information about an event for other uses. <a href='%s'>More information on placeholders.</a>", 'dbem' ), 'wp-events-plugin.com/documentation/the-em-templates-syntax/') );
115
-
116
- echo $save_button;
117
- ?>
118
- </table>
119
-
120
- </div> <!-- . inside -->
121
- </div> <!-- .postbox -->
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
122
 
123
- <div class="postbox " >
124
- <div class="handlediv" title="<?php __('Click to toggle'); ?>"><br /></div><h3 class='hndle'><span><?php _e ( 'Events page', 'dbem' ); ?> </span></h3>
125
- <div class="inside">
126
- <table class="form-table">
127
- <?php
128
- //Wordpress Pages
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
129
  global $em_disable_filter; //Using a flag here instead
130
  $em_disable_filter = true;
131
  $get_pages = get_pages();
132
  $events_page_options = array();
133
- $events_page_options[0] = __('[No Events Page]');
134
  //TODO Add the hierarchy style ddm, like when choosing page parents
135
  foreach($get_pages as $page){
136
  $events_page_options[$page->ID] = $page->post_title;
137
  }
138
- em_options_select ( __( 'Events page' ), 'dbem_events_page', $events_page_options, __( 'This option allows you to select which page to use as an events page','dbem' ) );
139
  $em_disable_filter = false;
140
- //Rest
141
- em_options_radio_binary ( __( 'Show events page in lists?', 'dbem' ), 'dbem_list_events_page', __( 'Check this option if you want the events page to appear together with other pages in pages lists.', 'dbem' ) );
142
- em_options_radio_binary ( __( 'Display calendar in events page?', 'dbem' ), 'dbem_display_calendar_in_events_page', __( 'This options allows to display the calendar in the events page, instead of the default list. It is recommended not to display both the calendar widget and a calendar page.','dbem' ).' '.__('If you would like to show events that span over more than one day, see the Calendar section on this page.','dbem') );
143
- em_options_radio_binary ( __( 'Disable title rewriting?', 'dbem' ), 'dbem_disable_title_rewrites', __( "Some wordpress themes don't follow best practices when generating navigation menus, and so the automatic title rewriting feature may cause problems, if your menus aren't working correctly on the event pages, try setting this to 'Yes', and provide an appropriate HTML title format below.",'dbem' ) );
144
- em_options_input_text ( __( 'Event Manager titles', 'dbem' ), 'dbem_title_html', __( "This only setting only matters if you selected 'Yes' to above. You will notice the events page titles aren't being rewritten, and you have a new title underneath the default page name. This is where you control the HTML of this title. Make sure you keep the #_PAGETITLE placeholder here, as that's what is rewritten by events manager. To control what's rewritten in this title, see settings further down for page titles.", 'dbem' ) );
145
- em_options_input_text ( __( 'Event List Limits', 'dbem' ), 'dbem_events_default_limit', __( "This will control how many events are shown on one list by default.", 'dbem' ) );
146
  ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
147
  <tr valign="top" id='dbem_events_default_orderby_row'>
148
  <th scope="row"><?php _e('Default event list ordering','dbem'); ?></th>
149
  <td>
150
  <select name="dbem_events_default_orderby" >
151
  <?php
152
  $orderby_options = apply_filters('em_settings_events_default_orderby_ddm', array(
153
- 'start_date,start_time,name' => __('Order by start date, start time, then event name','dbem'),
154
- 'name,start_date,start_time' => __('Order by name, start date, then start time','dbem'),
155
- 'name,end_date,end_time' => __('Order by name, end date, then end time','dbem'),
156
- 'end_date,end_time,name' => __('Order by end date, end time, then event name','dbem'),
157
  ));
158
  ?>
159
  <?php foreach($orderby_options as $key => $value) : ?>
@@ -186,251 +546,596 @@ function em_admin_options_page() {
186
  <br/>
187
  <em><?php _e('When Events Manager displays lists of events the default behaviour is ordering by start date in ascending order. To change this, modify the values above.','dbem'); ?></em>
188
  </td>
189
- </tr>
190
  <tr valign="top" id='dbem_events_display_time_limit'>
191
- <th scope="row"><?php _e('Event list range limit','dbem'); ?></th>
192
- <td>
193
- <select name="dbem_events_page_time_limit" >
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
194
  <?php
195
- $limit_options = apply_filters('em_settings_events_page_time_limit_ddm', array(
196
- '0' => __('no limit','dbem'),
197
- '1' => __('This month','dbem'),
198
- '2' => __('Next two months','dbem'),
199
- '3' => __('Next three months','dbem'),
200
- '6' => __('Next six months','dbem'),
201
- '12' => __('Next twelve months','dbem')
202
  ));
203
  ?>
204
- <?php foreach( $limit_options as $key => $value) : ?>
205
- <option value='<?php echo $key ?>' <?php echo ($key == get_option('dbem_events_page_time_limit')) ? "selected='selected'" : ''; ?>>
206
- <?php echo $value; ?>
207
- </option>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
208
  <?php endforeach; ?>
209
  </select>
210
- <br />
211
- <em><?php _e('Only show events starting within a certain time limit on the events page. Default is no time limit is applied.','dbem'); ?></em>
212
  </td>
213
- </tr>
214
- <?php
215
- echo $save_button;
216
- ?>
217
- </table>
218
- </div> <!-- . inside -->
219
- </div> <!-- .postbox -->
220
-
221
- <div class="postbox " >
222
- <div class="handlediv" title="<?php __('Click to toggle'); ?>"><br /></div><h3 class='hndle'><span><?php _e ( 'Events format', 'dbem' ); ?> </span></h3>
223
- <div class="inside">
224
- <table class="form-table">
225
- <?php
226
- em_options_textarea ( __( 'Default event list format header', 'dbem' ), 'dbem_event_list_item_format_header', __( 'This content will appear just above your code for the default event list format. Default is blank', 'dbem' ) );
227
- em_options_textarea ( __( 'Default event list format', 'dbem' ), 'dbem_event_list_item_format', __( 'The format of any events in a list.', 'dbem' ).$events_placeholder_tip );
228
- em_options_textarea ( __( 'Default event list format footer', 'dbem' ), 'dbem_event_list_item_format_footer', __( 'This content will appear just below your code for the default event list format. Default is blank', 'dbem' ) );
229
- em_options_input_text ( __( 'Single event page title format', 'dbem' ), 'dbem_event_page_title_format', __( 'The format of a single event page title.', 'dbem' ).$events_placeholder_tip );
230
- em_options_textarea ( __( 'Default single event format', 'dbem' ), 'dbem_single_event_format', __( 'The format of a single event page.', 'dbem' ).$events_placeholder_tip );
231
- em_options_input_text ( __( 'Events page title', 'dbem' ), 'dbem_events_page_title', __( 'The title on the multiple events page.', 'dbem' ) );
232
- em_options_input_text ( __( 'No events message', 'dbem' ), 'dbem_no_events_message', __( 'The message displayed when no events are available.', 'dbem' ) );
233
- em_options_input_text ( __( 'List events by date title', 'dbem' ), 'dbem_list_date_title', __( 'If viewing a page for events on a specific date, this is the title that would show up. To insert date values, use <a href="http://www.php.net/manual/en/function.date.php">PHP time format characters</a> with a <code>#</code> symbol before them, i.e. <code>#m</code>, <code>#M</code>, <code>#j</code>, etc.<br/>', 'dbem' ) );
234
- echo $save_button;
235
- ?>
236
- </table>
237
- </div> <!-- . inside -->
238
- </div> <!-- .postbox -->
239
-
240
- <div class="postbox " >
241
- <div class="handlediv" title="<?php __('Click to toggle'); ?>"><br /></div><h3 class='hndle'><span><?php _e ( 'Calendar format', 'dbem' ); ?></span></h3>
242
- <div class="inside">
243
- <table class="form-table">
244
- <?php
245
- em_options_input_text ( __( 'Small calendar title', 'dbem' ), 'dbem_small_calendar_event_title_format', __( 'The format of the title, corresponding to the text that appears when hovering on an eventful calendar day.', 'dbem' ).$events_placeholder_tip );
246
- em_options_input_text ( __( 'Small calendar title separator', 'dbem' ), 'dbem_small_calendar_event_title_separator', __( 'The separator appearing on the above title when more than one events are taking place on the same day.', 'dbem' ) );
247
- em_options_input_text ( __( 'Full calendar events format', 'dbem' ), 'dbem_full_calendar_event_format', __( 'The format of each event when displayed in the full calendar. Remember to include <code>li</code> tags before and after the event.', 'dbem' ).$events_placeholder_tip );
248
- em_options_radio_binary ( __( 'Show long events on calendar pages?', 'dbem' ), 'dbem_full_calendar_long_events', __( "If you are showing a calendar on the events page (see Events format section on this page), you have the option of showing events that span over days on each day it occurs.",'dbem' ) );
249
- em_options_radio_binary ( __( 'Show list on day with single event?', 'dbem' ), 'dbem_display_calendar_day_single', __( "By default, if a calendar day only has one event, it display a single event when clicking on the link of that calendar date. If you select Yes here, you will get always see a list of events.",'dbem' ) );
250
- echo $save_button;
251
- ?>
252
- </table>
253
- </div> <!-- . inside -->
254
- </div> <!-- .postbox -->
255
-
256
- <div class="postbox " >
257
- <div class="handlediv" title="<?php __('Click to toggle'); ?>"><br /></div><h3 class='hndle'><span><?php _e ( 'Locations format', 'dbem' ); ?> </span></h3>
258
- <div class="inside">
259
- <table class="form-table">
260
- <?php
261
- em_options_input_text ( __( 'Single location page title format', 'dbem' ), 'dbem_location_page_title_format', __( 'The format of a single location page title.', 'dbem' ).$locations_placeholder_tip );
262
- em_options_textarea ( __( 'Default single location page format', 'dbem' ), 'dbem_single_location_format', __( 'The format of a single location page.', 'dbem' ).$locations_placeholder_tip );
263
- em_options_textarea ( __( 'Default location balloon format', 'dbem' ), 'dbem_location_baloon_format', __( 'The format of of the text appearing in the baloon describing the location in the map.', 'dbem' ).$locations_placeholder_tip );
264
- em_options_textarea ( __( 'Default location event list format', 'dbem' ), 'dbem_location_event_list_item_format', __( 'The format of the events the list inserted in the location page through the <code>#_NEXTEVENTS</code>, <code>#_PASTEVENTS</code> and <code>#_ALLEVENTS</code> element.', 'dbem' ).$locations_placeholder_tip );
265
- em_options_textarea ( __( 'Default no events message', 'dbem' ), 'dbem_location_no_events_message', __( 'The message to be displayed in the list generated by <code>#_NEXTEVENTS</code>, <code>#_PASTEVENTS</code> and <code>#_ALLEVENTS</code> when no events are available.', 'dbem' ) );
266
- echo $save_button;
267
- ?>
268
- </table>
269
- </div> <!-- . inside -->
270
- </div> <!-- .postbox -->
271
-
272
- <div class="postbox " >
273
- <div class="handlediv" title="<?php __('Click to toggle'); ?>"><br /></div><h3 class='hndle'><span><?php _e ( 'RSS feed format', 'dbem' ); ?> </span></h3>
274
- <div class="inside">
275
- <table class="form-table">
276
- <?php
277
- em_options_input_text ( __( 'RSS main title', 'dbem' ), 'dbem_rss_main_title', __( 'The main title of your RSS events feed.', 'dbem' ).$events_placeholder_tip );
278
- em_options_input_text ( __( 'RSS main description', 'dbem' ), 'dbem_rss_main_description', __( 'The main description of your RSS events feed.', 'dbem' ) );
279
- em_options_input_text ( __( 'RSS title format', 'dbem' ), 'dbem_rss_title_format', __( 'The format of the title of each item in the events RSS feed.', 'dbem' ).$events_placeholder_tip );
280
- em_options_input_text ( __( 'RSS description format', 'dbem' ), 'dbem_rss_description_format', __( 'The format of the description of each item in the events RSS feed.', 'dbem' ).$events_placeholder_tip );
281
- echo $save_button;
282
- ?>
283
- </table>
284
- </div> <!-- . inside -->
285
- </div> <!-- .postbox -->
286
-
287
- <div class="postbox " >
288
- <div class="handlediv" title="<?php __('Click to toggle'); ?>"><br /></div><h3 class='hndle'><span><?php _e ( 'Maps and geotagging', 'dbem' ); ?> </span></h3>
289
- <div class="inside">
290
- <table class='form-table'>
291
- <?php $gmap_is_active = get_option ( 'dbem_gmap_is_active' ); ?>
292
- <tr valign="top">
293
- <th scope="row"><?php _e ( 'Enable Google Maps integration?', 'dbem' ); ?></th>
294
- <td>
295
- <?php _e ( 'Yes' ); ?> <input id="dbem_gmap_is_active_yes" name="dbem_gmap_is_active" type="radio" value="1" <?php echo ($gmap_is_active) ? "checked='checked'":''; ?> />
296
- <?php _e ( 'No' ); ?> <input name="dbem_gmap_is_active" type="radio" value="0" <?php echo ($gmap_is_active) ? '':"checked='checked'"; ?> /><br />
297
- <em><?php _e ( 'Check this option to enable Goggle Map integration.', 'dbem' )?></em>
298
  </td>
299
  </tr>
300
- <?php
301
- em_options_textarea ( __( 'Map text format', 'dbem' ), 'dbem_map_text_format', __( 'The text format inside the map balloons.', 'dbem' ).$events_placeholder_tip );
302
- echo $save_button;
303
- ?>
304
- </table>
305
- </div> <!-- . inside -->
306
- </div> <!-- .postbox -->
307
-
308
- <div class="postbox " >
309
- <div class="handlediv" title="<?php __('Click to toggle'); ?>"><br /></div><h3 class='hndle'><span><?php _e ( 'RSVP and bookings', 'dbem' ); ?> </span></h3>
310
- <div class="inside">
311
- <table class='form-table'>
312
- <?php
313
- em_options_select ( __( 'Default contact person', 'dbem' ), 'dbem_default_contact_person', em_get_wp_users (), __( 'Select the default contact person. This user will be employed whenever a contact person is not explicitly specified for an event', 'dbem' ) );
314
- em_options_radio_binary ( __( 'Approval Required?', 'dbem' ), 'dbem_bookings_approval', __( 'Bookings will not be confirmed until the event administrator approves it.', 'dbem' ) );
315
- em_options_input_text ( __( 'Email events admin?', 'dbem' ), 'dbem_bookings_notify_admin', __( "If you would like every event booking confirmation email sent to an administrator write their email here (leave blank to not send an email).", 'dbem' ) );
316
- em_options_radio_binary ( __( 'Email contact person?', 'dbem' ), 'dbem_bookings_contact_email', __( 'Check this option if you want the event contact to receive an email when someone books places. An email will be sent when a booking is first made (regardless if confirmed or pending)', 'dbem' ) );
317
- ?>
318
- <tr><td colspan='2'><h4><?php _e('Contact person booking confirmed','dbem') ?></h4></td></tr>
319
- <tr><td colspan='2'><?php echo __('An email will be sent to the event contact when a booking is first made.','dbem').$bookings_placeholder_tip ?></td></tr>
320
- <?php
321
- em_options_input_text ( __( 'Contact person email subject', 'dbem' ), 'dbem_bookings_contact_email_subject', '' );
322
- em_options_textarea ( __( 'Contact person email', 'dbem' ), 'dbem_bookings_contact_email_body', '' );
323
- ?>
324
- <tr><td colspan='2'><h4><?php _e('Contact person booking cancelled','dbem') ?></h4></td></tr>
325
- <tr><td colspan='2'><?php echo __('An email will be sent to the event contact if someone cancels their booking.','dbem').$bookings_placeholder_tip ?></td></tr>
326
- <?php
327
- em_options_input_text ( __( 'Contact person cancellation subject', 'dbem' ), 'dbem_contactperson_email_cancelled_subject', '' );
328
- em_options_textarea ( __( 'Contact person cancellation email', 'dbem' ), 'dbem_contactperson_email_cancelled_body', '' );
329
  ?>
330
- <tr><td colspan='2'><h4><?php _e('Confirmed booking email','dbem') ?></h4></td></tr>
331
- <tr><td colspan='2'><?php echo __('This is sent when a person\'s booking is confirmed. This will be sent automatically if approvals are required and the booking is approved. If approvals are disabled, this is sent out when a user first submits their booking.','dbem').$bookings_placeholder_tip ?></td></tr>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
332
  <?php
333
- em_options_input_text ( __( 'Booking confirmed email subject', 'dbem' ), 'dbem_bookings_email_confirmed_subject', '' );
334
- em_options_textarea ( __( 'Booking confirmed email', 'dbem' ), 'dbem_bookings_email_confirmed_body', '' );
335
  ?>
336
- <tr><td colspan='2'><h4><?php _e('Pending booking email','dbem') ?></h4></td></tr>
337
- <tr><td colspan='2'><?php echo __( 'This will be sent to the person when they first submit their booking. Not relevant if bookings don\'t require approval.', 'dbem' ).$bookings_placeholder_tip ?></td></tr>
338
- <?php
339
- em_options_input_text ( __( 'Booking pending email subject', 'dbem' ), 'dbem_bookings_email_pending_subject', '');
340
- em_options_textarea ( __( 'Booking pending email', 'dbem' ), 'dbem_bookings_email_pending_body','') ;
 
 
 
 
 
 
 
 
341
  ?>
342
- <tr><td colspan='2'><h4><?php _e('Rejected booking email','dbem') ?></h4></td></tr>
343
- <tr><td colspan='2'><?php echo __( 'This will be sent automatically when a booking is rejected. Not relevant if bookings don\'t require approval.', 'dbem' ).$bookings_placeholder_tip ?></td></tr>
 
 
 
 
 
 
 
 
344
  <?php
345
- em_options_input_text ( __( 'Booking rejected email subject', 'dbem' ), 'dbem_bookings_email_rejected_subject', __( "The subject of the email sent to the person making a booking that is awaiting administrator approval. Not relevant if bookings don't require approval.", 'dbem' ).$bookings_placeholder_tip );
346
- em_options_textarea ( __( 'Booking rejected email', 'dbem' ), 'dbem_bookings_email_rejected_body', __( 'The body of the email which will be sent to the person if the booking is rejected. Not relevant if bookings don\'t require approval.', 'dbem' ).$bookings_placeholder_tip );
347
- echo $save_button;
348
  ?>
349
- <tr><td colspan='2'><h4><?php _e('Booking cancelled','dbem') ?></h4></td></tr>
350
- <tr><td colspan='2'><?php echo __('This will be sent when a user cancels their booking.','dbem').$bookings_placeholder_tip ?></td></tr>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
351
  <?php
352
- em_options_input_text ( __( 'Booking cancelled email subject', 'dbem' ), 'dbem_bookings_email_cancelled_subject', '' );
353
- em_options_textarea ( __( 'Booking cancelled email', 'dbem' ), 'dbem_bookings_email_cancelled_body', '' );
354
  ?>
355
- </table>
356
- </div> <!-- . inside -->
357
- </div> <!-- .postbox -->
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
358
 
359
- <div class="postbox " >
360
- <div class="handlediv" title="<?php __('Click to toggle'); ?>"><br /></div><h3 class='hndle'><span><?php _e ( 'Email Settings', 'dbem' ); ?> </span></h3>
361
- <div class="inside">
362
- <table class='form-table'>
363
- <?php
364
- em_options_input_text ( __( 'Notification sender name', 'dbem' ), 'dbem_mail_sender_name', __( "Insert the display name of the notification sender.", 'dbem' ) );
365
- em_options_input_text ( __( 'Notification sender address', 'dbem' ), 'dbem_mail_sender_address', __( "Insert the address of the notification sender.", 'dbem' ) );
366
- em_options_input_text ( 'Mail sending port', 'dbem_rsvp_mail_port', __( "The port through which you e-mail notifications will be sent. Make sure the firewall doesn't block this port", 'dbem' ) );
367
- em_options_select ( __( 'Mail sending method', 'dbem' ), 'dbem_rsvp_mail_send_method', array ('smtp' => 'SMTP', 'mail' => __( 'PHP mail function', 'dbem' ), 'sendmail' => 'Sendmail', 'qmail' => 'Qmail', 'wp_mail' => 'WP Mail' ), __( 'Select the method to send email notification.', 'dbem' ) );
368
- em_options_radio_binary ( __( 'Use SMTP authentication?', 'dbem' ), 'dbem_rsvp_mail_SMTPAuth', __( 'SMTP authentication is often needed. If you use GMail, make sure to set this parameter to Yes', 'dbem' ) );
369
- em_options_input_text ( 'SMTP host', 'dbem_smtp_host', __( "The SMTP host. Usually it corresponds to 'localhost'. If you use GMail, set this value to 'ssl://smtp.gmail.com:465'.", 'dbem' ) );
370
- em_options_input_text ( __( 'SMTP username', 'dbem' ), 'dbem_smtp_username', __( "Insert the username to be used to access your SMTP server.", 'dbem' ) );
371
- em_options_input_password ( __( 'SMTP password', 'dbem' ), "dbem_smtp_password", __( "Insert the password to be used to access your SMTP server", 'dbem' ) );
372
- echo $save_button;
373
- ?>
374
- </table>
375
- </div> <!-- . inside -->
376
- </div> <!-- .postbox -->
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
377
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
378
  <div class="postbox " >
379
- <div class="handlediv" title="<?php __('Click to toggle'); ?>"><br /></div><h3 class='hndle'><span><?php _e ( 'Images size', 'dbem' ); ?> </span></h3>
380
  <div class="inside">
381
  <table class='form-table'>
382
  <?php
383
- em_options_input_text ( __( 'Maximum width (px)', 'dbem' ), 'dbem_image_max_width', __( 'The maximum allowed width for images uploades', 'dbem' ) );
384
- em_options_input_text ( __( 'Maximum height (px)', 'dbem' ), 'dbem_image_max_height', __( "The maximum allowed height for images uploaded, in pixels", 'dbem' ) );
385
- em_options_input_text ( __( 'Maximum size (bytes)', 'dbem' ), 'dbem_image_max_size', __( "The maximum allowed size for images uploaded, in pixels", 'dbem' ) );
386
- echo $save_button;
387
  ?>
388
- </table>
389
  </div> <!-- . inside -->
390
  </div> <!-- .postbox -->
 
391
 
392
- <div class="postbox " >
393
- <div class="handlediv" title="<?php __('Click to toggle'); ?>"><br /></div><h3 class='hndle'><span><?php _e ( 'Management Permission Options', 'dbem' ); ?> (Beta)</span></h3>
394
- <div class="inside">
395
- <table class="form-table">
396
- <tr><td colspan="2">
397
- <strong><?php _e('Warning: Changing these values may result in exposing previously hidden information to all users.')?></strong><br />
398
- <em><?php _e('Note that currently "users" are considered as wordpress contributor users upwards, as they can create and manage events (we\'re working on that). Wordpress administrators can control all events/locations/categories/etc. on Events Manager.','dbem'); ?></em>
399
- </td></tr>
400
- <tr><th colspan="2"><strong><?php _e('Event Permissions','dbem'); ?></strong></th></tr>
401
- <?php
402
- $location_privacy_options = array(
403
- '0' => __('Every user can create and manage their own events. Users can\'t view or modify each others\' events and booking data','dbem'),
404
- '1' => __('Every user can create/edit/delete any event on this site. (not recommended)','dbem')
405
- );
406
- em_options_radio ( 'dbem_permissions_events', $location_privacy_options );
407
- ?>
408
- <tr><th colspan="2"><strong><?php _e('Location Permissions','dbem'); ?></strong></th></tr>
409
- <?php
410
- $location_privacy_options = array(
411
- '0' => __('Every user can create and manage their own location.','dbem')." ".__('In future releases of Events Manager, sharing locations with more than one user will be possible in this option, as well as connecting different user defined locations to prevent duplicate listings.','dbem'),
412
- '1' => __('Only event administrators can create and edit locations. User must choose from these available locations.','dbem'),
413
- '2' => __('Everyone can create/edit/delete all locations on this site. (not recommended)','dbem')
414
- );
415
- em_options_radio ( 'dbem_permissions_locations', $location_privacy_options );
416
- ?>
417
- <tr><th colspan="2"><strong><?php _e('Category Permissions','dbem'); ?></strong></th></tr>
418
- <?php
419
- $category_privacy_options = array(
420
- '0' => __('Every user can create and manage their own category.','dbem'),
421
- '1' => __('Only event administrators can create and edit categories. User must choose from these available categories.','dbem'),
422
- '2' => __('Everyone can create/edit/delete all categories on the system. (not recommended)','dbem')
423
- );
424
- em_options_radio ( 'dbem_permissions_categories', $category_privacy_options );
425
- ?>
426
- </table>
427
-
428
- </div> <!-- . inside -->
429
- </div> <!-- .postbox -->
430
-
431
  <p class="submit">
432
  <input type="submit" id="dbem_options_submit" name="Submit" value="<?php _e ( 'Save Changes' )?>" />
433
  <input type="hidden" name="em-submitted" value="1" />
 
434
  </p>
435
 
436
  </div> <!-- .metabox-sortables -->
@@ -441,4 +1146,199 @@ function em_admin_options_page() {
441
  </div>
442
  <?php
443
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
444
  ?>
2
 
3
  //Function composing the options subpanel
4
  function em_options_save(){
5
+ global $EM_Notices;
6
+ /*
7
+ * Here's the idea, we have an array of all options that need super admin approval if in multi-site mode
8
+ * since options are only updated here, its one place fit all
9
+ */
10
+ if( current_user_can('activate_plugins') && !empty($_POST['em-submitted']) && check_admin_referer('events-manager-options','_wpnonce') ){
11
  //Build the array of options here
12
  $post = $_POST;
13
  foreach ($_POST as $postKey => $postValue){
18
  //Do nothing, keep old setting.
19
  }else{
20
  //TODO slashes being added?
 
21
  update_option($postKey, stripslashes($postValue));
22
  }
23
  }
24
  }
25
+ //set capabilities
26
+ if( !empty($_POST['em_capabilities']) && is_array($_POST['em_capabilities']) && (!is_multisite() || is_multisite() && is_super_admin()) ){
27
+ global $em_capabilities_array, $wp_roles;
28
+ foreach( $wp_roles->role_objects as $role_name => $role ){
29
+ foreach( array_keys($em_capabilities_array) as $capability){
30
+ if( !empty($_POST['em_capabilities'][$role_name][$capability]) ){
31
+ $role->add_cap($capability);
32
+ }else{
33
+ $role->remove_cap($capability);
34
+ }
35
+ }
36
+ }
37
  }
38
+ update_option('dbem_flush_needed',1);
39
+ do_action('em_options_save');
40
+ $EM_Notices->add_confirm('<strong>'.__('Changes saved.', 'dbem').'</strong>', true);
41
+ wp_redirect(wp_get_referer());
42
+ exit();
43
+ }
44
+ //Migration
45
+ if( !empty($_GET['em_migrate_images']) && check_admin_referer('em_migrate_images','_wpnonce') && get_option('dbem_migrate_images') ){
46
+ include(plugin_dir_path(__FILE__).'../em-install.php');
47
+ $result = em_migrate_uploads();
48
+ if($result){
49
+ $failed = ( $result['fail'] > 0 ) ? $result['fail'] . ' images failed to migrate.' : '';
50
+ $EM_Notices->add_confirm('<strong>'.$result['success'].' images migrated successfully. '.$failed.'</strong>');
51
+ }
52
+ wp_redirect(admin_url().'edit.php?post_type=event&page=events-manager-options&em_migrate_images');
53
+ }elseif( !empty($_GET['em_not_migrate_images']) && check_admin_referer('em_not_migrate_images','_wpnonce') ){
54
+ delete_option('dbem_migrate_images_nag');
55
+ delete_option('dbem_migrate_images');
56
+ }
57
+ //Uninstall
58
+ if( !empty($_REQUEST['action']) && $_REQUEST['action'] == 'uninstall' && !empty($_REQUEST['confirmed']) && check_admin_referer('em_uninstall_'.get_current_user_id().'_wpnonce') && is_super_admin() ){
59
+ if( check_admin_referer('em_uninstall_'.get_current_user_id().'_confirmed','_wpnonce2') ){
60
+ //We have a go to uninstall
61
+ global $wpdb;
62
+ //delete EM posts
63
+ remove_action('before_delete_post',array('EM_Location_Post_Admin','before_delete_post'),10,1);
64
+ remove_action('before_delete_post',array('EM_Event_Post_Admin','before_delete_post'),10,1);
65
+ remove_action('before_delete_post',array('EM_Event_Recurring_Post_Admin','before_delete_post'),10,1);
66
+ $post_ids = $wpdb->get_col('SELECT ID FROM '.$wpdb->posts." WHERE post_type IN ('".EM_POST_TYPE_EVENT."','".EM_POST_TYPE_LOCATION."','event-recurring')");
67
+ foreach($post_ids as $post_id){
68
+ wp_delete_post($post_id);
69
+ }
70
+ //delete categories
71
+ $cat_terms = get_terms(EM_TAXONOMY_CATEGORY, array('hide_empty'=>false));
72
+ foreach($cat_terms as $cat_term){
73
+ wp_delete_term($cat_term->term_id, EM_TAXONOMY_CATEGORY);
74
+ }
75
+ $tag_terms = get_terms(EM_TAXONOMY_TAG, array('hide_empty'=>false));
76
+ foreach($tag_terms as $tag_term){
77
+ wp_delete_term($tag_term->term_id, EM_TAXONOMY_TAG);
78
+ }
79
+ //delete EM tables
80
+ $wpdb->query('DROP TABLE '.EM_EVENTS_TABLE);
81
+ $wpdb->query('DROP TABLE '.EM_BOOKINGS_TABLE);
82
+ $wpdb->query('DROP TABLE '.EM_LOCATIONS_TABLE);
83
+ $wpdb->query('DROP TABLE '.EM_TICKETS_TABLE);
84
+ $wpdb->query('DROP TABLE '.EM_TICKETS_BOOKINGS_TABLE);
85
+ $wpdb->query('DROP TABLE '.EM_RECURRENCE_TABLE);
86
+ $wpdb->query('DROP TABLE '.EM_CATEGORIES_TABLE);
87
+ $wpdb->query('DROP TABLE '.EM_META_TABLE);
88
+
89
+ //delete options
90
+ $wpdb->query('DELETE FROM '.$wpdb->options.' WHERE option_name LIKE \'em_%\' OR option_name LIKE \'dbem_%\'');
91
+ //deactivate and go!
92
+ deactivate_plugins(array('events-manager/events-manager.php','events-manager-pro/events-manager-pro.php'), true);
93
+ wp_redirect(admin_url('plugins.php?deactivate=true'));
94
+ exit();
95
+ }
96
+ }
97
+ //Reset
98
+ if( !empty($_REQUEST['action']) && $_REQUEST['action'] == 'reset' && !empty($_REQUEST['confirmed']) && check_admin_referer('em_reset_'.get_current_user_id().'_wpnonce') && is_super_admin() ){
99
+ if( check_admin_referer('em_reset_'.get_current_user_id().'_confirmed','_wpnonce2') ){
100
+ //We have a go to uninstall
101
+ global $wpdb;
102
+ //delete options
103
+ $wpdb->query('DELETE FROM '.$wpdb->options.' WHERE option_name LIKE \'em_%\' OR option_name LIKE \'dbem_%\'');
104
+ //reset capabilities
105
+ global $em_capabilities_array, $wp_roles;
106
+ foreach( $wp_roles->role_objects as $role_name => $role ){
107
+ foreach( array_keys($em_capabilities_array) as $capability){
108
+ $role->remove_cap($capability);
109
+ }
110
+ }
111
+ //go back to plugin options page
112
+ $EM_Notices->add_confirm(__('Settings have been reset back to default. Your events, locations and categories have not been modified.','dbem'), true);
113
+ wp_redirect(EM_ADMIN_URL.'&page=events-manager-options');
114
+ exit();
115
+ }
116
+ }
117
  }
118
+ add_action('admin_init', 'em_options_save');
 
119
 
120
+ function em_admin_options_reset_page(){
121
+ if( check_admin_referer('em_reset_'.get_current_user_id().'_wpnonce') && is_super_admin() ){
122
+ ?>
123
+ <div class="wrap">
124
+ <div id='icon-options-general' class='icon32'><br /></div>
125
+ <h2><?php _e('Reset Events Manager','dbem'); ?></h2>
126
+ <p style="color:red; font-weight:bold;"><?php _e('Are you sure you want to reset Events Manager?','dbem')?></p>
127
+ <p style="font-weight:bold;"><?php _e('All your settings, including email templates and template formats for Events Manager will be deleted.','dbem')?></p>
128
+ <p>
129
+ <a href="<?php echo add_query_arg(array('_wpnonce2' => wp_create_nonce('em_reset_'.get_current_user_id().'_confirmed'), 'confirmed'=>1)); ?>" class="button-primary"><?php _e('Reset Events Manager','dbem'); ?></a>
130
+ <a href="<?php echo wp_get_referer(); ?>" class="button-secondary"><?php _e('Cancel','dbem'); ?></a>
131
+ </p>
132
+ </div>
133
+ <?php
134
+ }
135
+ }
136
+ function em_admin_options_uninstall_page(){
137
+ if( check_admin_referer('em_uninstall_'.get_current_user_id().'_wpnonce') && is_super_admin() ){
138
+ ?>
139
+ <div class="wrap">
140
+ <div id='icon-options-general' class='icon32'><br /></div>
141
+ <h2><?php _e('Uninstall Events Manager','dbem'); ?></h2>
142
+ <p style="color:red; font-weight:bold;"><?php _e('Are you sure you want to uninstall Events Manager?','dbem')?></p>
143
+ <p style="font-weight:bold;"><?php _e('All your settings and events will be permanently deleted. This cannot be undone.','dbem')?></p>
144
+ <p><?php echo sprintf(__('If you just want to deactivate the plugin, <a href="%s">go to your plugins page</a>.','dbem'), wp_nonce_url(admin_url('plugins.php'))); ?></p>
145
+ <p>
146
+ <a href="<?php echo add_query_arg(array('_wpnonce2' => wp_create_nonce('em_uninstall_'.get_current_user_id().'_confirmed'), 'confirmed'=>1)); ?>" class="button-primary"><?php _e('Uninstall and Deactivate','dbem'); ?></a>
147
+ <a href="<?php echo wp_get_referer(); ?>" class="button-secondary"><?php _e('Cancel','dbem'); ?></a>
148
+ </p>
149
+ </div>
150
+ <?php
151
+ }
152
+ }
153
 
154
  function em_admin_options_page() {
155
+ global $wpdb, $EM_Notices;
156
+ //Check for uninstall request
157
+ if( !empty($_REQUEST['action']) && $_REQUEST['action'] == 'uninstall' ){
158
+ em_admin_options_uninstall_page();
159
+ return;
160
+ }
161
+ if( !empty($_REQUEST['action']) && $_REQUEST['action'] == 'reset' ){
162
+ em_admin_options_reset_page();
163
+ return;
164
+ }
165
  //TODO place all options into an array
166
+ $events_placeholders = '<a href="'.EM_ADMIN_URL .'&amp;page=events-manager-help#event-placeholders">'. __('Event Related Placeholders','dbem') .'</a>';
167
+ $locations_placeholders = '<a href="'.EM_ADMIN_URL .'&amp;page=events-manager-help#location-placeholders">'. __('Location Related Placeholders','dbem') .'</a>';
168
+ $bookings_placeholders = '<a href="'.EM_ADMIN_URL .'&amp;page=events-manager-help#booking-placeholders">'. __('Booking Related Placeholders','dbem') .'</a>';
169
+ $categories_placeholders = '<a href="'.EM_ADMIN_URL .'&amp;page=events-manager-help#category-placeholders">'. __('Category Related Placeholders','dbem') .'</a>';
170
  $events_placeholder_tip = " ". sprintf(__('This accepts %s and %s placeholders.','dbem'),$events_placeholders, $locations_placeholders);
171
  $locations_placeholder_tip = " ". sprintf(__('This accepts %s placeholders.','dbem'), $locations_placeholders);
172
+ $categories_placeholder_tip = " ". sprintf(__('This accepts %s placeholders.','dbem'), $categories_placeholders);
173
  $bookings_placeholder_tip = " ". sprintf(__('This accepts %s, %s and %s placeholders.','dbem'), $bookings_placeholders, $events_placeholders, $locations_placeholders);
174
 
175
+ global $save_button;
176
+ $save_button = '<tr><th>&nbsp;</th><td><p class="submit" style="margin:0px; padding:0px; text-align:right;"><input type="submit" id="dbem_options_submit" name="Submit" value="'. __( 'Save Changes', 'dbem') .' ('. __('All','dbem') .')" /></p></ts></td></tr>';
177
+ ?>
178
  <script type="text/javascript" charset="utf-8">
179
  jQuery(document).ready(function($){
180
+ //Meta Box Options
181
  var close_text = '<?php _e('Collapse All','dbem'); ?>';
182
  var open_text = '<?php _e('Expand All','dbem'); ?>';
183
+ var open_close = $('<a href="#" style="display:block; float:right; clear:right; margin:10px;">'+open_text+'</a>');
184
+ $('#em-options-title').before(open_close);
185
  open_close.click( function(e){
186
  e.preventDefault();
187
  if($(this).text() == close_text){
192
  $(this).text(close_text);
193
  }
194
  });
195
+ $(".postbox > h3").click(function(){ $(this).parent().toggleClass('closed'); });
196
+ $(".postbox").addClass('closed');
197
+ //Navigation Tabs
198
+ $('.nav-tab-wrapper .nav-tab').click(function(){
199
+ $('.nav-tab-wrapper .nav-tab').removeClass('nav-tab-active');
200
+ el = $(this);
201
+ elid = el.attr('id');
202
+ $('.em-menu-group').hide();
203
+ $('.'+elid).show();
204
+ el.addClass('nav-tab-active');
205
+ $(".postbox").addClass('closed');
206
+ open_close.text(open_text);
207
+ });
208
+ var navUrl = document.location.toString();
209
+ if (navUrl.match('#')) { //anchor-based navigation
210
+ var current_tab = 'a#em-menu-' + navUrl.split('#')[1];
211
+ $(current_tab).trigger('click');
212
+ }
213
+ $('.nav-tab-link').click(function(){ $($(this).attr('rel')).trigger('click'); }); //links to mimick tabs
214
+ //Page Options
215
+ $('input[name="dbem_cp_events_has_archive"]').change(function(){ //event archives
216
+ if( $('input:radio[name="dbem_cp_events_has_archive"]:checked').val() == 1 ){
217
+ $('tbody.em-event-archive-sub-options').show();
218
+ }else{
219
+ $('tbody.em-event-archive-sub-options').hide();
220
+ }
221
+ });
222
+ $('select[name="dbem_events_page"]').change(function(){
223
+ if( $('select[name="dbem_events_page"]').val() == 0 ){
224
+ $('tbody.em-event-page-options').hide();
225
+ $('tbody.em-event-archive-options').show();
226
+ $('input:radio[name="dbem_cp_events_has_archive"]:checked').trigger('change');
227
+ }else{
228
+ $('tbody.em-event-page-options').show();
229
+ $('tbody.em-event-archive-options').hide();
230
+ }
231
+ }).trigger('change');
232
+ $('input[name="dbem_cp_locations_has_archive"]').change(function(){ //location archives
233
+ console.log('changed!');
234
+ if( $('input:radio[name="dbem_cp_locations_has_archive"]:checked').val() == 1 ){
235
+ $('tbody.em-location-archive-sub-options').show();
236
+ }else{
237
+ $('tbody.em-location-archive-sub-options').hide();
238
+ }
239
+ });
240
+ $('select[name="dbem_locations_page"]').change(function(){
241
+ if( $('select[name="dbem_locations_page"]').val() == 0 ){
242
+ $('tbody.em-location-page-options').hide();
243
+ $('tbody.em-location-archive-options').show();
244
+ $('input:radio[name="dbem_cp_locations_has_archive"]:checked').trigger('change');
245
+ }else{
246
+ $('tbody.em-location-page-options').show();
247
+ $('tbody.em-location-archive-options').hide();
248
+ }
249
+ }).trigger('change');
250
  //For rewrite titles
251
  $('input:radio[name=dbem_disable_title_rewrites]').live('change',function(){
252
  checked_check = $('input:radio[name=dbem_disable_title_rewrites]:checked');
253
  if( checked_check.val() == 1 ){
254
  $('#dbem_title_html_row').show();
255
  }else{
256
+ $('#dbem_title_html_row').hide();
257
  }
258
  });
259
  $('input:radio[name=dbem_disable_title_rewrites]').trigger('change');
 
260
  });
261
  </script>
262
+ <style type="text/css">.postbox h3 { cursor:pointer; }</style>
263
+ <div class="wrap">
264
+ <div id='icon-options-general' class='icon32'><br /></div>
265
+ <h2 class="nav-tab-wrapper">
266
+ <a href="#general" id="em-menu-general" class="nav-tab nav-tab-active"><?php _e('General','dbem'); ?></a>
267
+ <a href="#pages" id="em-menu-pages" class="nav-tab"><?php _e('Pages','dbem'); ?></a>
268
+ <a href="#formats" id="em-menu-formats" class="nav-tab"><?php _e('Formats/Layouts','dbem'); ?></a>
269
+ <?php if( get_option('dbem_rsvp_enabled') ): ?>
270
+ <a href="#bookings" id="em-menu-bookings" class="nav-tab"><?php _e('Booking Options','dbem'); ?></a>
271
+ <?php endif; ?>
272
+ <a href="#emails" id="em-menu-emails" class="nav-tab"><?php _e('Emails','dbem'); ?></a>
273
+ </h2>
274
+ <?php echo $EM_Notices; ?>
275
+ <h3 id="em-options-title"><?php _e ( 'Event Manager Options', 'dbem' ); ?></h3>
276
+ <form id="em-options-form" method="post" action="">
277
  <div class="metabox-holder">
278
  <!-- // TODO Move style in css -->
279
  <div class='postbox-container' style='width: 99.5%'>
280
+ <div id="">
281
 
282
+ <div class="em-menu-general em-menu-group">
283
+
284
+ <!-- GENERAL OPTIONS -->
285
+ <div class="postbox " >
286
+ <div class="handlediv" title="<?php __('Click to toggle', 'dbem'); ?>"><br /></div><h3><span><?php _e ( 'General Options', 'dbem' ); ?> </span></h3>
287
+ <div class="inside">
288
+ <table class="form-table">
289
+ <tr>
290
+ <td colspan="2">
291
+ <h4><?php echo sprintf(__('%s Settings','dbem'),__('Event','dbem')); ?></h4>
292
+ </td>
293
+ </tr>
294
+ <?php
295
+ em_options_radio_binary ( __( 'Enable recurrence?', 'dbem' ), 'dbem_recurrence_enabled', __( 'Select yes to enable the recurrence features feature','dbem' ) );
296
+ em_options_radio_binary ( __( 'Enable bookings?', 'dbem' ), 'dbem_rsvp_enabled', __( 'Select yes to allow bookings and tickets for events.','dbem' ) );
297
+ em_options_radio_binary ( __( 'Enable tags?', 'dbem' ), 'dbem_tags_enabled', __( 'Select yes to enable the tag features','dbem' ) );
298
+ if( !(EM_MS_GLOBAL && !is_main_blog()) ){
299
+ em_options_radio_binary ( __( 'Enable categories?', 'dbem' ), 'dbem_categories_enabled', __( 'Select yes to enable the category features','dbem' ) );
300
+ if( get_option('dbem_categories_enabled') ){
301
+ /*default category*/
302
+ $category_options = array();
303
+ $category_options[0] = __('no default category','dbem');
304
+ $EM_Categories = EM_Categories::get();
305
+ foreach($EM_Categories as $EM_Category){
306
+ $category_options[$EM_Category->id] = $EM_Category->name;
307
+ }
308
+ em_options_select ( __( 'Default Category', 'dbem' ), 'dbem_default_category', $category_options, __( 'This option allows you to select the default category when adding an event.','dbem' )." ".__('(not applicable with event ownership on presently, coming soon!)','dbem') );
309
+ }
310
+ }
311
+ em_options_radio_binary ( __( 'Enable event attributes?', 'dbem' ), 'dbem_attributes_enabled', __( 'Select yes to enable the attributes feature','dbem' ) );
312
+ em_options_radio_binary ( __( 'Enable event custom fields?', 'dbem' ), 'dbem_cp_events_custom_fields', __( 'Custom fields are the same as attributes, except you cannot restrict specific values, users can add any kind of custom field name/value pair. Only available in the WordPress admin area.','dbem' ) );
313
+ if( get_option('dbem_attributes_enabled') ){
314
+ em_options_textarea ( __( 'Event Attributes', 'dbem' ), 'dbem_placeholders_custom', sprintf(__( "You can also add event attributes here, one per line in this format <code>#_ATT{key}</code>. They will not appear on event pages unless you insert them into another template below, but you may want to store extra information about an event for other uses. <a href='%s'>More information on placeholders.</a>", 'dbem' ), EM_ADMIN_URL .'&amp;page=events-manager-help') );
315
+ }
316
+ if( get_option('dbem_locations_enabled') ){
317
+ /*default location*/
318
+ $location_options = array();
319
+ $location_options[0] = __('no default location','dbem');
320
+ $EM_Locations = EM_Locations::get();
321
+ foreach($EM_Locations as $EM_Location){
322
+ $location_options[$EM_Location->id] = $EM_Location->name;
323
+ }
324
+ em_options_select ( __( 'Default Location', 'dbem' ), 'dbem_default_location', $location_options, __( 'This option allows you to select the default location when adding an event.','dbem' )." ".__('(not applicable with event ownership on presently, coming soon!)','dbem') );
325
+
326
+ /*default location country*/
327
+ em_options_select ( __( 'Default Location Country', 'dbem' ), 'dbem_location_default_country', em_get_countries(__('no default country', 'dbem')), __('If you select a default country, that will be pre-selected when creating a new location.','dbem') );
328
+ }
329
+ ?>
330
+ <tr>
331
+ <td colspan="2">
332
+ <h4><?php echo sprintf(__('%s Settings','dbem'),__('Location','dbem')); ?></h4>
333
+ </td>
334
+ </tr>
335
+ <?php
336
+ em_options_radio_binary ( __( 'Enable locations?', 'dbem' ), 'dbem_locations_enabled', __( 'If you disable locations, bear in mind that you should remove your location page, shortcodes and related placeholders from your formats.','dbem' ) );
337
+ if( get_option('dbem_locations_enabled') ){
338
+ em_options_radio_binary ( __( 'Require locations for events?', 'dbem' ), 'dbem_require_location', __( 'Setting this to no will allow you to submit events without locations. You can use the <code>{no_location}...{/no_location}</code> or <code>{has_location}..{/has_location}</code> conditional placeholder to selectively display location information.','dbem' ) );
339
+ em_options_radio_binary ( __( 'Use dropdown for locations?', 'dbem' ), 'dbem_use_select_for_locations', __( 'Select yes to select location from a drow-down menu; location selection will be faster, but you will lose the ability to insert locations with events','dbem' ) );
340
+ }
341
+ ?>
342
+ <tr>
343
+ <td colspan="2">
344
+ <h4><?php echo sprintf(__('%s Settings','dbem'),__('Other','dbem')); ?></h4>
345
+ </td>
346
+ </tr>
347
+ <?php
348
+ em_options_radio_binary ( __('Show some love?','dbem'), 'dbem_credits', __( 'Hundreds of free hours have gone into making this free plugin, show your support and add a small link to the plugin website at the bottom of your event pages.','dbem' ) );
349
+ echo $save_button;
350
+ ?>
351
+ </table>
352
+
353
+ </div> <!-- . inside -->
354
+ </div> <!-- .postbox -->
355
+
356
+ <?php if ( !is_multisite() ){ em_admin_option_box_image_sizes(); } ?>
357
+
358
+ <?php if ( !is_multisite() ){ em_admin_option_box_caps(); } ?>
359
+
360
+ <?php if ( !is_multisite() ) { em_admin_option_box_anon_events(); } ?>
361
+
362
+ <?php do_action('em_options_page_footer'); ?>
363
+
364
+ <?php if ( !is_multisite() ) { em_admin_option_box_uninstall(); } ?>
365
+
366
+ <?php if( get_option('dbem_migrate_images') ): ?>
367
+ <div class="postbox " >
368
+ <div class="handlediv" title="<?php __('Click to toggle', 'dbem'); ?>"><br /></div><h3><span>Migrate Images From Version 4</span></h3>
369
+ <div class="inside">
370
+ <?php /* Not translating as it's temporary */ ?>
371
+ <p>You have the option of migrating images from version 4 so they become the equivalent of 'featured images' like with regular WordPress posts and pages and are also available in your media library.</p>
372
+ <p>Your event and location images will still display correctly on the front-end even if you don't migrate, but will not show up within your edit location/event pages in the admin area.</p>
373
+ <p>
374
+ <a href="<?php echo $_SERVER['REQUEST_URI'] ?>&amp;em_migrate_images=1&amp;_wpnonce=<?php echo wp_create_nonce('em_migrate_images'); ?>" />Migrate Images</a><br />
375
+ <a href="<?php echo $_SERVER['REQUEST_URI'] ?>&amp;em_not_migrate_images=1&amp;_wpnonce=<?php echo wp_create_nonce('em_not_migrate_images'); ?>" />Do Not Migrate Images</a>
376
+ </p>
377
+ </div> <!-- . inside -->
378
+ </div> <!-- .postbox -->
379
+ <?php endif; ?>
380
+ </div> <!-- .em-menu-general -->
381
 
382
+ <!-- PAGE OPTIONS -->
383
+ <div class="em-menu-pages em-menu-group" style="display:none;">
384
+ <?php
385
+ $template_page_tip = __( "Many themes display extra meta information on post pages such as 'posted by' or 'post date' information, which may not be desired. Usually, page templates contain less clutter.", 'dbem' );
386
+ $format_override_tip = __("By using formats, you can control how your %s are displayed from within the Events Manager <a href='#formats' class='nav-tab-link' rel='#em-menu-formats'>Formats</a> tab above without having to edit your theme files.")
387
+ ?>
388
+ <div class="postbox " >
389
+ <div class="handlediv" title="<?php __('Click to toggle', 'dbem'); ?>"><br /></div><h3><span><?php echo sprintf(__('Permalink Slugs','dbem')); ?></span></h3>
390
+ <div class="inside">
391
+ <p><?php _e('You can change the permalink structure of your events, locations, categories and tags here. Be aware that you may want to set up redirects if you change your permalink structures to maintain SEO rankings.','dbem'); ?></p>
392
+ <table class="form-table">
393
+ <?php
394
+ em_options_input_text ( __( 'Events', 'dbem' ), 'dbem_cp_events_slug', sprintf(__('e.g. %s - you can use / seperators too', 'dbem' ), '<strong>'.home_url().'/<code>'.get_option('dbem_cp_events_slug',EM_POST_TYPE_EVENT_SLUG).'</code>/2012-olympics/</strong>'), EM_POST_TYPE_EVENT_SLUG );
395
+ if( get_option('dbem_locations_enabled') ){
396
+ em_options_input_text ( __( 'Locations', 'dbem' ), 'dbem_cp_locations_slug', sprintf(__('e.g. %s - you can use / seperators too', 'dbem' ), '<strong>'.home_url().'/<code>'.get_option('dbem_cp_locations_slug',EM_POST_TYPE_LOCATION_SLUG).'</code>/wembley-stadium/</strong>'), EM_POST_TYPE_LOCATION_SLUG );
397
+ }
398
+ if( get_option('dbem_categories_enabled') && !(EM_MS_GLOBAL && !is_main_blog()) ){
399
+ em_options_input_text ( __( 'Event Categories', 'dbem' ), 'dbem_taxonomy_category_slug', sprintf(__('e.g. %s - you can use / seperators too', 'dbem' ), '<strong>'.home_url().'/<code>'.get_option('dbem_taxonomy_category_slug',EM_TAXONOMY_CATEGORY_SLUG).'</code>/sports/</strong>'), EM_TAXONOMY_CATEGORY_SLUG );
400
+ }
401
+ if( get_option('dbem_tags_enabled') ){
402
+ em_options_input_text ( __( 'Event Tags', 'dbem' ), 'dbem_taxonomy_tag_slug', sprintf(__('e.g. %s - you can use / seperators too', 'dbem' ), '<strong>'.home_url().'/<code>'.get_option('dbem_taxonomy_tag_slug',EM_TAXONOMY_TAG_SLUG).'</code>/running/</strong>'), EM_TAXONOMY_TAG_SLUG );
403
+ }
404
+ echo $save_button;
405
+ ?>
406
+ </table>
407
+ </div> <!-- . inside -->
408
+ </div> <!-- .postbox -->
409
+
410
+ <div class="postbox " >
411
+ <div class="handlediv" title="<?php __('Click to toggle', 'dbem'); ?>"><br /></div><h3><span><?php echo sprintf(__('%s Page Options','dbem'),__('Event','dbem')); ?></span></h3>
412
+ <div class="inside">
413
+ <table class="form-table">
414
+ <?php
415
+ em_options_radio_binary ( sprintf(__( 'Display %s as', 'dbem' ),__('events','dbem')), 'dbem_cp_events_template_page', $template_page_tip, array(__('Posts'),__('Pages')) );
416
+ em_options_radio_binary ( __( 'Override with Formats?', 'dbem' ), 'dbem_cp_events_formats', sprintf($format_override_tip,__('events','dbem')));
417
+ echo $save_button;
418
+ ?>
419
+ </table>
420
+ </div> <!-- . inside -->
421
+ </div> <!-- .postbox -->
422
+
423
+ <div class="postbox " >
424
+ <div class="handlediv" title="<?php __('Click to toggle', 'dbem'); ?>"><br /></div><h3><span><?php echo sprintf(__('%s List/Archives Options','dbem'),__('Event','dbem')); ?></span></h3>
425
+ <div class="inside">
426
+ <table class="form-table">
427
+ <?php //WordPress Pages
428
  global $em_disable_filter; //Using a flag here instead
429
  $em_disable_filter = true;
430
  $get_pages = get_pages();
431
  $events_page_options = array();
432
+ $events_page_options[0] = sprintf(__('[No %s Page]', 'dbem'),__('Events','dbem'));
433
  //TODO Add the hierarchy style ddm, like when choosing page parents
434
  foreach($get_pages as $page){
435
  $events_page_options[$page->ID] = $page->post_title;
436
  }
437
+ em_options_select ( __( 'Events page', 'dbem' ), 'dbem_events_page', $events_page_options, __( 'This option allows you to select which page to use as an events page. If you do not select an events page, to display event lists you can enable event archives or use the appropriate shortcodes and/or template tags.','dbem' ) );
438
  $em_disable_filter = false;
 
 
 
 
 
 
439
  ?>
440
+ <tbody class="em-event-page-options">
441
+ <?php
442
+ em_options_radio_binary ( __( 'Show events page in lists?', 'dbem' ), 'dbem_list_events_page', __( 'Check this option if you want the events page to appear together with other pages in pages lists.', 'dbem' ) );
443
+ em_options_radio_binary ( __( 'Display calendar in events page?', 'dbem' ), 'dbem_display_calendar_in_events_page', __( 'This options allows to display the calendar in the events page, instead of the default list. It is recommended not to display both the calendar widget and a calendar page.','dbem' ).' '.__('If you would like to show events that span over more than one day, see the Calendar section on this page.','dbem') );
444
+ em_options_radio_binary ( __( 'Disable title rewriting?', 'dbem' ), 'dbem_disable_title_rewrites', __( "Some WordPress themes don't follow best practices when generating navigation menus, and so the automatic title rewriting feature may cause problems, if your menus aren't working correctly on the event pages, try setting this to 'Yes', and provide an appropriate HTML title format below.",'dbem' ) );
445
+ em_options_input_text ( __( 'Event Manager titles', 'dbem' ), 'dbem_title_html', __( "This only setting only matters if you selected 'Yes' to above. You will notice the events page titles aren't being rewritten, and you have a new title underneath the default page name. This is where you control the HTML of this title. Make sure you keep the #_PAGETITLE placeholder here, as that's what is rewritten by events manager. To control what's rewritten in this title, see settings further down for page titles.", 'dbem' ) );
446
+ em_options_radio_binary ( __( 'Show events search?', 'dbem' ), 'dbem_events_page_search', __( "If set to yes, a search form will appear just above your list of events.", 'dbem' ) );
447
+ ?>
448
+ </tbody>
449
+ <tbody class="em-event-archive-options">
450
+ <?php
451
+ em_options_radio_binary ( __( 'Enable Archives?', 'dbem' ), 'dbem_cp_events_has_archive', __( "Allow WordPress post-style archives.", 'dbem' ) );
452
+ ?>
453
+ </tbody>
454
+ <tbody class="em-event-archive-options em-event-archive-sub-options">
455
+ <tr valign="top">
456
+ <th scope="row"><?php _e('Default event archive ordering','dbem'); ?></th>
457
+ <td>
458
+ <select name="dbem_events_default_archive_orderby" >
459
+ <?php
460
+ $event_archive_orderby_options = apply_filters('em_settings_events_default_archive_orderby_ddm', array(
461
+ '_start_ts' => __('Order by start date, start time','dbem'),
462
+ 'title' => __('Order by name','dbem')
463
+ ));
464
+ ?>
465
+ <?php foreach($event_archive_orderby_options as $key => $value) : ?>
466
+ <option value='<?php echo $key ?>' <?php echo ($key == get_option('dbem_events_default_archive_orderby')) ? "selected='selected'" : ''; ?>>
467
+ <?php echo $value; ?>
468
+ </option>
469
+ <?php endforeach; ?>
470
+ </select>
471
+ <select name="dbem_events_default_archive_order" >
472
+ <?php
473
+ $ascending = __('Ascending','dbem');
474
+ $descending = __('Descending','dbem');
475
+ $event_archive_order_options = apply_filters('em_settings_events_default_archive_order_ddm', array(
476
+ 'ASC' => __('Ascending','dbem'),
477
+ 'DESC' => __('Descending','dbem')
478
+ ));
479
+ ?>
480
+ <?php foreach( $event_archive_order_options as $key => $value) : ?>
481
+ <option value='<?php echo $key ?>' <?php echo ($key == get_option('dbem_events_default_archive_order')) ? "selected='selected'" : ''; ?>>
482
+ <?php echo $value; ?>
483
+ </option>
484
+ <?php endforeach; ?>
485
+ </select>
486
+ <br/>
487
+ <em><?php _e('When Events Manager displays lists of events the default behaviour is ordering by start date in ascending order. To change this, modify the values above.','dbem'); ?></em>
488
+ </td>
489
+ </tr>
490
+ </tbody>
491
+ <tr>
492
+ <td colspan="2">
493
+ <h4><?php echo _e('General settings','dbem'); ?></h4>
494
+ </td>
495
+ </tr>
496
+ <?php
497
+ em_options_radio_binary ( __( 'Override with Formats?', 'dbem' ), 'dbem_cp_events_archive_formats', sprintf($format_override_tip,__('events','dbem')));
498
+ em_options_radio_binary ( __( 'Are current events past events?', 'dbem' ), 'dbem_events_current_are_past', __( "By default, events that are have an end date later than today will be included in searches, set this to yes to consider events that started 'yesterday' as past.", 'dbem' ) );
499
+ em_options_radio_binary ( __( 'Include in WordPress Searches?', 'dbem' ), 'dbem_cp_events_search_results', sprintf(__( "Allow %s to appear in the built-in search results.", 'dbem' ),__('events','dbem')) );
500
+ ?>
501
+ <tr>
502
+ <td colspan="2">
503
+ <h4><?php echo sprintf(__('Default %s list options','dbem'), __('event','dbem')); ?></h4>
504
+ <p><?php _e('These can be overriden when using shortcode or template tags.','dbem'); ?></p>
505
+ </td>
506
+ </tr>
507
  <tr valign="top" id='dbem_events_default_orderby_row'>
508
  <th scope="row"><?php _e('Default event list ordering','dbem'); ?></th>
509
  <td>
510
  <select name="dbem_events_default_orderby" >
511
  <?php
512
  $orderby_options = apply_filters('em_settings_events_default_orderby_ddm', array(
513
+ 'event_start_date,event_start_time,event_name' => __('Order by start date, start time, then event name','dbem'),
514
+ 'event_name,event_start_date,event_start_time' => __('Order by name, start date, then start time','dbem'),
515
+ 'event_name,event_end_date,event_end_time' => __('Order by name, end date, then end time','dbem'),
516
+ 'event_end_date,event_end_time,event_name' => __('Order by end date, end time, then event name','dbem'),
517
  ));
518
  ?>
519
  <?php foreach($orderby_options as $key => $value) : ?>
546
  <br/>
547
  <em><?php _e('When Events Manager displays lists of events the default behaviour is ordering by start date in ascending order. To change this, modify the values above.','dbem'); ?></em>
548
  </td>
549
+ </tr>
550
  <tr valign="top" id='dbem_events_display_time_limit'>
551
+ <th scope="row"><?php _e('Event list scope','dbem'); ?></th>
552
+ <td>
553
+ <select name="dbem_events_page_scope" >
554
+ <?php foreach( em_get_scopes() as $key => $value) : ?>
555
+ <option value='<?php echo $key ?>' <?php echo ($key == get_option('dbem_events_page_scope')) ? "selected='selected'" : ''; ?>>
556
+ <?php echo $value; ?>
557
+ </option>
558
+ <?php endforeach; ?>
559
+ </select>
560
+ <br />
561
+ <em><?php _e('Only show events starting within a certain time limit on the events page. Default is future events with no end time limit.','dbem'); ?></em>
562
+ </td>
563
+ </tr>
564
+ <?php
565
+ em_options_input_text ( __( 'Event List Limits', 'dbem' ), 'dbem_events_default_limit', __( "This will control how many events are shown on one list by default.", 'dbem' ) );
566
+ echo $save_button;
567
+ ?>
568
+ </table>
569
+ </div> <!-- . inside -->
570
+ </div> <!-- .postbox -->
571
+
572
+ <?php if( get_option('dbem_locations_enabled') ): ?>
573
+ <div class="postbox " >
574
+ <div class="handlediv" title="<?php __('Click to toggle', 'dbem'); ?>"><br /></div><h3><span><?php echo sprintf(__('%s Page Options','dbem'),__('Location','dbem')); ?></span></h3>
575
+ <div class="inside">
576
+ <table class="form-table">
577
+ <?php
578
+ em_options_radio_binary ( sprintf(__( 'Display %s as', 'dbem' ),__('locations','dbem')), 'dbem_cp_locations_template_page', $template_page_tip, array(__('Posts'),__('Pages')) );
579
+ em_options_radio_binary ( __( 'Override with Formats?', 'dbem' ), 'dbem_cp_locations_formats', sprintf($format_override_tip,__('locations','dbem')));
580
+ echo $save_button;
581
+ ?>
582
+ </table>
583
+ </div> <!-- . inside -->
584
+ </div> <!-- .postbox -->
585
+
586
+ <div class="postbox " >
587
+ <div class="handlediv" title="<?php __('Click to toggle', 'dbem'); ?>"><br /></div><h3><span><?php echo sprintf(__('%s List/Archives Options','dbem'),__('Location','dbem')); ?></span></h3>
588
+ <div class="inside">
589
+ <table class="form-table">
590
+ <?php
591
+ $events_page_options[0] = sprintf(__('[No %s Page]', 'dbem'),__('Locations','dbem'));
592
+ em_options_select ( sprintf(__( '%s page', 'dbem' ),__('Locations','dbem')), 'dbem_locations_page', $events_page_options, sprintf(__( 'This option allows you to select which page to use as the %s page. If you do not select no %s page, to display lists you can enable archives or use the appropriate shortcodes and/or template tags.','dbem' ),__('locations','dbem'),__('locations','dbem')) );
593
+ ?>
594
+ <tbody class="em-location-page-options">
595
+ <?php
596
+ em_options_radio_binary ( sprintf(__( 'Show %s page in lists?', 'dbem' ),__('locations','dbem')), 'dbem_list_locations_page', sprintf(__( 'Check this option if you want the %s page to appear together with other pages in pages lists.', 'dbem' ),__('locations','dbem')) );
597
+ ?>
598
+ </tbody>
599
+ <tbody class="em-location-archive-options">
600
+ <?php
601
+ em_options_radio_binary ( __( 'Enable Archives?', 'dbem' ), 'dbem_cp_locations_has_archive', __( "Allow WordPress post-style archives.", 'dbem' ) );
602
+ ?>
603
+ </tbody>
604
+ <tbody class="em-location-archive-options em-location-archive-sub-options">
605
+ <tr valign="top">
606
+ <th scope="row"><?php _e('Default archive ordering','dbem'); ?></th>
607
+ <td>
608
+ <select name="dbem_locations_default_archive_orderby" >
609
  <?php
610
+ $orderby_options = apply_filters('em_settings_locations_default_archive_orderby_ddm', array(
611
+ '_country' => sprintf(__('Order by %s','dbem'),__('Country','dbem')),
612
+ '_town' => sprintf(__('Order by %s','dbem'),__('Town','dbem')),
613
+ 'title' => sprintf(__('Order by %s','dbem'),__('Name','dbem'))
 
 
 
614
  ));
615
  ?>
616
+ <?php foreach($orderby_options as $key => $value) : ?>
617
+ <option value='<?php echo $key ?>' <?php echo ($key == get_option('dbem_locations_default_archive_orderby')) ? "selected='selected'" : ''; ?>>
618
+ <?php echo $value; ?>
619
+ </option>
620
+ <?php endforeach; ?>
621
+ </select>
622
+ <select name="dbem_locations_default_archive_order" >
623
+ <?php
624
+ $ascending = __('Ascending','dbem');
625
+ $descending = __('Descending','dbem');
626
+ $order_options = apply_filters('em_settings_locations_default_archive_order_ddm', array(
627
+ 'ASC' => __('Ascending','dbem'),
628
+ 'DESC' => __('Descending','dbem')
629
+ ));
630
+ ?>
631
+ <?php foreach( $order_options as $key => $value) : ?>
632
+ <option value='<?php echo $key ?>' <?php echo ($key == get_option('dbem_locations_default_archive_order')) ? "selected='selected'" : ''; ?>>
633
+ <?php echo $value; ?>
634
+ </option>
635
  <?php endforeach; ?>
636
  </select>
 
 
637
  </td>
638
+ </tr>
639
+ </tbody>
640
+ <tr>
641
+ <td colspan="2">
642
+ <h4><?php echo _e('General settings','dbem'); ?></h4>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
643
  </td>
644
  </tr>
645
+ <?php
646
+ em_options_radio_binary ( __( 'Override with Formats?', 'dbem' ), 'dbem_cp_locations_archive_formats', sprintf($format_override_tip,__('locations','dbem')));
647
+ em_options_radio_binary ( __( 'Include in WordPress Searches?', 'dbem' ), 'dbem_cp_locations_search_results', sprintf(__( "Allow %s to appear in the built-in search results.", 'dbem' ),__('locations','dbem')) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
648
  ?>
649
+ <tr>
650
+ <td colspan="2">
651
+ <h4><?php echo sprintf(__('Default %s list options','dbem'), __('location','dbem')); ?></h4>
652
+ <p><?php _e('These can be overriden when using shortcode or template tags.','dbem'); ?></p>
653
+ </td>
654
+ </tr>
655
+ <tr valign="top" id='dbem_locations_default_orderby_row'>
656
+ <th scope="row"><?php _e('Default list ordering','dbem'); ?></th>
657
+ <td>
658
+ <select name="dbem_locations_default_orderby" >
659
+ <?php
660
+ $orderby_options = apply_filters('em_settings_locations_default_orderby_ddm', array(
661
+ 'location_country' => sprintf(__('Order by %s','dbem'),__('Country','dbem')),
662
+ 'location_town' => sprintf(__('Order by %s','dbem'),__('Town','dbem')),
663
+ 'location_name' => sprintf(__('Order by %s','dbem'),__('Name','dbem'))
664
+ ));
665
+ ?>
666
+ <?php foreach($orderby_options as $key => $value) : ?>
667
+ <option value='<?php echo $key ?>' <?php echo ($key == get_option('dbem_locations_default_orderby')) ? "selected='selected'" : ''; ?>>
668
+ <?php echo $value; ?>
669
+ </option>
670
+ <?php endforeach; ?>
671
+ </select>
672
+ <select name="dbem_locations_default_order" >
673
+ <?php
674
+ $ascending = __('Ascending','dbem');
675
+ $descending = __('Descending','dbem');
676
+ $order_options = apply_filters('em_settings_locations_default_order_ddm', array(
677
+ 'ASC' => __('Ascending','dbem'),
678
+ 'DESC' => __('Descending','dbem')
679
+ ));
680
+ ?>
681
+ <?php foreach( $order_options as $key => $value) : ?>
682
+ <option value='<?php echo $key ?>' <?php echo ($key == get_option('dbem_locations_default_order')) ? "selected='selected'" : ''; ?>>
683
+ <?php echo $value; ?>
684
+ </option>
685
+ <?php endforeach; ?>
686
+ </select>
687
+ </td>
688
+ </tr>
689
  <?php
690
+ em_options_input_text ( __( 'List Limits', 'dbem' ), 'dbem_locations_default_limit', sprintf(__( "This will control how many %s are shown on one list by default.", 'dbem' ),__('locations','dbem')) );
691
+ echo $save_button;
692
  ?>
693
+ </table>
694
+ </div> <!-- . inside -->
695
+ </div> <!-- .postbox -->
696
+ <?php endif; ?>
697
+
698
+ <?php if( get_option('dbem_categories_enabled') && !(EM_MS_GLOBAL && !is_main_blog()) ): ?>
699
+ <div class="postbox " >
700
+ <div class="handlediv" title="<?php __('Click to toggle', 'dbem'); ?>"><br /></div><h3><span><?php echo sprintf(__('%s List/Archives Options','dbem'),__('Event Category','dbem')); ?></span></h3>
701
+ <div class="inside">
702
+ <table class="form-table">
703
+ <?php
704
+ $events_page_options[0] = sprintf(__('[No %s Page]', 'dbem'),__('Categories','dbem'));
705
+ em_options_select ( sprintf(__( '%s page', 'dbem' ),__('Categories','dbem')), 'dbem_categories_page', $events_page_options, sprintf(__( 'This option allows you to select which page to use as the %s page.','dbem' ),__('categories','dbem'),__('categories','dbem')) );
706
  ?>
707
+ <tbody class="em-category-page-options">
708
+ <?php
709
+ em_options_radio_binary ( sprintf(__( 'Show %s page in lists?', 'dbem' ),__('categories','dbem')), 'dbem_list_categories_page', sprintf(__( 'Check this option if you want the %s page to appear together with other pages in pages lists.', 'dbem' ),__('categories','dbem')) );
710
+ ?>
711
+ </tbody>
712
+ <tr>
713
+ <td colspan="2">
714
+ <h4><?php echo _e('General settings','dbem'); ?></h4>
715
+ </td>
716
+ </tr>
717
  <?php
718
+ em_options_radio_binary ( __( 'Override with Formats?', 'dbem' ), 'dbem_cp_categories_formats', sprintf($format_override_tip,__('categories','dbem').' '. __('Setting this to yes will make categories display as a page rather than an archive.')));
 
 
719
  ?>
720
+ <tr valign="top">
721
+ <th scope="row"><?php _e('Default archive ordering','dbem'); ?></th>
722
+ <td>
723
+ <select name="dbem_categories_default_archive_orderby" >
724
+ <?php foreach($event_archive_orderby_options as $key => $value) : ?>
725
+ <option value='<?php echo $key ?>' <?php echo ($key == get_option('dbem_categories_default_archive_orderby')) ? "selected='selected'" : ''; ?>>
726
+ <?php echo $value; ?>
727
+ </option>
728
+ <?php endforeach; ?>
729
+ </select>
730
+ <select name="dbem_categories_default_archive_order" >
731
+ <?php foreach( $event_archive_order_options as $key => $value) : ?>
732
+ <option value='<?php echo $key ?>' <?php echo ($key == get_option('dbem_categories_default_archive_order')) ? "selected='selected'" : ''; ?>>
733
+ <?php echo $value; ?>
734
+ </option>
735
+ <?php endforeach; ?>
736
+ </select>
737
+ </td>
738
+ </tr>
739
+ <tr>
740
+ <td colspan="2">
741
+ <h4><?php echo sprintf(__('Default %s list options','dbem'), __('category','dbem')); ?></h4>
742
+ <p><?php _e('These can be overriden when using shortcode or template tags.','dbem'); ?></p>
743
+ </td>
744
+ </tr>
745
+ <tr valign="top" id='dbem_categories_default_orderby_row'>
746
+ <th scope="row"><?php _e('Default list ordering','dbem'); ?></th>
747
+ <td>
748
+ <select name="dbem_categories_default_orderby" >
749
+ <?php
750
+ $orderby_options = apply_filters('em_settings_categories_default_orderby_ddm', array(
751
+ 'category_country' => sprintf(__('Order by %s','dbem'),__('Country','dbem')),
752
+ 'category_town' => sprintf(__('Order by %s','dbem'),__('Town','dbem')),
753
+ 'category_name' => sprintf(__('Order by %s','dbem'),__('Name','dbem'))
754
+ ));
755
+ ?>
756
+ <?php foreach($orderby_options as $key => $value) : ?>
757
+ <option value='<?php echo $key ?>' <?php echo ($key == get_option('dbem_categories_default_orderby')) ? "selected='selected'" : ''; ?>>
758
+ <?php echo $value; ?>
759
+ </option>
760
+ <?php endforeach; ?>
761
+ </select>
762
+ <select name="dbem_categories_default_order" >
763
+ <?php
764
+ $ascending = __('Ascending','dbem');
765
+ $descending = __('Descending','dbem');
766
+ $order_options = apply_filters('em_settings_categories_default_order_ddm', array(
767
+ 'ASC' => __('Ascending','dbem'),
768
+ 'DESC' => __('Descending','dbem')
769
+ ));
770
+ ?>
771
+ <?php foreach( $order_options as $key => $value) : ?>
772
+ <option value='<?php echo $key ?>' <?php echo ($key == get_option('dbem_categories_default_order')) ? "selected='selected'" : ''; ?>>
773
+ <?php echo $value; ?>
774
+ </option>
775
+ <?php endforeach; ?>
776
+ </select>
777
+ </td>
778
+ </tr>
779
  <?php
780
+ em_options_input_text ( __( 'List Limits', 'dbem' ), 'dbem_categories_default_limit', sprintf(__( "This will control how many %s are shown on one list by default.", 'dbem' ),__('categories','dbem')) );
781
+ echo $save_button;
782
  ?>
783
+ </table>
784
+ </div> <!-- . inside -->
785
+ </div> <!-- .postbox -->
786
+ <?php endif; ?>
787
+
788
+ <?php if( get_option('dbem_tags_enabled') ): ?>
789
+ <div class="postbox " >
790
+ <div class="handlediv" title="<?php __('Click to toggle', 'dbem'); ?>"><br /></div><h3><span><?php echo sprintf(__('%s List/Archives Options','dbem'),__('Event Tag','dbem')); ?></span></h3>
791
+ <div class="inside">
792
+ <table class="form-table">
793
+ <?php
794
+ em_options_radio_binary ( __( 'Override with Formats?', 'dbem' ), 'dbem_cp_categories_formats', sprintf($format_override_tip,__('categories','dbem')));
795
+ echo $save_button;
796
+ ?>
797
+ </table>
798
+ </div> <!-- . inside -->
799
+ </div> <!-- .postbox -->
800
+ <?php endif; ?>
801
+
802
+ </div> <!-- .em-menu-pages -->
803
+
804
+ <!-- FORMAT OPTIONS -->
805
+ <div class="em-menu-formats em-menu-group" style="display:none;">
806
+ <div class="postbox " >
807
+ <div class="handlediv" title="<?php __('Click to toggle', 'dbem'); ?>"><br /></div><h3><span><?php _e ( 'Events format', 'dbem' ); ?> </span></h3>
808
+ <div class="inside">
809
+ <table class="form-table">
810
+ <tr><td><strong><?php echo sprintf(__('%s Page','dbem'),__('Events','dbem')); ?></strong></td></tr>
811
+ <?php
812
+ em_options_textarea ( __( 'Default event list format header', 'dbem' ), 'dbem_event_list_item_format_header', __( 'This content will appear just above your code for the default event list format. Default is blank', 'dbem' ) );
813
+ em_options_textarea ( __( 'Default event list format', 'dbem' ), 'dbem_event_list_item_format', __( 'The format of any events in a list.', 'dbem' ).$events_placeholder_tip );
814
+ em_options_textarea ( __( 'Default event list format footer', 'dbem' ), 'dbem_event_list_item_format_footer', __( 'This content will appear just below your code for the default event list format. Default is blank', 'dbem' ) );
815
+ em_options_input_text ( __( 'No events message', 'dbem' ), 'dbem_no_events_message', __( 'The message displayed when no events are available.', 'dbem' ) );
816
+ em_options_input_text ( __( 'List events by date title', 'dbem' ), 'dbem_list_date_title', __( 'If viewing a page for events on a specific date, this is the title that would show up. To insert date values, use <a href="http://www.php.net/manual/en/function.date.php">PHP time format characters</a> with a <code>#</code> symbol before them, i.e. <code>#m</code>, <code>#M</code>, <code>#j</code>, etc.<br/>', 'dbem' ) );
817
+ ?>
818
+ <tr><td><strong><?php echo sprintf(__('Single %s Page','dbem'),__('Event','dbem')); ?></strong></td></tr>
819
+ <?php
820
+ em_options_input_text ( __( 'Single event page title format', 'dbem' ), 'dbem_event_page_title_format', __( 'The format of a single event page title.', 'dbem' ).$events_placeholder_tip );
821
+ em_options_textarea ( __( 'Default single event format', 'dbem' ), 'dbem_single_event_format', __( 'The format of a single event page.', 'dbem' ).$events_placeholder_tip );
822
+ echo $save_button;
823
+ ?>
824
+ </table>
825
+ </div> <!-- . inside -->
826
+ </div> <!-- .postbox -->
827
+
828
+ <div class="postbox " >
829
+ <div class="handlediv" title="<?php __('Click to toggle', 'dbem'); ?>"><br /></div><h3><span><?php _e ( 'Calendar format', 'dbem' ); ?></span></h3>
830
+ <div class="inside">
831
+ <table class="form-table">
832
+ <?php
833
+ em_options_input_text ( __( 'Small calendar title', 'dbem' ), 'dbem_small_calendar_event_title_format', __( 'The format of the title, corresponding to the text that appears when hovering on an eventful calendar day.', 'dbem' ).$events_placeholder_tip );
834
+ em_options_input_text ( __( 'Small calendar title separator', 'dbem' ), 'dbem_small_calendar_event_title_separator', __( 'The separator appearing on the above title when more than one events are taking place on the same day.', 'dbem' ) );
835
+ em_options_input_text ( __( 'Full calendar events format', 'dbem' ), 'dbem_full_calendar_event_format', __( 'The format of each event when displayed in the full calendar. Remember to include <code>li</code> tags before and after the event.', 'dbem' ).$events_placeholder_tip );
836
+ em_options_radio_binary ( __( 'Show long events on calendar pages?', 'dbem' ), 'dbem_full_calendar_long_events', __( "If you are showing a calendar on the events page (see Events format section on this page), you have the option of showing events that span over days on each day it occurs.",'dbem' ) );
837
+ em_options_radio_binary ( __( 'Show list on day with single event?', 'dbem' ), 'dbem_display_calendar_day_single', __( "By default, if a calendar day only has one event, it display a single event when clicking on the link of that calendar date. If you select Yes here, you will get always see a list of events.",'dbem' ) );
838
+ ?>
839
+ <tr><td><strong><?php echo sprintf(__('iCal Feed Settings','dbem'),__('Event','dbem')); ?></strong></td></tr>
840
+ <?php
841
+ em_options_input_text ( __( 'iCal Title', 'dbem' ), 'dbem_ical_description_format', __( 'The title that will appear in the calendar.', 'dbem' ).$events_placeholder_tip );
842
+ em_options_input_text ( __( 'iCal Limit', 'dbem' ), 'dbem_ical_limit', __( 'Limits the number of future events shown (0 = unlimited).', 'dbem' ) );
843
+ echo $save_button;
844
+ ?>
845
+ </table>
846
+ </div> <!-- . inside -->
847
+ </div> <!-- .postbox -->
848
+
849
+ <?php if( get_option('dbem_locations_enabled') ): ?>
850
+ <div class="postbox " >
851
+ <div class="handlediv" title="<?php __('Click to toggle', 'dbem'); ?>"><br /></div><h3><span><?php _e ( 'Locations format', 'dbem' ); ?> </span></h3>
852
+ <div class="inside">
853
+ <table class="form-table">
854
+ <tr><td><strong><?php echo sprintf(__('%s Page','dbem'),__('Locations','dbem')); ?></strong></td></tr>
855
+ <?php
856
+ em_options_textarea ( sprintf(__('%s list header format','dbem'),__('Locations','dbem')), 'dbem_location_list_item_format_header', sprintf(__( 'This content will appear just above your code for the %s list format below. Default is blank', 'dbem' ), __('locations','dbem')) );
857
+ em_options_textarea ( sprintf(__('%s list item format','dbem'),__('Locations','dbem')), 'dbem_location_list_item_format', sprintf(__( 'The format of a single %s in a list.', 'dbem' ), __('locations','dbem')).$locations_placeholder_tip );
858
+ em_options_textarea ( sprintf(__('%s list footer format','dbem'),__('Locations','dbem')), 'dbem_location_list_item_format_footer', sprintf(__( 'This content will appear just below your code for the %s list format above. Default is blank', 'dbem' ), __('locations','dbem')) );
859
+ em_options_input_text ( sprintf(__( 'No %s message', 'dbem' ),__('Locations','dbem')), 'dbem_no_locations_message', sprintf( __( 'The message displayed when no %s are available.', 'dbem' ), __('locations','dbem')) );
860
+ ?>
861
+ <tr><td><strong><?php echo sprintf(__('Single %s Page','dbem'),__('Location','dbem')); ?></strong></td></tr>
862
+ <?php
863
+ em_options_input_text (sprintf( __( 'Single %s title format', 'dbem' ),__('location','dbem')), 'dbem_location_page_title_format', __( 'The format of a single location page title.', 'dbem' ).$locationscategoriesder_tip );
864
+ em_options_textarea ( sprintf(__('Single %s page format', 'dbem' ),__('location','dbem')), 'dbem_single_location_format', __( 'The format of a single location page.', 'dbem' ).$locations_placeholder_tip );
865
+ em_options_textarea ( __( 'Default location balloon format', 'dbem' ), 'dbem_location_baloon_format', __( 'The format of of the text appearing in the baloon describing the location a single location map.', 'dbem' ).$locations_placeholder_tip );
866
+ ?>
867
+ <tr><td><strong><?php echo sprintf(__('%s List Formats','dbem'),__('Event','dbem')); ?></strong></td></tr>
868
+ <?php
869
+ em_options_textarea ( sprintf(__( 'Default %s list format', 'dbem' ),__('events','dbem')), 'dbem_location_event_list_item_format', __( 'The format of the events the list inserted in the location page through the <code>#_LOCATIONNEXTEVENTS</code>, <code>#_LOCATIONNEXTEVENTS</code> and <code>#_LOCATIONALLEVENTS</code> element.', 'dbem' ).$locations_placeholder_tip );
870
+ em_options_textarea ( sprintf(__( 'No %s message', 'dbem' ),__('events','dbem')), 'dbem_location_no_events_message', __( 'The message to be displayed in the list generated by <code>#_LOCATIONNEXTEVENTS</code>, <code>#_LOCATIONNEXTEVENTS</code> and <code>#_LOCATIONALLEVENTS</code> when no events are available.', 'dbem' ) );
871
+ echo $save_button;
872
+ ?>
873
+ </table>
874
+ </div> <!-- . inside -->
875
+ </div> <!-- .postbox -->
876
+ <?php endif; ?>
877
+
878
+ <?php if( get_option('dbem_categories_enabled') && !(EM_MS_GLOBAL && !is_main_blog()) ): ?>
879
+ <div class="postbox " >
880
+ <div class="handlediv" title="<?php __('Click to toggle', 'dbem'); ?>"><br /></div><h3><span><?php _e ( 'Categories format', 'dbem' ); ?> </span></h3>
881
+ <div class="inside">
882
+ <table class="form-table">
883
+ <tr><td><strong><?php echo sprintf(__('%s Page','dbem'),__('Categories','dbem')); ?></strong></td></tr>
884
+ <?php
885
+ em_options_textarea ( sprintf(__('%s list header format','dbem'),__('Categories','dbem')), 'dbem_categories_list_item_format_header', sprintf(__( 'This content will appear just above your code for the %s list format below. Default is blank', 'dbem' ), __('categories','dbem')) );
886
+ em_options_textarea ( sprintf(__('%s list item format','dbem'),__('Categories','dbem')), 'dbem_categories_list_item_format', sprintf(__( 'The format of a single %s in a list.', 'dbem' ), __('categories','dbem')).$categories_placeholder_tip );
887
+ em_options_textarea ( sprintf(__('%s list footer format','dbem'),__('Categories','dbem')), 'dbem_categories_list_item_format_footer', sprintf(__( 'This content will appear just below your code for the %s list format above. Default is blank', 'dbem' ), __('categories','dbem')) );
888
+ em_options_input_text ( sprintf(__( 'No %s message', 'dbem' ),__('Categories','dbem')), 'dbem_no_categories_message', sprintf( __( 'The message displayed when no %s are available.', 'dbem' ), __('categories','dbem')) );
889
+ ?>
890
+ <tr><td><strong><?php echo sprintf(__('Single %s Page','dbem'),__('Category','dbem')); ?></strong></td></tr>
891
+ <?php
892
+ em_options_input_text ( sprintf(__( 'Single %s title format', 'dbem' ),__('category','dbem')), 'dbem_category_page_title_format', __( 'The format of a single category page title.', 'dbem' ).$categories_placeholder_tip );
893
+ em_options_textarea ( sprintf(__('Single %s page format', 'dbem' ),__('category','dbem')), 'dbem_category_page_format', __( 'The format of a single category page.', 'dbem' ).$categories_placeholder_tip );
894
+ ?>
895
+ <tr><td><strong><?php echo sprintf(__('%s List Formats','dbem'),__('Event','dbem')); ?></strong></td></tr>
896
+ <?php
897
+ em_options_textarea ( sprintf(__( 'Default %s list format', 'dbem' ),__('events','dbem')), 'dbem_category_event_list_item_format', __( 'The format of the events the list inserted in the category page through the <code>#_CATEGORYNEXTEVENTS</code>, <code>#_CATEGORYNEXTEVENTS</code> and <code>#_CATEGORYALLEVENTS</code> element.', 'dbem' ).$categories_placeholder_tip );
898
+ em_options_textarea ( sprintf(__( 'No %s message', 'dbem' ),__('events','dbem')), 'dbem_category_no_events_message', __( 'The message to be displayed in the list generated by <code>#_CATEGORYNEXTEVENTS</code>, <code>#_CATEGORYNEXTEVENTS</code> and <code>#_CATEGORYALLEVENTS</code> when no events are available.', 'dbem' ) );
899
+ echo $save_button;
900
+ ?>
901
+ </table>
902
+ </div> <!-- . inside -->
903
+ </div> <!-- .postbox -->
904
+ <?php endif; ?>
905
+
906
+ <div class="postbox " >
907
+ <div class="handlediv" title="<?php __('Click to toggle', 'dbem'); ?>"><br /></div><h3><span><?php _e ( 'RSS feed format', 'dbem' ); ?> </span></h3>
908
+ <div class="inside">
909
+ <table class="form-table">
910
+ <?php
911
+ em_options_input_text ( __( 'RSS main title', 'dbem' ), 'dbem_rss_main_title', __( 'The main title of your RSS events feed.', 'dbem' ).$events_placeholder_tip );
912
+ em_options_input_text ( __( 'RSS main description', 'dbem' ), 'dbem_rss_main_description', __( 'The main description of your RSS events feed.', 'dbem' ) );
913
+ em_options_input_text ( __( 'RSS title format', 'dbem' ), 'dbem_rss_title_format', __( 'The format of the title of each item in the events RSS feed.', 'dbem' ).$events_placeholder_tip );
914
+ em_options_input_text ( __( 'RSS description format', 'dbem' ), 'dbem_rss_description_format', __( 'The format of the description of each item in the events RSS feed.', 'dbem' ).$events_placeholder_tip );
915
+ echo $save_button;
916
+ ?>
917
+ </table>
918
+ </div> <!-- . inside -->
919
+ </div> <!-- .postbox -->
920
+
921
+ <div class="postbox " >
922
+ <div class="handlediv" title="<?php __('Click to toggle', 'dbem'); ?>"><br /></div><h3><span><?php _e ( 'Maps and geotagging', 'dbem' ); ?> </span></h3>
923
+ <div class="inside">
924
+ <table class='form-table'>
925
+ <?php $gmap_is_active = get_option ( 'dbem_gmap_is_active' ); ?>
926
+ <tr valign="top">
927
+ <th scope="row"><?php _e ( 'Enable Google Maps integration?', 'dbem' ); ?></th>
928
+ <td>
929
+ <?php _e ( 'Yes' ); ?> <input id="dbem_gmap_is_active_yes" name="dbem_gmap_is_active" type="radio" value="1" <?php echo ($gmap_is_active) ? "checked='checked'":''; ?> />
930
+ <?php _e ( 'No' ); ?> <input name="dbem_gmap_is_active" type="radio" value="0" <?php echo ($gmap_is_active) ? '':"checked='checked'"; ?> /><br />
931
+ <em><?php _e ( 'Check this option to enable Goggle Map integration.', 'dbem' )?></em>
932
+ </td>
933
+ </tr>
934
+ <?php
935
+ em_options_textarea ( __( 'Map text format', 'dbem' ), 'dbem_map_text_format', __( 'The text format inside the map balloons.', 'dbem' ).$events_placeholder_tip );
936
+ echo $save_button;
937
+ ?>
938
+ </table>
939
+ </div> <!-- . inside -->
940
+ </div> <!-- .postbox -->
941
+
942
+ </div> <!-- .em-menu-formats -->
943
+
944
+ <?php if( get_option('dbem_rsvp_enabled') ): ?>
945
+ <!-- BOOKING OPTIONS -->
946
+ <div class="em-menu-bookings em-menu-group" style="display:none;">
947
+
948
+ <div class="postbox " >
949
+ <div class="handlediv" title="<?php __('Click to toggle', 'dbem'); ?>"><br /></div><h3><span><?php echo sprintf(__( '%s Options', 'dbem' ),__('General','dbem')); ?> </span></h3>
950
+ <div class="inside">
951
+ <table class='form-table'>
952
+ <?php
953
+ em_options_radio_binary ( __( 'Approval Required?', 'dbem' ), 'dbem_bookings_approval', __( 'Bookings will not be confirmed until the event administrator approves it.', 'dbem' ) );
954
+ em_options_radio_binary ( __( 'Reserved unconfirmed spaces?', 'dbem' ), 'dbem_bookings_approval_reserved', __( 'By default, event spaces become unavailable once there are enough CONFIRMED bookings. To reserve spaces even if unnapproved, choose yes.', 'dbem' ) );
955
+ em_options_radio_binary ( __( 'Can users cancel their booking?', 'dbem' ), 'dbem_bookings_user_cancellation', __( 'If enabled, users can cancel their bookings themselves from their bookings page.', 'dbem' ) );
956
+ em_options_radio_binary ( __( 'Allow overbooking when approving?', 'dbem' ), 'dbem_bookings_approval_overbooking', __( 'If you get a lot of pending bookings and you decide to allow more bookings than spaces allow, setting this to yes will allow you to override the event space limit when manually approving.', 'dbem' ) );
957
+ em_options_radio_binary ( __( 'Allow double bookings?', 'dbem' ), 'dbem_bookings_double', __( 'If enabled, users can book an event more than once.', 'dbem' ) );
958
+ echo $save_button;
959
+ ?>
960
+ </table>
961
+ </div> <!-- . inside -->
962
+ </div> <!-- .postbox -->
963
+
964
+ <div class="postbox " >
965
+ <div class="handlediv" title="<?php __('Click to toggle', 'dbem'); ?>"><br /></div><h3><span><?php echo sprintf(__( '%s Options', 'dbem' ),__('Pricing','dbem')); ?> </span></h3>
966
+ <div class="inside">
967
+ <table class='form-table'>
968
+ <?php
969
+ /* Tax & Currency */
970
+ em_options_select ( __( 'Currency', 'dbem' ), 'dbem_bookings_currency', em_get_currencies()->names, __( 'Choose your currency for displaying event pricing.', 'dbem' ) );
971
+ em_options_input_text ( __( 'Tax Rate', 'dbem' ), 'dbem_bookings_tax', __( 'Add a tax rate to your ticket prices (entering 10 will add 10% to the ticket price).', 'dbem' ) );
972
+ em_options_radio_binary ( __( 'Add tax to ticket price?', 'dbem' ), 'dbem_bookings_tax_auto_add', __( 'When displaying ticket prices and booking totals, include the tax automatically?', 'dbem' ) );
973
 
974
+ echo $save_button;
975
+ ?>
976
+ </table>
977
+ </div> <!-- . inside -->
978
+ </div> <!-- .postbox -->
979
+
980
+ <div class="postbox " >
981
+ <div class="handlediv" title="<?php __('Click to toggle', 'dbem'); ?>"><br /></div><h3><span><?php echo sprintf(__( '%s Options', 'dbem' ),__('Booking Form','dbem')); ?> </span></h3>
982
+ <div class="inside">
983
+ <table class='form-table'>
984
+ <?php
985
+ em_options_radio_binary ( __( 'Allow guest bookings?', 'dbem' ), 'dbem_bookings_anonymous', __( 'If enabled, guest visitors can supply an email address and a user account will automatically be created for them along with their booking. They will be also be able to log back in with that newly created account.', 'dbem' ) );
986
+ em_options_radio_binary ( __( 'Display login form?', 'dbem' ), 'dbem_bookings_login_form', __( 'Choose whether or not to display a login form in the booking form area to remind your members to log in before booking.', 'dbem' ) );
987
+ ?>
988
+ <tr><td colspan='2'><h4><?php _e('Booking form feedback messages','dbem') ?></h4></td></tr>
989
+ <tr><td colspan='2'><?php _e('When a booking is made by a user, a feedback message is shown depending on the result, which can be customized below.','dbem'); ?></td></tr>
990
+ <?php
991
+ em_options_input_text ( __( 'Successful booking', 'dbem' ), 'dbem_booking_feedback', __( 'When a booking is registered and confirmed.', 'dbem' ) );
992
+ em_options_input_text ( __( 'Successful pending booking', 'dbem' ), 'dbem_booking_feedback_pending', __( 'When a booking is registered but pending.', 'dbem' ) );
993
+ em_options_input_text ( __( 'Not enough spaces', 'dbem' ), 'dbem_booking_feedback_full', __( 'When a booking cannot be made due to lack of spaces.', 'dbem' ) );
994
+ em_options_input_text ( __( 'Errors', 'dbem' ), 'dbem_booking_feedback_error', __( 'When a booking cannot be made due to an error when filling the form. Below this, there will be a dynamic list of errors.', 'dbem' ) );
995
+ em_options_input_text ( __( 'User must log in', 'dbem' ), 'dbem_booking_feedback_log_in', __( 'When a user must log in before making a booking.', 'dbem' ) );
996
+ em_options_input_text ( __( 'Error mailing user', 'dbem' ), 'dbem_booking_feedback_nomail', __( 'If a booking is made and an email cannot be sent, this is added to the success message.', 'dbem' ) );
997
+ em_options_input_text ( __( 'Already booked', 'dbem' ), 'dbem_booking_feedback_already_booked', __( 'If the user made a previous booking and cannot double-book.', 'dbem' ) );
998
+ em_options_input_text ( __( 'No spaces booked', 'dbem' ), 'dbem_booking_feedback_min_space', __( 'If the user tries to make a booking without requesting any spaces.', 'dbem' ) );
999
+ echo $save_button;
1000
+ ?>
1001
+ </table>
1002
+ </div> <!-- . inside -->
1003
+ </div> <!-- .postbox -->
1004
+
1005
+ <div class="postbox " >
1006
+ <div class="handlediv" title="<?php __('Click to toggle', 'dbem'); ?>"><br /></div><h3><span><?php echo sprintf(__( '%s Options', 'dbem' ),__('Ticket','dbem')); ?> </span></h3>
1007
+ <div class="inside">
1008
+ <table class='form-table'>
1009
+ <?php
1010
+ em_options_radio_binary ( __( 'Single ticket mode?', 'dbem' ), 'dbem_bookings_tickets_single', __( 'In single ticket mode, users can only create one ticket per booking (and will not see options to add more tickets).', 'dbem' ) );
1011
+ em_options_radio_binary ( __( 'Show ticket table in single ticket mode?', 'dbem' ), 'dbem_bookings_tickets_single_form', __( 'If you prefer a ticket table like with multiple tickets, even for single ticket events, enable this.', 'dbem' ) );
1012
+ em_options_radio_binary ( __( 'Show unavailable tickets?', 'dbem' ), 'dbem_bookings_tickets_show_unavailable', __( 'You can choose whether or not to show unavailable tickets to visitors.', 'dbem' ) );
1013
+ em_options_radio_binary ( __( 'Show multiple tickets if logged out?', 'dbem' ), 'dbem_bookings_tickets_show_loggedout', __( 'If logged out, a user will be asked to register in order to book. However, we can show available tickets if you have more than one ticket.', 'dbem' ) );
1014
+ $ticket_orders = array(
1015
+ 'ticket_price DESC, ticket_name ASC'=>__('Ticket Price (Descending)','dbem'),
1016
+ 'ticket_price ASC, ticket_name ASC'=>__('Ticket Price (Ascending)','dbem'),
1017
+ 'ticket_name DESC, ticket_price DESC'=>__('Ticket Name (Ascending)','dbem'),
1018
+ 'ticket_name ASC, ticket_price DESC'=>__('Ticket Name (Descending)','dbem')
1019
+ );
1020
+ em_options_select ( __( 'Order Tickets By', 'dbem' ), 'dbem_bookings_tickets_orderby', $ticket_orders, __( 'Choose which order your tickets appear.', 'dbem' ) );
1021
+ echo $save_button;
1022
+ ?>
1023
+ </table>
1024
+ </div> <!-- . inside -->
1025
+ </div> <!-- .postbox -->
1026
+
1027
+ <div class="postbox " >
1028
+ <div class="handlediv" title="<?php __('Click to toggle', 'dbem'); ?>"><br /></div><h3><span><?php _e('No-User Booking Mode','dbem'); ?> </span></h3>
1029
+ <div class="inside">
1030
+ <table class='form-table'>
1031
+ <tr><td colspan='2'>
1032
+ <p><?php _e('By default, when a booking is made by a user, this booking is tied to a user account, if the user is not registered nor logged in and guest bookings are enabled, an account will be created for them.','dbem'); ?></p>
1033
+ <p><?php _e('The option below allows you to disable user accounts and assign all bookings to a parent user, yet you will still see the supplied booking personal information for each booking. When this mode is enabled, extra booking information about the person is stored alongside the booking record rather than as a WordPress user.','dbem'); ?></p>
1034
+ <p><?php _e('<strong>Warning : </strong> Various features afforded to users with an account will not be available, e.g. viewing bookings. Once you enable this and select a user, modifying these values will prevent older non-user bookings from displaying the correct information.','dbem'); ?></p>
1035
+ </td></tr>
1036
+ <?php
1037
+ em_options_radio_binary ( __( 'Enable No-User Booking Mode?', 'dbem' ), 'dbem_bookings_registration_disable', __( 'This disables user registrations for bookings.', 'dbem' ) );
1038
+ em_options_select ( __( 'Assign bookings to', 'dbem' ), 'dbem_bookings_registration_user', em_get_wp_users(array('role' => 'subscriber')), __( 'Choose a parent user to assign bookings to. People making their booking will be unaware of this and will never have access to those user details. This should be a subscriber user you do not use to log in with yourself.', 'dbem' ) );
1039
+ echo $save_button;
1040
+ ?>
1041
+ </table>
1042
+ </div> <!-- . inside -->
1043
+ </div> <!-- .postbox -->
1044
+
1045
+ </div> <!-- .em-menu-bookings -->
1046
+ <?php endif; ?>
1047
 
1048
+ <!-- EMAIL OPTIONS -->
1049
+ <div class="em-menu-emails em-menu-group" style="display:none;">
1050
+
1051
+ <?php if ( !is_multisite() ) { em_admin_option_box_email(); } ?>
1052
+
1053
+ <?php if( get_option('dbem_rsvp_enabled') ): ?>
1054
+ <div class="postbox " >
1055
+ <div class="handlediv" title="<?php __('Click to toggle', 'dbem'); ?>"><br /></div><h3><span><?php _e ( 'Booking Email Templates', 'dbem' ); ?> </span></h3>
1056
+ <div class="inside">
1057
+ <table class='form-table'>
1058
+ <?php
1059
+ em_options_select ( __( 'Default contact person', 'dbem' ), 'dbem_default_contact_person', em_get_wp_users(), __( 'Select the default contact person. This user will be employed whenever a contact person is not explicitly specified for an event', 'dbem' ) );
1060
+ em_options_input_text ( __( 'Email events admin?', 'dbem' ), 'dbem_bookings_notify_admin', __( "If you would like every event booking confirmation email sent to an administrator write their email here (leave blank to not send an email).", 'dbem' ) );
1061
+ em_options_radio_binary ( __( 'Email contact person?', 'dbem' ), 'dbem_bookings_contact_email', __( 'Check this option if you want the event contact to receive an email when someone books places. An email will be sent when a booking is first made (regardless if confirmed or pending)', 'dbem' ) );
1062
+ em_options_radio_binary ( __( 'Disable new registration email?', 'dbem' ), 'dbem_email_disable_registration', __( 'Check this option if you want to prevent the WordPress registration email from going out when a user anonymously books an event.', 'dbem' ) );
1063
+ ?>
1064
+ <tr><td colspan='2'><h4><?php _e('Contact person booking confirmed','dbem') ?></h4></td></tr>
1065
+ <tr><td colspan='2'><?php echo __('An email will be sent to the event contact when a booking is first made.','dbem').$bookings_placeholder_tip ?></td></tr>
1066
+ <?php
1067
+ em_options_input_text ( __( 'Contact person email subject', 'dbem' ), 'dbem_bookings_contact_email_subject', '' );
1068
+ em_options_textarea ( __( 'Contact person email', 'dbem' ), 'dbem_bookings_contact_email_body', '' );
1069
+ ?>
1070
+ <tr><td colspan='2'><h4><?php _e('Contact person booking cancelled','dbem') ?></h4></td></tr>
1071
+ <tr><td colspan='2'><?php echo __('An email will be sent to the event contact if someone cancels their booking.','dbem').$bookings_placeholder_tip ?></td></tr>
1072
+ <?php
1073
+ em_options_input_text ( __( 'Contact person cancellation subject', 'dbem' ), 'dbem_contactperson_email_cancelled_subject', '' );
1074
+ em_options_textarea ( __( 'Contact person cancellation email', 'dbem' ), 'dbem_contactperson_email_cancelled_body', '' );
1075
+ ?>
1076
+ <tr><td colspan='2'><h4><?php _e('Confirmed booking email','dbem') ?></h4></td></tr>
1077
+ <tr><td colspan='2'><?php echo __('This is sent when a person\'s booking is confirmed. This will be sent automatically if approvals are required and the booking is approved. If approvals are disabled, this is sent out when a user first submits their booking.','dbem').$bookings_placeholder_tip ?></td></tr>
1078
+ <?php
1079
+ em_options_input_text ( __( 'Booking confirmed email subject', 'dbem' ), 'dbem_bookings_email_confirmed_subject', '' );
1080
+ em_options_textarea ( __( 'Booking confirmed email', 'dbem' ), 'dbem_bookings_email_confirmed_body', '' );
1081
+ ?>
1082
+ <tr><td colspan='2'><h4><?php _e('Pending booking email','dbem') ?></h4></td></tr>
1083
+ <tr><td colspan='2'><?php echo __( 'This will be sent to the person when they first submit their booking. Not relevant if bookings don\'t require approval.', 'dbem' ).$bookings_placeholder_tip ?></td></tr>
1084
+ <?php
1085
+ em_options_input_text ( __( 'Booking pending email subject', 'dbem' ), 'dbem_bookings_email_pending_subject', '');
1086
+ em_options_textarea ( __( 'Booking pending email', 'dbem' ), 'dbem_bookings_email_pending_body','') ;
1087
+ ?>
1088
+ <tr><td colspan='2'><h4><?php _e('Rejected booking email','dbem') ?></h4></td></tr>
1089
+ <tr><td colspan='2'><?php echo __( 'This will be sent automatically when a booking is rejected. Not relevant if bookings don\'t require approval.', 'dbem' ).$bookings_placeholder_tip ?></td></tr>
1090
+ <?php
1091
+ em_options_input_text ( __( 'Booking rejected email subject', 'dbem' ), 'dbem_bookings_email_rejected_subject', __( "The subject of the email sent to the person making a booking that is awaiting administrator approval. Not relevant if bookings don't require approval.", 'dbem' ).$bookings_placeholder_tip );
1092
+ em_options_textarea ( __( 'Booking rejected email', 'dbem' ), 'dbem_bookings_email_rejected_body', __( 'The body of the email which will be sent to the person if the booking is rejected. Not relevant if bookings don\'t require approval.', 'dbem' ).$bookings_placeholder_tip );
1093
+ echo $save_button;
1094
+ ?>
1095
+ <tr><td colspan='2'><h4><?php _e('Booking cancelled','dbem') ?></h4></td></tr>
1096
+ <tr><td colspan='2'><?php echo __('This will be sent when a user cancels their booking.','dbem').$bookings_placeholder_tip ?></td></tr>
1097
+ <?php
1098
+ em_options_input_text ( __( 'Booking cancelled email subject', 'dbem' ), 'dbem_bookings_email_cancelled_subject', '' );
1099
+ em_options_textarea ( __( 'Booking cancelled email', 'dbem' ), 'dbem_bookings_email_cancelled_body', '' );
1100
+ ?>
1101
+ </table>
1102
+ </div> <!-- . inside -->
1103
+ </div> <!-- .postbox -->
1104
+ <?php endif; ?>
1105
+
1106
+ <div class="postbox " >
1107
+ <div class="handlediv" title="<?php __('Click to toggle', 'dbem'); ?>"><br /></div><h3><span><?php _e ( 'Event Email Templates', 'dbem' ); ?> </span></h3>
1108
+ <div class="inside">
1109
+ <table class='form-table'>
1110
+ <tr><td colspan='2'><strong><?php _e('Event Approved','dbem') ?></strong></td></tr>
1111
+ <tr><td colspan='2'><?php echo __('An email will be sent to the event owner when their event is approved. Users requiring event approval do not have the <code>publish_events</code> capability.','dbem').$bookings_placeholder_tip ?></td></tr>
1112
+ <?php
1113
+ em_options_input_text ( __( 'Event approved subject', 'dbem' ), 'dbem_event_approved_email_subject', '' );
1114
+ em_options_textarea ( __( 'Event approved email', 'dbem' ), 'dbem_event_approved_email_body', '' );
1115
+ ?>
1116
+ </table>
1117
+ </div> <!-- . inside -->
1118
+ </div> <!-- .postbox -->
1119
+
1120
+ </div><!-- .em-group-emails -->
1121
+ <?php /*
1122
  <div class="postbox " >
1123
+ <div class="handlediv" title="<?php __('Click to toggle', 'dbem'); ?>"><br /></div><h3><span><?php _e ( 'Debug Modes', 'dbem' ); ?> </span></h3>
1124
  <div class="inside">
1125
  <table class='form-table'>
1126
  <?php
1127
+ em_options_radio_binary ( __( 'EM Debug Mode?', 'dbem' ), 'dbem_debug', __( 'Setting this to yes will display different content to admins for event pages and emails so you can see all the available placeholders and their values.', 'dbem' ) );
1128
+ em_options_radio_binary ( __( 'WP Debug Mode?', 'dbem' ), 'dbem_wp_debug', __( 'This will turn WP_DEBUG mode on. Useful if you want to troubleshoot php errors without looking at your logs.', 'dbem' ) );
 
 
1129
  ?>
1130
+ </table>
1131
  </div> <!-- . inside -->
1132
  </div> <!-- .postbox -->
1133
+ */ ?>
1134
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1135
  <p class="submit">
1136
  <input type="submit" id="dbem_options_submit" name="Submit" value="<?php _e ( 'Save Changes' )?>" />
1137
  <input type="hidden" name="em-submitted" value="1" />
1138
+ <input type="hidden" name="_wpnonce" value="<?php echo wp_create_nonce('events-manager-options'); ?>" />
1139
  </p>
1140
 
1141
  </div> <!-- .metabox-sortables -->
1146
  </div>
1147
  <?php
1148
  }
1149
+
1150
+ /**
1151
+ * Meta options box for anonymous events. Shared in both MS and Normal options page, hence it's own function
1152
+ */
1153
+ function em_admin_option_box_anon_events(){
1154
+ global $save_button;
1155
+ ?>
1156
+ <div class="postbox" >
1157
+ <div class="handlediv" title="<?php __('Click to toggle', 'dbem'); ?>"><br /></div><h3><span><?php _e ( 'Anonymous Event Submission', 'dbem' ); ?> (Beta)</span></h3>
1158
+ <div class="inside">
1159
+ <table class="form-table">
1160
+ <tr><td colspan="2">
1161
+ <strong><?php _e('You can allow users to publicly submit events on your blog by using the [event_form] shortcode, and enabling anonymous submissions below.','dbem')?> (beta)</strong><br />
1162
+ </td></tr>
1163
+ <?php
1164
+ em_options_radio_binary ( __( 'Allow anonymous event submissions?', 'dbem' ), 'dbem_events_anonymous_submissions', __( 'Would you like to allow users to submit bookings anonymously? If so, you can use the new [event_form] shortcode or <code>em_event_form()</code> template tag with this enabled.', 'dbem' ) );
1165
+ em_options_select ( __('Guest Default User', 'dbem'), 'dbem_events_anonymous_user', em_get_wp_users (), __( 'Events require a user to own them. In order to allow events to be submitted anonymously you need to assign that event a specific user. We recommend you create a "Anonymous" subscriber with a very good password and use that. Guests will have the same event permissions as this user when submitting.', 'dbem' ) );
1166
+ em_options_textarea ( __( 'Success Message', 'dbem' ), 'dbem_events_anonymous_result_success', __( 'Anonymous submitters cannot see or modify their event once submitted. You can customize the success message they see here.', 'dbem' ).$events_placeholder_tip );
1167
+ ?>
1168
+ <?php echo $save_button; ?>
1169
+ </table>
1170
+ </div> <!-- . inside -->
1171
+ </div> <!-- .postbox -->
1172
+ <?php
1173
+ }
1174
+
1175
+ /**
1176
+ * Meta options box for image sizes. Shared in both MS and Normal options page, hence it's own function
1177
+ */
1178
+ function em_admin_option_box_image_sizes(){
1179
+ global $save_button;
1180
+ ?>
1181
+ <div class="postbox " >
1182
+ <div class="handlediv" title="<?php __('Click to toggle', 'dbem'); ?>"><br /></div><h3><span><?php _e ( 'Image Sizes', 'dbem' ); ?> </span></h3>
1183
+ <div class="inside">
1184
+ <table class='form-table'>
1185
+ <?php
1186
+ em_options_input_text ( __( 'Maximum width (px)', 'dbem' ), 'dbem_image_max_width', __( 'The maximum allowed width for images uploades', 'dbem' ) );
1187
+ em_options_input_text ( __( 'Maximum height (px)', 'dbem' ), 'dbem_image_max_height', __( "The maximum allowed height for images uploaded, in pixels", 'dbem' ) );
1188
+ em_options_input_text ( __( 'Maximum size (bytes)', 'dbem' ), 'dbem_image_max_size', __( "The maximum allowed size for images uploaded, in bytes", 'dbem' ) );
1189
+ echo $save_button;
1190
+ ?>
1191
+ </table>
1192
+ </div> <!-- . inside -->
1193
+ </div> <!-- .postbox -->
1194
+ <?php
1195
+ }
1196
+
1197
+ /**
1198
+ * Meta options box for email settings. Shared in both MS and Normal options page, hence it's own function
1199
+ */
1200
+ function em_admin_option_box_email(){
1201
+ global $save_button;
1202
+ ?>
1203
+ <div class="postbox " >
1204
+ <div class="handlediv" title="<?php __('Click to toggle', 'dbem'); ?>"><br /></div><h3><span><?php _e ( 'Email Settings', 'dbem' ); ?></span></h3>
1205
+ <div class="inside">
1206
+ <table class='form-table'>
1207
+ <?php
1208
+ em_options_input_text ( __( 'Notification sender name', 'dbem' ), 'dbem_mail_sender_name', __( "Insert the display name of the notification sender.", 'dbem' ) );
1209
+ em_options_input_text ( __( 'Notification sender address', 'dbem' ), 'dbem_mail_sender_address', __( "Insert the address of the notification sender.", 'dbem' ) );
1210
+ em_options_input_text ( 'Mail sending port', 'dbem_rsvp_mail_port', __( "The port through which you e-mail notifications will be sent. Make sure the firewall doesn't block this port", 'dbem' ) );
1211
+ em_options_select ( __( 'Mail sending method', 'dbem' ), 'dbem_rsvp_mail_send_method', array ('smtp' => 'SMTP', 'mail' => __( 'PHP mail function', 'dbem' ), 'sendmail' => 'Sendmail', 'qmail' => 'Qmail', 'wp_mail' => 'WP Mail' ), __( 'Select the method to send email notification.', 'dbem' ) );
1212
+ em_options_radio_binary ( __( 'Use SMTP authentication?', 'dbem' ), 'dbem_rsvp_mail_SMTPAuth', __( 'SMTP authentication is often needed. If you use GMail, make sure to set this parameter to Yes', 'dbem' ) );
1213
+ em_options_input_text ( 'SMTP host', 'dbem_smtp_host', __( "The SMTP host. Usually it corresponds to 'localhost'. If you use GMail, set this value to 'ssl://smtp.gmail.com:465'.", 'dbem' ) );
1214
+ em_options_input_text ( __( 'SMTP username', 'dbem' ), 'dbem_smtp_username', __( "Insert the username to be used to access your SMTP server.", 'dbem' ) );
1215
+ em_options_input_password ( __( 'SMTP password', 'dbem' ), "dbem_smtp_password", __( "Insert the password to be used to access your SMTP server", 'dbem' ) );
1216
+ echo $save_button;
1217
+ ?>
1218
+ </table>
1219
+ </div> <!-- . inside -->
1220
+ </div> <!-- .postbox -->
1221
+ <?php
1222
+ }
1223
+
1224
+ /**
1225
+ * Meta options box for user capabilities. Shared in both MS and Normal options page, hence it's own function
1226
+ */
1227
+ function em_admin_option_box_caps(){
1228
+ global $save_button;
1229
+ ?>
1230
+ <div class="postbox" >
1231
+ <div class="handlediv" title="<?php __('Click to toggle', 'dbem'); ?>"><br /></div><h3><span><?php _e ( 'User Capabilities', 'dbem' ); ?></span></h3>
1232
+ <div class="inside">
1233
+ <table class="form-table">
1234
+ <tr><td colspan="2">
1235
+ <strong><?php _e('Warning: Changing these values may result in exposing previously hidden information to all users.', 'dbem')?></strong><br />
1236
+ </td></tr>
1237
+ <?php
1238
+ global $wp_roles;
1239
+ $cap_docs = array(
1240
+ sprintf(__('%s Capabilities','dbem'),__('Event','dbem')) => array(
1241
+ /* Event Capabilities */
1242
+ 'publish_events' => sprintf(__('Users can publish %s and skip any admin approval','dbem'),__('events','dbem')),
1243
+ 'delete_others_events' => sprintf(__('User can delete other users %s','dbem'),__('events','dbem')),
1244
+ 'edit_others_events' => sprintf(__('User can edit other users %s','dbem'),__('events','dbem')),
1245
+ 'delete_events' => sprintf(__('User can delete their own %s','dbem'),__('events','dbem')),
1246
+ 'edit_events' => sprintf(__('User can create and edit %s','dbem'),__('events','dbem')),
1247
+ 'read_private_events' => sprintf(__('User can view private %s','dbem'),__('events','dbem')),
1248
+ /*'read_events' => sprintf(__('User can view %s','dbem'),__('events','dbem')),*/
1249
+ ),
1250
+ sprintf(__('%s Capabilities','dbem'),__('Recurring Event','dbem')) => array(
1251
+ /* Recurring Event Capabilties */
1252
+ 'publish_recurring_events' => sprintf(__('Users can publish %s and skip any admin approval','dbem'),__('recurring events','dbem')),
1253
+ 'delete_others_recurring_events' => sprintf(__('User can delete other users %s','dbem'),__('recurring events','dbem')),
1254
+ 'edit_others_recurring_events' => sprintf(__('User can edit other users %s','dbem'),__('recurring events','dbem')),
1255
+ 'delete_recurring_events' => sprintf(__('User can delete their own %s','dbem'),__('recurring events','dbem')),
1256
+ 'edit_recurring_events' => sprintf(__('User can create and edit %s','dbem'),__('recurring events','dbem'))
1257
+ ),
1258
+ sprintf(__('%s Capabilities','dbem'),__('Location','dbem')) => array(
1259
+ /* Location Capabilities */
1260
+ 'publish_locations' => sprintf(__('Users can publish %s and skip any admin approval','dbem'),__('locations','dbem')),
1261
+ 'delete_others_locations' => sprintf(__('User can delete other users %s','dbem'),__('locations','dbem')),
1262
+ 'edit_others_locations' => sprintf(__('User can edit other users %s','dbem'),__('locations','dbem')),
1263
+ 'delete_locations' => sprintf(__('User can delete their own %s','dbem'),__('locations','dbem')),
1264
+ 'edit_locations' => sprintf(__('User can create and edit %s','dbem'),__('locations','dbem')),
1265
+ 'read_private_locations' => sprintf(__('User can view private %s','dbem'),__('locations','dbem')),
1266
+ 'read_others_locations' => __('User can use other user locations for their events.','dbem'),
1267
+ /*'read_locations' => sprintf(__('User can view %s','dbem'),__('locations','dbem')),*/
1268
+ ),
1269
+ sprintf(__('%s Capabilities','dbem'),__('Other','dbem')) => array(
1270
+ /* Category Capabilities */
1271
+ 'delete_event_categories' => sprintf(__('User can delete %s categories and tags.','dbem'),__('event','dbem')),
1272
+ 'edit_event_categories' => sprintf(__('User can edit %s categories and tags.','dbem'),__('event','dbem')),
1273
+ /* Booking Capabilities */
1274
+ 'manage_others_bookings' => __('User can manage other users individual bookings and event booking settings.','dbem'),
1275
+ 'manage_bookings' => __('User can use and manage bookings with their events.','dbem'),
1276
+ )
1277
+ );
1278
+ ?>
1279
+ <tr><td colspan="2">
1280
+ <p><em><?php _e('You can now give fine grained control with regards to what your users can do with events. Each user role can have perform different sets of actions.','dbem'); ?></em></p>
1281
+ <table class="em-caps-table" style="width:auto;" cellspacing="0" cellpadding="0">
1282
+ <thead>
1283
+ <tr>
1284
+ <td>&nbsp;</td>
1285
+ <?php
1286
+ $odd = 0;
1287
+ foreach(array_keys($cap_docs) as $capability_group){
1288
+ ?><th class="<?php echo ( !is_int($odd/2) ) ? 'odd':''; ?>"><?php echo $capability_group ?></th><?php
1289
+ $odd++;
1290
+ }
1291
+ ?>
1292
+ </tr>
1293
+ </thead>
1294
+ <tbody>
1295
+ <?php foreach($wp_roles->role_objects as $role): ?>
1296
+ <tr>
1297
+ <td class="cap"><strong><?php echo $role->name; ?></strong></td>
1298
+ <?php
1299
+ $odd = 0;
1300
+ foreach($cap_docs as $capability_group){
1301
+ ?>
1302
+ <td class="<?php echo ( !is_int($odd/2) ) ? 'odd':''; ?>">
1303
+ <?php foreach($capability_group as $cap => $cap_help){ ?>
1304
+ <input type="checkbox" name="em_capabilities[<?php echo $role->name; ?>][<?php echo $cap ?>]" value="1" id="<?php echo $role->name.'_'.$cap; ?>" <?php echo $role->has_cap($cap) ? 'checked="checked"':''; ?> />
1305
+ &nbsp;<label for="<?php echo $role->name.'_'.$cap; ?>"><?php echo $cap; ?></label>&nbsp;<a href="#" title="<?php echo $cap_help; ?>">?</a>
1306
+ <br />
1307
+ <?php } ?>
1308
+ </td>
1309
+ <?php
1310
+ $odd++;
1311
+ }
1312
+ ?>
1313
+ </tr>
1314
+ <?php endforeach; ?>
1315
+ </tbody>
1316
+ </table>
1317
+ </td></tr>
1318
+ <?php echo $save_button; ?>
1319
+ </table>
1320
+ </div> <!-- . inside -->
1321
+ </div> <!-- .postbox -->
1322
+ <?php
1323
+ }
1324
+
1325
+ function em_admin_option_box_uninstall(){
1326
+ if( is_multisite() ){
1327
+ $uninstall_url = admin_url().'network/admin.php?page=events-manager-options&amp;action=uninstall&amp;_wpnonce='.wp_create_nonce('em_uninstall_'.get_current_user_id().'_wpnonce');
1328
+ $reset_url = admin_url().'network/admin.php?page=events-manager-options&amp;action=reset&amp;_wpnonce='.wp_create_nonce('em_reset_'.get_current_user_id().'_wpnonce');
1329
+ }else{
1330
+ $uninstall_url = EM_ADMIN_URL.'&amp;page=events-manager-options&amp;action=uninstall&amp;_wpnonce='.wp_create_nonce('em_uninstall_'.get_current_user_id().'_wpnonce');
1331
+ $reset_url = EM_ADMIN_URL.'&amp;page=events-manager-options&amp;action=reset&amp;_wpnonce='.wp_create_nonce('em_reset_'.get_current_user_id().'_wpnonce');
1332
+ }
1333
+ ?>
1334
+ <div class="postbox" >
1335
+ <div class="handlediv" title="<?php __('Click to toggle', 'dbem'); ?>"><br /></div><h3><span><?php _e ( 'Uninstall/Reset', 'dbem' ); ?></span></h3>
1336
+ <div class="inside">
1337
+ <p><?php _e('Use the buttons below to uninstall Events Manager completely from your system or reset Events Manager to original settings and keep your event data.','dbem'); ?></p>
1338
+ <a href="<?php echo $uninstall_url; ?>" class="button-secondary"><?php _e('Uninstall','dbem'); ?></a>
1339
+ <a href="<?php echo $reset_url; ?>" class="button-secondary"><?php _e('Reset','dbem'); ?></a>
1340
+ </div>
1341
+ </div>
1342
+ <?php
1343
+ }
1344
  ?>
admin/em-people.php DELETED
@@ -1,192 +0,0 @@
1
- <?php
2
- /**
3
- * Check for flags to save personal data
4
- */
5
- function em_person_actions(){
6
- global $EM_Person;
7
- if( !empty($_REQUEST['action']) && is_object($EM_Person) ){
8
- if( $_REQUEST['action'] == 'edit_person' ){
9
- $validation = $EM_Person->get_post();
10
- if ( $validation ) { //EM_Event gets the event if submitted via POST and validates it (safer than to depend on JS)
11
- //Save
12
- if( $EM_Person->save() ) {
13
- function em_person_save_notification(){
14
- global $EM_Person;
15
- ?><div class="updated"><p><strong><?php echo $EM_Person->feedback_message; ?></strong></p></div><?php
16
- }
17
- }else{
18
- function em_person_save_notification(){
19
- global $EM_Person;
20
- ?><div class="error"><p><strong><?php echo $EM_Person->feedback_message; ?></strong></p></div><?php
21
- }
22
- }
23
- }else{
24
- //TODO make errors clearer when saving person
25
- function em_person_save_notification(){
26
- global $EM_Person;
27
- ?><div class="error"><p><strong><?php echo $EM_Person->feedback_message; ?></strong></p></div><?php
28
- }
29
- }
30
- add_action ( 'admin_notices', 'em_person_save_notification' );
31
- }
32
- if( $_REQUEST['action'] == 'person_delete' ){
33
- if( $EM_Person->delete() ){
34
- //TODO delete person needs confirmation
35
- wp_redirect( get_bloginfo('wpurl').'/wp-admin/admin.php?page=events-manager-bookings');
36
- exit();
37
- }else{
38
- function em_person_delete_notification(){
39
- global $EM_Person;
40
- ?><div class="error"><p><strong><?php echo $EM_Person->feedback_message; ?></strong></p></div><?php
41
- }
42
- }
43
- add_action ( 'admin_notices', 'em_person_delete_notification' );
44
- }
45
- }
46
- }
47
- add_action('admin_init','em_person_actions');
48
-
49
- /**
50
- * Generate an edit form for person details.
51
- */
52
- function em_person_edit_form(){
53
- global $EM_Person;
54
- ?>
55
- <form action="" method="post" id="em-person-form">
56
- <table>
57
- <tr><td><strong><?php _e('Name','dbem'); ?></strong></td><td><input type="text" name="person_name" size="60" value="<?php echo $EM_Person->name; ?>" /></td></tr>
58
- <tr><td><strong><?php _e('Phone','dbem'); ?></strong></td><td><input type="text" name="person_phone" size="60" value="<?php echo $EM_Person->phone; ?>" /></td></tr>
59
- <tr><td><strong><?php _e('E-mail','dbem'); ?></strong></td><td><input type="text" name="person_email" size="60" value="<?php echo $EM_Person->email; ?>" /></td></tr>
60
- </table>
61
- <p class="submit">
62
- <input type="submit" name="events_update" value="<?php _e ( 'Save' ); ?> &raquo;" />
63
- </p>
64
- <input type="hidden" name="action" value="person_edit" />
65
- <input type="hidden" name="person_id" value="<?php echo $EM_Person->id; ?>" />
66
- </form>
67
- <?php
68
- }
69
-
70
- /**
71
- * Depreciated page... for now at least.
72
- */
73
- function em_admin_people_page() {
74
- ?>
75
- <div class='wrap'>
76
- <div id="icon-users" class="icon32"><br/></div>
77
- <h2>People</h2>
78
- <?php
79
- $EM_People = EM_People::get();
80
- if (count($EM_People) < 1 ) {
81
- _e("No people have responded to your events yet!", 'dbem');
82
- } else {
83
- ?>
84
- <p><?php _e('This table collects the data about the people who responded to your events', 'dbem') ?></p>
85
- <table id='dbem-people-table' class='widefat post fixed'>
86
- <thead>
87
- <tr>
88
- <th class='manage-column column-cb check-column' scope='col'>&nbsp;</th>
89
- <th class='manage-column ' scope='col'>Name</th>
90
- <th scope='col'>E-mail</th>
91
- <th scope='col'>Phone number</th>
92
- </tr>
93
- </thead>
94
- <tfoot>
95
- <tr>
96
- <th class='manage-column column-cb check-column' scope='col'>&nbsp;</th>
97
- <th class='manage-column ' scope='col'>Name</th>
98
- <th scope='col'>E-mail</th>
99
- <th scope='col'>Phone number</th>
100
- </tr>
101
- </tfoot>
102
- <?php foreach ($EM_People as $EM_Person): ?>
103
- <tr>
104
- <td>&nbsp;</td>
105
- <td><?php echo $EM_Person->name ?></td>
106
- <td><?php echo $EM_Person->email ?></td>
107
- <td><?php echo $EM_Person->phone ?></td>
108
- </tr>
109
- <?php endforeach; ?>
110
- </table>
111
- <?php
112
- }
113
- ?>
114
- </div>
115
- <?php
116
- }
117
-
118
- function em_printable_booking_report() {
119
- global $EM_Event;
120
- //check that user can access this page
121
- if( isset($_GET['page']) && $_GET['page']=='events-manager-bookings' && isset($_GET['action']) && $_GET['action'] == 'bookings_report' && is_object($EM_Event)){
122
- if( is_object($EM_Event) && !$EM_Event->can_manage() ){
123
- ?>
124
- <div class="wrap"><h2><?php _e('Unauthorized Access','dbem'); ?></h2><p><?php _e('You do not have the rights to manage this event.','dbem'); ?></p></div>
125
- <?php
126
- return false;
127
- }
128
- ?>
129
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
130
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
131
- <html>
132
- <head>
133
- <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
134
- <title>Bookings for <?php echo $EM_Event->name; ?></title>
135
- <link rel="stylesheet" href="<?php echo bloginfo('wpurl') ?>/wp-content/plugins/events-manager/includes/css/events_manager.css" type="text/css" media="screen" />
136
- </head>
137
- <body id="printable">
138
- <div id="container">
139
- <h1>Bookings for <?php echo $EM_Event->name; ?></h1>
140
- <p><?php echo $EM_Event->output("#d #M #Y"); ?></p>
141
- <p><?php echo $EM_Event->output("#_LOCATION, #_ADDRESS, #_TOWN"); ?></p>
142
- <h2><?php _e('Bookings data', 'dbem');?></h2>
143
- <table id="bookings-table">
144
- <tr>
145
- <th scope='col'><?php _e('Name', 'dbem')?></th>
146
- <th scope='col'><?php _e('E-mail', 'dbem')?></th>
147
- <th scope='col'><?php _e('Phone number', 'dbem')?></th>
148
- <th scope='col'><?php _e('Seats', 'dbem')?></th>
149
- <th scope='col'><?php _e('Comment', 'dbem')?></th>
150
- </tr>
151
- <?php foreach($EM_Event->get_bookings()->bookings as $EM_Booking) { ?>
152
- <tr>
153
-
154
- <td><?php echo $EM_Booking->person->name ?></td>
155
- <td><?php echo $EM_Booking->person->email ?></td>
156
- <td><?php echo $EM_Booking->person->phone ?></td>
157
- <td class='seats-number'><?php echo $EM_Booking->seats ?></td>
158
- <td><?php echo $EM_Booking->comment ?></td>
159
- </tr>
160
- <?php } ?>
161
- <tr id='booked-seats'>
162
- <td colspan='3'>&nbsp;</td>
163
- <td class='total-label'><?php _e('Booked', 'dbem')?>:</td>
164
- <td class='seats-number'><?php echo $EM_Event->get_bookings()->get_booked_seats(); ?></td>
165
- </tr>
166
- <tr id='available-seats'>
167
- <td colspan='3'>&nbsp;</td>
168
- <td class='total-label'><?php _e('Available', 'dbem')?>:</td>
169
- <td class='seats-number'><?php echo $EM_Event->get_bookings()->get_available_seats(); ?></td>
170
- </tr>
171
- </table>
172
- </div>
173
- </body>
174
- </html>
175
- <?php
176
- die();
177
- }
178
- }
179
- add_action('admin_init', 'em_printable_booking_report');
180
-
181
- /**
182
- * Adds phone number to contact info of users, compatible with previous phone field method
183
- * @param $array
184
- * @return array
185
- */
186
- function em_contact_methods($array){
187
- $array['dbem_phone'] = __('Phone','dbem') . ' <span class="description">('. __('Events Manager','dbem') .')</span>';
188
- return $array;
189
- }
190
- add_filter( 'user_contactmethods' , 'em_contact_methods' , 10 , 1 );
191
-
192
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
buddypress/bp-em-activity.php ADDED
@@ -0,0 +1,126 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // This file handles hooks/filter requiring activity stream publications
3
+
4
+ /**
5
+ * bp_em_record_activity()
6
+ *
7
+ * If the activity stream component is installed, this function will record activity items for your
8
+ * component.
9
+ */
10
+ function bp_em_record_activity( $args = '' ) {
11
+ if ( !function_exists( 'bp_activity_add' ) )
12
+ return false;
13
+
14
+ $defaults = array(
15
+ 'id' => false,
16
+ 'user_id' => '',
17
+ 'action' => '',
18
+ 'content' => '',
19
+ 'primary_link' => '',
20
+ 'component' => 'events-manager',
21
+ 'type' => false,
22
+ 'item_id' => false,
23
+ 'secondary_item_id' => false,
24
+ 'recorded_time' => gmdate( "Y-m-d H:i:s" ),
25
+ 'hide_sitewide' => false
26
+ );
27
+
28
+ $r = wp_parse_args( $args, $defaults );
29
+ extract( $r );
30
+
31
+ return bp_activity_add( array( 'id' => $id, 'user_id' => $user_id, 'action' => $action, 'content' => $content, 'primary_link' => $primary_link, 'component' => $component, 'type' => $type, 'item_id' => $item_id, 'secondary_item_id' => $secondary_item_id, 'recorded_time' => $recorded_time, 'hide_sitewide' => $hide_sitewide ) );
32
+ }
33
+
34
+ /**
35
+ * Records new events to the activity stream.
36
+ * @param unknown_type $result
37
+ * @param unknown_type $EM_Event
38
+ * @return unknown
39
+ */
40
+ function bp_em_record_activity_event_save( $result, $EM_Event ){
41
+ if( $result && $EM_Event->event_status == 1 && empty($EM_Event->previous_status) ){
42
+ $user = get_userdata($EM_Event->event_owner);
43
+ $member_slug = function_exists( 'bp_get_members_root_slug' ) ? bp_get_members_root_slug() : BP_MEMBERS_SLUG;
44
+ $member_link = trailingslashit(bp_get_root_domain()) . $member_slug . '/' . $user->user_login;
45
+ if( empty($EM_Event->group_id) ){
46
+ bp_em_record_activity( array(
47
+ 'user_id' => $user->ID,
48
+ 'action' => sprintf(__('%s added the event %s','dbem'), "<a href='".$member_link."/'>".$user->display_name."</a>", $EM_Event->output('#_EVENTLINK') ),
49
+ 'primary_link' => $EM_Event->output('#_EVENTURL'),
50
+ 'type' => 'new_event',
51
+ 'item_id' => $EM_Event->id,
52
+ ));
53
+ }else{
54
+ //tis a group event
55
+ $group = new BP_Groups_Group($EM_Event->group_id);
56
+ bp_em_record_activity( array(
57
+ 'user_id' => $user->ID,
58
+ 'action' => sprintf(__('%s added the event %s to %s.','dbem'), "<a href='".$member_link."/'>".$user->display_name."</a>", $EM_Event->output('#_EVENTLINK'), '<a href="'.bp_get_group_permalink($group).'">'.bp_get_group_name($group).'</a>' ),
59
+ 'component' => 'groups',
60
+ 'type' => 'new_event',
61
+ 'item_id' => $EM_Event->group_id,
62
+ ));
63
+ }
64
+ }
65
+ return $result;
66
+ }
67
+ add_filter('em_event_save','bp_em_record_activity_event_save', 10, 2);
68
+
69
+ /**
70
+ * @param boolean $result
71
+ * @param EM_Booking $EM_Booking
72
+ * @return boolean
73
+ */
74
+ function bp_em_record_activity_booking_save( $result, $EM_Booking ){
75
+ if( $result ){
76
+ $rejected_statuses = array(0,2,3); //these statuses apply to rejected/cancelled bookings
77
+ $user = $EM_Booking->person;
78
+ $member_slug = function_exists( 'bp_get_members_root_slug' ) ? bp_get_members_root_slug() : BP_MEMBERS_SLUG;
79
+ $member_link = trailingslashit(bp_get_root_domain()) . $member_slug . '/' . $user->user_login;
80
+ $user_link = "<a href='".$member_link."/'>".$user->display_name."</a>";
81
+ $event_link = $EM_Booking->get_event()->output('#_EVENTLINK');
82
+ $status = $EM_Booking->booking_status;
83
+ $EM_Event = $EM_Booking->get_event();
84
+ if( empty($EM_Event->group_id) ){
85
+ if( $status == 1 || (!get_option('dbem_bookings_approval') && $status < 2) ){
86
+ $action = sprintf(__('%s is attending %s.','dbem'), $user_link, $event_link );
87
+ }elseif( ($EM_Booking->previous_status == 1 || (!get_option('dbem_bookings_approval') && $EM_Booking->previous_status < 2)) && in_array($status, $rejected_statuses) ){
88
+ $action = sprintf(__('%s will not be attending %s anymore.','dbem'), $user_link, $event_link );
89
+ }
90
+ }else{
91
+ $group = new BP_Groups_Group($EM_Event->group_id);
92
+ $group_link = '<a href="'.bp_get_group_permalink($group).'">'.bp_get_group_name($group).'</a>';
93
+ if( $status == 1 || (!get_option('dbem_bookings_approval') && $status < 2) ){
94
+ $action = sprintf(__('%s is attending %s of the group %s.','dbem'), $user_link, $event_link, $group_link );
95
+ }elseif( ($EM_Booking->previous_status == 1 || (!get_option('dbem_bookings_approval') && $EM_Booking->previous_status < 2)) && in_array($status, $rejected_statuses) ){
96
+ $action = sprintf(__('%s will not be attending %s of group %s anymore.','dbem'), $user_link, $event_link, $group_link );
97
+ }
98
+ }
99
+ if( !empty($action) ){
100
+ bp_em_record_activity( array(
101
+ 'user_id' => $EM_Booking->person->ID,
102
+ 'action' => $action,
103
+ 'primary_link' => $EM_Event->output('#_EVENTURL'),
104
+ 'type' => 'new_booking',
105
+ 'item_id' => $EM_Event->id,
106
+ 'secondary_item_id' => $EM_Booking->booking_id
107
+ ));
108
+ //group activity
109
+ if( !empty($EM_Event->group_id) ){
110
+ //tis a group event
111
+ bp_em_record_activity( array(
112
+ 'component' => 'groups',
113
+ 'item_id' => $EM_Event->group_id,
114
+ 'user_id' => $EM_Booking->person->ID,
115
+ 'action' => $action,
116
+ 'primary_link' => $EM_Event->output('#_EVENTURL'),
117
+ 'type' => 'new_booking',
118
+ 'secondary_item_id' => $EM_Booking->booking_id
119
+ ));
120
+ }
121
+ }
122
+ }
123
+ return $result;
124
+ }
125
+ add_filter('em_booking_save','bp_em_record_activity_booking_save', 10, 2);
126
+ add_filter('em_booking_delete','bp_em_record_activity_booking_save', 10, 2);
buddypress/bp-em-core.php ADDED
@@ -0,0 +1,240 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ //Main loader for buddypress
3
+ /**
4
+ * Events Manager component for BuddyPress
5
+ * @author marcus
6
+ * @since 5.0
7
+ */
8
+ class BP_EM_Component extends BP_Component {
9
+
10
+ function __construct() {
11
+ global $bp;
12
+ parent::start('events', __('Events', 'dbem'), EM_DIR);
13
+ $this->includes();
14
+ //TODO make BP component optional
15
+ $bp->active_components[$this->id] = '1';
16
+ }
17
+
18
+ function includes() {
19
+ // Files to include
20
+ $includes = array(
21
+ 'buddypress/bp-em-activity.php',
22
+ 'buddypress/bp-em-templatetags.php',
23
+ 'buddypress/bp-em-notifications.php',
24
+ 'buddypress/bp-em-groups.php',
25
+ 'buddypress/screens/profile.php',
26
+ 'buddypress/screens/my-events.php',
27
+ 'buddypress/screens/my-locations.php',
28
+ 'buddypress/screens/attending.php',
29
+ 'buddypress/screens/my-bookings.php',
30
+ 'buddypress/screens/my-group-events.php',
31
+ 'buddypress/screens/group-events.php',
32
+ );
33
+ parent::includes( $includes );
34
+ //TODO add admin pages for extra BP specific settings
35
+ }
36
+
37
+ /**
38
+ * Sets up the global Events Manager BuddyPress Components
39
+ */
40
+ function setup_globals() {
41
+ global $bp, $wpdb;
42
+ // Define a slug constant that will be used to view this components pages
43
+ if ( !defined( 'BP_EM_SLUG' ) )
44
+ define ( 'BP_EM_SLUG', EM_POST_TYPE_EVENT_SLUG );
45
+
46
+ // Set up the $globals array to be passed along to parent::setup_globals()
47
+ $globals = array(
48
+ 'slug' => BP_EM_SLUG,
49
+ 'has_directory' => false, //already done by EM
50
+ 'notification_callback' => 'bp_em_format_notifications',
51
+ 'search_string' => sprintf(__( 'Search %s...', 'dbem' ),__('Events','dbem')),
52
+ );
53
+
54
+ // Let BP_Component::setup_globals() do its work.
55
+ parent::setup_globals( $globals );
56
+
57
+ //quick link shortcut - may need to revisit this
58
+ $bp->{$this->id}->link = trailingslashit($bp->loggedin_user->domain).BP_EM_SLUG.'/';
59
+ }
60
+
61
+ function setup_nav() {
62
+ global $blog_id;
63
+ //check multisite or normal mode for correct permission checking
64
+ if(is_multisite() && $blog_id != BP_ROOT_BLOG){
65
+ //FIXME MS mode doesn't seem to recognize cross subsite caps, using the proper functions, for now we use switch_blog.
66
+ $current_blog = $blog_id;
67
+ switch_to_blog(BP_ROOT_BLOG);
68
+ $can_manage_events = current_user_can_for_blog(BP_ROOT_BLOG, 'edit_events');
69
+ $can_manage_locations = current_user_can_for_blog(BP_ROOT_BLOG, 'edit_locations');
70
+ $can_manage_bookings = current_user_can_for_blog(BP_ROOT_BLOG, 'manage_bookings');
71
+ switch_to_blog($current_blog);
72
+ }else{
73
+ $can_manage_events = current_user_can('edit_events');
74
+ $can_manage_locations = current_user_can('edit_locations');
75
+ $can_manage_bookings = current_user_can('manage_bookings');
76
+ }
77
+ /* Add 'Events' to the main user profile navigation */
78
+ $main_nav = array(
79
+ 'name' => __( 'Events', 'dbem' ),
80
+ 'slug' => em_bp_get_slug(),
81
+ 'position' => 80,
82
+ 'screen_function' => 'bp_em_events',
83
+ 'default_subnav_slug' => 'profile'
84
+ );
85
+
86
+ $em_link = trailingslashit( bp_loggedin_user_domain() . em_bp_get_slug() );
87
+
88
+ /* Create SubNav Items */
89
+ $sub_nav[] = array(
90
+ 'name' => __( 'My Profile', 'dbem' ),
91
+ 'slug' => 'profile',
92
+ 'parent_slug' => em_bp_get_slug(),
93
+ 'parent_url' => $em_link,
94
+ 'screen_function' => 'bp_em_events',
95
+ 'position' => 10
96
+ );
97
+
98
+ $sub_nav[] = array(
99
+ 'name' => __( 'Events I\'m Attending', 'dbem' ),
100
+ 'slug' => 'attending',
101
+ 'parent_slug' => em_bp_get_slug(),
102
+ 'parent_url' => $em_link,
103
+ 'screen_function' => 'bp_em_attending',
104
+ 'position' => 20,
105
+ 'user_has_access' => bp_is_my_profile() // Only the logged in user can access this on his/her profile
106
+ );
107
+
108
+ if( $can_manage_events ){
109
+ $sub_nav[] = array(
110
+ 'name' => __( 'My Events', 'dbem' ),
111
+ 'slug' => 'my-events',
112
+ 'parent_slug' => em_bp_get_slug(),
113
+ 'parent_url' => $em_link,
114
+ 'screen_function' => 'bp_em_my_events',
115
+ 'position' => 30,
116
+ 'user_has_access' => bp_is_my_profile() // Only the logged in user can access this on his/her profile
117
+ );
118
+ }
119
+
120
+ if( $can_manage_locations && get_option('dbem_locations_enabled') ){
121
+ $sub_nav[] = array(
122
+ 'name' => __( 'My Locations', 'dbem' ),
123
+ 'slug' => 'my-locations',
124
+ 'parent_slug' => em_bp_get_slug(),
125
+ 'parent_url' => $em_link,
126
+ 'screen_function' => 'bp_em_my_locations',
127
+ 'position' => 40,
128
+ 'user_has_access' => bp_is_my_profile() // Only the logged in user can access this on his/her profile
129
+ );
130
+ }
131
+
132
+ if( $can_manage_bookings && get_option('dbem_rsvp_enabled') ){
133
+ $sub_nav[] = array(
134
+ 'name' => __( 'My Event Bookings', 'dbem' ),
135
+ 'slug' => 'my-bookings',
136
+ 'parent_slug' => em_bp_get_slug(),
137
+ 'parent_url' => $em_link,
138
+ 'screen_function' => 'bp_em_my_bookings',
139
+ 'position' => 50,
140
+ 'user_has_access' => bp_is_my_profile() // Only the logged in user can access this on his/her profile
141
+ );
142
+ }
143
+
144
+ /* Create Profile Group Sub-Nav */
145
+ $sub_nav[] = array(
146
+ 'name' => __( 'Events', 'dbem' ),
147
+ 'slug' => 'group-events',
148
+ 'parent_slug' => bp_get_groups_slug(),
149
+ 'parent_url' =>trailingslashit( bp_loggedin_user_domain() . bp_get_groups_slug() ),
150
+ 'screen_function' => 'bp_em_my_group_events',
151
+ 'position' => 60,
152
+ 'user_has_access' => bp_is_my_profile() // Only the logged in user can access this on his/her profile
153
+ );
154
+
155
+ parent::setup_nav( $main_nav, $sub_nav );
156
+ add_action( 'bp_init', array(&$this, 'setup_group_nav') );
157
+ }
158
+
159
+ function setup_group_nav(){
160
+ global $bp;
161
+ /* Add some group subnav items */
162
+ $user_access = false;
163
+ $group_link = '';
164
+ if( !empty($bp->groups->current_group) ){
165
+ $group_link = $bp->root_domain . '/' . $bp->groups->slug . '/' . $bp->groups->current_group->slug . '/';
166
+ $user_access = $bp->groups->current_group->user_has_access;
167
+ if( !empty($bp->current_component) && $bp->current_component == 'groups' ){
168
+ $count = EM_Events::count(array('group'=>$bp->groups->current_group->id));
169
+ if( empty($count) ) $count = 0;
170
+ }
171
+ bp_core_new_subnav_item( array(
172
+ 'name' => __( 'Events', 'dbem' ) . " <span>$count</span>",
173
+ 'slug' => 'events',
174
+ 'parent_url' => $group_link,
175
+ 'parent_slug' => $bp->groups->current_group->slug,
176
+ 'screen_function' => 'bp_em_group_events',
177
+ 'position' => 50,
178
+ 'user_has_access' => $user_access,
179
+ 'item_css_id' => 'forums'
180
+ ));
181
+ }
182
+ }
183
+ }
184
+ function bp_em_load_core_component() {
185
+ global $bp;
186
+ $bp->events = new BP_EM_Component();
187
+ }
188
+ add_action( 'bp_loaded', 'bp_em_load_core_component' );
189
+
190
+
191
+ /**
192
+ * Some links may need rewriting in case a BP user wants to edit parts of their events, which would require a link to the right BP screen
193
+ * @param string $replace
194
+ * @param EM_Event $object
195
+ * @param string $result
196
+ * @return string
197
+ */
198
+ function em_bp_rewrite_links($replace, $EM_Event, $result){
199
+ global $bp;
200
+ if( is_object($EM_Event) && get_class($EM_Event)=='EM_Event' ){
201
+ switch( $result ){
202
+ case '#_EDITEVENTURL':
203
+ case '#_EDITEVENTLINK':
204
+ if( $EM_Event->can_manage('edit_events','edit_others_events') && !is_admin() ){
205
+ $replace = $bp->events->link.'my-events/edit/?event_id='.$EM_Event->event_id;
206
+ if($result == '#_EDITEVENTLINK'){
207
+ $replace = "<a href='".$replace."'>".__('Edit', 'dbem').' '.__('Event', 'dbem')."</a>";
208
+ }
209
+ }
210
+ break;
211
+ case '#_BOOKINGSLINK':
212
+ case '#_BOOKINGSURL':
213
+ if( $EM_Event->can_manage('manage_bookings','manage_others_bookings') && !is_admin() ){
214
+ $replace = $bp->events->link.'my-bookings/?event_id='.$EM_Event->event_id;
215
+ if($result == '#_BOOKINGSLINK'){
216
+ $replace = "<a href='{$replace}' title='{$EM_Event->event_name}'>{$EM_Event->event_name}</a>";
217
+ }
218
+ }
219
+ break;
220
+ }
221
+ }
222
+ return $replace;
223
+ }
224
+ add_filter('em_event_output_placeholder','em_bp_rewrite_links',10,3);
225
+
226
+ /**
227
+ * Delete events when you delete a user.
228
+ */
229
+ function bp_em_remove_data( $user_id ) {
230
+ $EM_Events = EM_Events::get(array('scope'=>'all','owner'=>$user_id, 'status'=>false));
231
+ EM_Events::delete($EM_Events);
232
+ }
233
+ add_action( 'wpmu_delete_user', 'bp_em_remove_data', 1 );
234
+ add_action( 'delete_user', 'bp_em_remove_data', 1 );
235
+
236
+ function bp_example_var_dump() {
237
+ global $bp;
238
+ echo "<pre>"; print_r( $bp ); echo "<pre>";
239
+ }
240
+ ?>
buddypress/bp-em-groups.php ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @param EM_Event $EM_Event
4
+ */
5
+ function bp_em_group_event_save($EM_Event){
6
+ if( is_object($EM_Event) && empty($EM_Event->group_id) && !empty($_REQUEST['group_id']) && is_numeric($_REQUEST['group_id']) ){
7
+ //we have been requested an event creation tied to a group, so does this group exist, and does this person have admin rights to it?
8
+ if( groups_is_user_admin(get_current_user_id(), $_REQUEST['group_id']) ){
9
+ $EM_Event->group_id = $_REQUEST['group_id'];
10
+ }
11
+ }
12
+ return $EM_Event;
13
+ }
14
+ add_action('em_event_save_pre','bp_em_group_event_save',1,1);
15
+
16
+ /**
17
+ * @param boolean $result
18
+ * @param EM_Event $EM_Event
19
+ */
20
+ function bp_em_group_event_can_manage( $result, $EM_Event){
21
+ if( !$result && !empty($EM_Event->group_id) ){ //only override if already false, incase it's true
22
+ if( groups_is_user_admin(get_current_user_id(),$EM_Event->group_id) && current_user_can('edit_events') ){
23
+ //This user is an admin of the owner's group, so they can edit this event.
24
+ return true;
25
+ }
26
+ }
27
+ return $result;
28
+ }
29
+ add_filter('em_event_can_manage','bp_em_group_event_can_manage',1,2);
30
+
31
+
32
+ function bp_em_group_events_accepted_searches($searches){
33
+ $searches[] = 'group';
34
+ return $searches;
35
+ }
36
+ add_filter('em_accepted_searches','bp_em_group_events_accepted_searches',1,1);
37
+
38
+ function bp_em_group_events_get_default_search($searches, $array){
39
+ if( !empty($array['group']) && (is_numeric($array['group']) || $array['group'] == 'my') ){
40
+ $searches['group'] = $array['group'];
41
+ }
42
+ return $searches;
43
+ }
44
+ add_filter('em_events_get_default_search','bp_em_group_events_get_default_search',1,2);
45
+
46
+ function bp_em_group_events_build_sql_conditions( $conditions, $args ){
47
+ if( !empty($args['group']) && is_numeric($args['group']) ){
48
+ $conditions['group'] = "( `group_id`={$args['group']} )";
49
+ }elseif( !empty($args['group']) && $args['group'] == 'my' ){
50
+ $groups = groups_get_user_groups(get_current_user_id());
51
+ if( count($groups) > 0 ){
52
+ $conditions['group'] = "( `group_id` IN (".implode(',',$groups['groups']).") )";
53
+ }
54
+ }
55
+ return $conditions;
56
+ }
57
+ add_filter('em_events_build_sql_conditions','bp_em_group_events_build_sql_conditions',1,2);
buddypress/bp-em-notifications.php ADDED
@@ -0,0 +1,82 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ //This file handles hooks requiring notifications
3
+
4
+ /**
5
+ * bp_em_format_notifications()
6
+ *
7
+ * The format notification function will take DB entries for notifications and format them
8
+ * so that they can be displayed and read on the screen.
9
+ *
10
+ * Notifications are "screen" notifications, that is, they appear on the notifications menu
11
+ * in the site wide navigation bar. They are not for email notifications.
12
+ *
13
+ *
14
+ * The recording is done by using bp_core_add_notification() which you can search for in this file for
15
+ * ems of usage.
16
+ */
17
+ function bp_em_format_notifications( $action, $item_id, $secondary_item_id, $total_items ) {
18
+ global $bp;
19
+ switch ( $action ) {
20
+ case 'pending_booking':
21
+ //Count pending bookings
22
+ if( get_option('dbem_bookings_approval')){
23
+ if ( $total_items > 1 ) {
24
+ return '<a href="' . $bp->loggedin_user->domain . $bp->events->slug . '/my-bookings/" title="' . __( 'My Bookings', 'dbem' ) . '">' . __('You have a pending booking','dbem'). '</a>';
25
+ } else {
26
+ return apply_filters( 'bp_em_format_new_booking_notification', '<a href="' . $bp->loggedin_user->domain . $bp->events->slug . '/my-bookings/" title="' . __( 'My Bookings', 'dbem' ) . '">' . sprintf(__('You have %s pending bookings','dbem'), $total_items). '</a>' );
27
+ }
28
+ }
29
+ break;
30
+ case 'confirmed_booking':
31
+ //Count pending bookings
32
+ if ( $total_items > 1 ) {
33
+ return apply_filters( 'bp_em_format_confirmed_booking_notifications', '<a href="' . $bp->loggedin_user->domain . $bp->events->slug . '/my-bookings/" title="' . __( 'My Bookings', 'dbem' ) . '">' . __('You have a confirmed booking','dbem'). '</a>' );
34
+ } else {
35
+ return apply_filters( 'bp_em_format_confirmed_booking_notification', '<a href="' . $bp->loggedin_user->domain . $bp->events->slug . '/my-bookings/" title="' . __( 'My Bookings', 'dbem' ) . '">' . sprintf(__('You have %s confirmed bookings','dbem'), $total_items). '</a>' );
36
+ }
37
+ break;
38
+ case 'cancelled_booking':
39
+ //Count pending bookings
40
+ if ( $total_items > 1 ) {
41
+ return apply_filters( 'bp_em_format_cancelled_booking_notifications', '<a href="' . $bp->loggedin_user->domain . $bp->events->slug . '/my-bookings/" title="' . __( 'My Bookings', 'dbem' ) . '">' . __('A user cancelled a booking','dbem'). '</a>' );
42
+ } else {
43
+ return apply_filters( 'bp_em_format_cancelled_booking_notification', '<a href="' . $bp->loggedin_user->domain . $bp->events->slug . '/my-bookings/" title="' . __( 'My Bookings', 'dbem' ) . '">' . sprintf(__('%s users cancelled bookings.','dbem'), $total_items). '</a>' );
44
+ }
45
+ break;
46
+ }
47
+ do_action( 'bp_em_format_notifications', $action, $item_id, $secondary_item_id, $total_items );
48
+
49
+ return false;
50
+ }
51
+
52
+ /**
53
+ * Remove a screen notification for a user.
54
+ */
55
+ function bp_em_remove_screen_notifications() {
56
+ global $bp;
57
+ bp_core_delete_notifications_for_user_by_type( $bp->loggedin_user->id, $bp->events->slug, 'attending' );
58
+ }
59
+ add_action( 'bp_em_my_events', 'bp_em_remove_screen_notifications' );
60
+ add_action( 'xprofile_screen_display_profile', 'bp_em_remove_screen_notifications' );
61
+
62
+ /**
63
+ * Catch booking saves and add a BP notification.
64
+ * @param boolean $result
65
+ * @param EM_Booking $EM_Booking
66
+ * @return boolean
67
+ */
68
+ function bp_em_add_booking_notification($result, $EM_Booking){
69
+ global $bp;
70
+ if( get_option('dbem_bookings_approval') && $EM_Booking->status == 0 ){
71
+ $action = 'pending_booking';
72
+ }elseif( $EM_Booking->status == 1 || (get_option('dbem_bookings_approval') && $EM_Booking->status == 0) ){
73
+ $action = 'confirmed_booking';
74
+ }elseif( $EM_Booking->status == 3 ){
75
+ $action = 'cancelled_booking';
76
+ }
77
+ if( !empty($action) ){
78
+ bp_core_add_notification( $EM_Booking->booking_id, $EM_Booking->get_event()->owner, 'events', $action );
79
+ }
80
+ return $result;
81
+ }
82
+ add_filter('em_booking_save','bp_em_add_booking_notification',1,2);
buddypress/bp-em-templatetags.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Echo the Events Manager BuddyPresss component's slug
4
+ * @since 5.0
5
+ */
6
+ function em_bp_slug() {
7
+ echo em_bp_get_slug();
8
+ }
9
+ /**
10
+ * Return the Events Manager BuddyPresss component's slug
11
+ *
12
+ * @since 5.0
13
+ * @uses apply_filters() Filter 'em_bp_get_slug' to change the output
14
+ * @return str $slug The slug from $bp->events->slug, if it exists
15
+ */
16
+ function em_bp_get_slug() {
17
+ global $bp;
18
+ // Avoid PHP warnings, in case the value is not set for some reason
19
+ $slug = !empty( $bp->evebts->slug ) ? $bp->events->slug : BP_EM_SLUG;
20
+ return apply_filters( 'em_bp_get_slug', $slug );
21
+ }
buddypress/screens/attending.php ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * bp_em_screen_two()
4
+ *
5
+ * Sets up and displays the screen output for the sub nav item "em/screen-two"
6
+ */
7
+ function bp_em_attending() {
8
+ global $bp;
9
+ /**
10
+ * If the user has not Accepted or Rejected anything, then the code above will not run,
11
+ * we can continue and load the template.
12
+ */
13
+ do_action( 'bp_em_attending' );
14
+
15
+ add_action( 'bp_template_title', 'bp_em_attending_title' );
16
+ add_action( 'bp_template_content', 'bp_em_attending_content' );
17
+
18
+ /* Finally load the plugin template file. */
19
+ bp_core_load_template( apply_filters( 'bp_core_template_plugin', 'members/single/plugins' ) );
20
+ }
21
+
22
+ function bp_em_attending_title() {
23
+ _e( 'Events I\'m Attending', 'dbem' );
24
+ }
25
+
26
+ function bp_em_attending_content() {
27
+ //We can use the same template as the public user interface for non bp sites
28
+ em_locate_template('templates/my-bookings.php',true);
29
+ }
buddypress/screens/group-events.php ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Controller for the event views in BP (using mvc terms here)
4
+ */
5
+ function bp_em_group_events() {
6
+ global $bp;
7
+ do_action( 'bp_em_group_events' );
8
+
9
+ //plug into EM admin code (at least for now)
10
+ include_once(EM_DIR.'/admin/em-admin.php');
11
+
12
+ add_action( 'bp_template_title', 'bp_em_group_events_title' );
13
+ add_action( 'bp_template_content', 'bp_em_group_events_content' );
14
+
15
+ /* Finally load the plugin template file. */
16
+ bp_core_load_template( apply_filters( 'bp_core_template_plugin', 'groups/single/plugins' ) );
17
+ }
18
+
19
+ function bp_em_group_events_title() {
20
+ _e( 'Group Events', 'dbem' );
21
+ }
22
+ /**
23
+ * Determines whether to show event page or events page, and saves any updates to the event or events
24
+ * @return null
25
+ */
26
+ function bp_em_group_events_content() {
27
+ em_locate_template('buddypress/group-events.php', true);
28
+ }
29
+
30
+ ?>
buddypress/screens/my-bookings.php ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * bp_em_screen_two()
4
+ *
5
+ * Sets up and displays the screen output for the sub nav item "em/screen-two"
6
+ */
7
+ function bp_em_my_bookings() {
8
+ global $bp, $EM_Event;
9
+
10
+ //assume any notifications here are considered viewed via this page
11
+ bp_core_delete_notifications_for_user_by_type(get_current_user_id(), 'events','pending_booking');
12
+ bp_core_delete_notifications_for_user_by_type(get_current_user_id(), 'events','confirmed_booking');
13
+ bp_core_delete_notifications_for_user_by_type(get_current_user_id(), 'events','cancelled_booking');
14
+
15
+ em_load_event();
16
+ /**
17
+ * If the user has not Accepted or Rejected anything, then the code above will not run,
18
+ * we can continue and load the template.
19
+ */
20
+ do_action( 'bp_em_my_bookings' );
21
+
22
+ add_action( 'bp_template_title', 'bp_em_my_bookings_title' );
23
+ add_action( 'bp_template_content', 'bp_em_my_bookings_content' );
24
+
25
+ /* Finally load the plugin template file. */
26
+ bp_core_load_template( apply_filters( 'bp_core_template_plugin', 'members/single/plugins' ) );
27
+ }
28
+
29
+ function bp_em_my_bookings_title() {
30
+ _e( 'My Event Bookings', 'dbem' );
31
+ }
32
+
33
+ function bp_em_my_bookings_content() {
34
+ em_locate_template('buddypress/my-bookings.php',true);
35
+ }
buddypress/screens/my-events.php ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Controller for the event views in BP (using mvc terms here)
4
+ */
5
+ function bp_em_my_events() {
6
+ global $bp, $EM_Event;
7
+ if( !is_object($EM_Event) && !empty($_REQUEST['event_id']) ){
8
+ $EM_Event = new EM_Event($_REQUEST['event_id']);
9
+ }
10
+
11
+ do_action( 'bp_em_my_events' );
12
+
13
+ //plug into EM admin code (at least for now)
14
+ include_once(EM_DIR.'/admin/em-admin.php');
15
+ EM_Scripts_and_Styles::localize_script();
16
+
17
+ $template_title = 'bp_em_my_events_title';
18
+ $template_content = 'bp_em_my_events_content';
19
+
20
+ if( count($bp->action_variables) > 0 ){
21
+ if( !empty($bp->action_variables[0]) ){
22
+ switch($bp->action_variables[0]){
23
+ case 'edit':
24
+ $template_title = 'bp_em_my_events_editor_title';
25
+ $template_content = 'bp_em_my_events_editor';
26
+ break;
27
+ }
28
+ }
29
+ }
30
+
31
+ add_action( 'bp_template_title', $template_title );
32
+ add_action( 'bp_template_content', $template_content );
33
+
34
+ /* Finally load the plugin template file. */
35
+ bp_core_load_template( apply_filters( 'bp_core_template_plugin', 'members/single/plugins' ) );
36
+ }
37
+
38
+ function bp_em_my_events_title() {
39
+ _e( 'My Events', 'dbem' );
40
+ }
41
+
42
+ /**
43
+ * Determines whether to show event page or events page, and saves any updates to the event or events
44
+ * @return null
45
+ */
46
+ function bp_em_my_events_content() {
47
+ em_locate_template('buddypress/my-events.php', true);
48
+ }
49
+
50
+ function bp_em_my_events_editor_title() {
51
+ global $EM_Event;
52
+ if( is_object($EM_Event) ){
53
+ if($EM_Event->is_recurring()){
54
+ _e( "Reschedule Events", 'dbem' )." '{$EM_Event->event_name}'";
55
+ }else{
56
+ _e ( "Edit Event", 'dbem' ) . " '" . $EM_Event->event_name . "'";
57
+ }
58
+ }else{
59
+ _e( 'Add Event', 'dbem' );
60
+ }
61
+ }
62
+
63
+ function bp_em_my_events_editor(){
64
+ em_locate_template('forms/event-editor.php', true);
65
+ }
66
+
67
+ ?>
buddypress/screens/my-group-events.php ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Controller for the event views in BP (using mvc terms here)
4
+ */
5
+ function bp_em_my_group_events() {
6
+ global $bp;
7
+ do_action( 'bp_em_my_group_events' );
8
+
9
+ //plug into EM admin code (at least for now)
10
+ include_once(EM_DIR.'/admin/em-admin.php');
11
+
12
+ add_action( 'bp_template_title', 'bp_em_my_group_events_title' );
13
+ add_action( 'bp_template_content', 'bp_em_my_group_events_content' );
14
+
15
+ /* Finally load the plugin template file. */
16
+ bp_core_load_template( apply_filters( 'bp_core_template_plugin', 'members/single/plugins' ) );
17
+ }
18
+
19
+ function bp_em_my_group_events_title() {
20
+ _e( 'Group Events', 'dbem' );
21
+ }
22
+
23
+ function bp_em_my_group_events_content(){
24
+ em_locate_template('buddypress/my-group-events.php', true);
25
+ }
26
+
27
+ ?>
buddypress/screens/my-locations.php ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Controller for the location views in BP (using mvc terms here)
4
+ */
5
+ function bp_em_my_locations() {
6
+ global $bp, $EM_Location;
7
+ if( !is_object($EM_Location) && !empty($_REQUEST['location_id']) ){
8
+ $EM_Location = new EM_Location($_REQUEST['location_id']);
9
+ }
10
+
11
+ do_action( 'bp_em_my_locations' );
12
+
13
+ //plug into EM admin code (at least for now)
14
+ include_once(EM_DIR.'/admin/em-admin.php');
15
+ EM_Scripts_and_Styles::localize_script();
16
+
17
+ $template_title = 'bp_em_my_locations_title';
18
+ $template_content = 'bp_em_my_locations_content';
19
+
20
+ if( !empty($_GET['action']) ){
21
+ switch($_GET['action']){
22
+ case 'edit':
23
+ $template_title = 'bp_em_my_locations_editor_title';
24
+ $template_content = 'bp_em_my_locations_editor_content';
25
+ break;
26
+ default :
27
+ $template_title = 'bp_em_my_locations_title';
28
+ $template_content = 'bp_em_my_locations_content';
29
+ break;
30
+ }
31
+ }else{
32
+ $template_title = 'bp_em_my_locations_title';
33
+ $template_content = 'bp_em_my_locations_content';
34
+ }
35
+
36
+ add_action( 'bp_template_title', $template_title );
37
+ add_action( 'bp_template_content', $template_content );
38
+
39
+ /* Finally load the plugin template file. */
40
+ bp_core_load_template( apply_filters( 'bp_core_template_plugin', 'members/single/plugins' ) );
41
+ }
42
+
43
+ function bp_em_my_locations_title() {
44
+ _e( 'My Locations', 'dbem' );
45
+ }
46
+
47
+ /**
48
+ * Determines whether to show location page or locations page, and saves any updates to the location or locations
49
+ * @return null
50
+ */
51
+ function bp_em_my_locations_content() {
52
+ em_locate_template('buddypress/my-locations.php', true);
53
+ }
54
+
55
+ function bp_em_my_locations_editor_title() {
56
+ global $EM_Location;
57
+ if( empty($EM_Location) || !is_object($EM_Location) ){
58
+ $title = __('Add location', 'dbem');
59
+ $EM_Location = new EM_Location();
60
+ }else{
61
+ $title = __('Edit location', 'dbem');
62
+ }
63
+ }
64
+
65
+ function bp_em_my_locations_editor_content(){
66
+ em_locate_template('forms/location-editor.php', true);
67
+ }
68
+
69
+ ?>
buddypress/screens/profile.php ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * bp_em_screen_one()
4
+ *
5
+ * Sets up and displays the screen output for the sub nav item "em/screen-one"
6
+ */
7
+ function bp_em_events() {
8
+ global $bp, $EM_Notices;
9
+
10
+ if( bp_is_my_profile() ){
11
+ $EM_Notices->add_info( __('You are currently viewing your public page, this is what other users will see.', 'dbem') );
12
+ }
13
+
14
+ /* Add a do action here, so your component can be extended by others. */
15
+ do_action( 'bp_em_events' );
16
+
17
+ add_action( 'bp_template_title', 'bp_em_events_title' );
18
+ add_action( 'bp_template_content', 'bp_em_events_content' );
19
+ bp_core_load_template( apply_filters( 'bp_core_template_plugin', 'members/single/plugins' ) );
20
+ //bp_core_load_template( apply_filters( 'bp_em_template_screen_one', 'em/screen-one' ) );
21
+ }
22
+ /***
23
+ * The second argument of each of the above add_action() calls is a function that will
24
+ * display the corresponding information. The functions are presented below:
25
+ */
26
+ function bp_em_events_title() {
27
+ _e( 'Events', 'dbem' );
28
+ }
29
+
30
+ function bp_em_events_content() {
31
+ em_locate_template('buddypress/profile.php',true);
32
+ }
classes/em-booking.php CHANGED
@@ -1,37 +1,63 @@
1
  <?php
2
  class EM_Booking extends EM_Object{
3
  //DB Fields
4
- var $id;
5
  var $event_id;
6
  var $person_id;
7
- var $seats;
8
- var $comment;
9
- var $status = 0;
10
- var $notes = array();
 
11
  var $fields = array(
12
  'booking_id' => array('name'=>'id','type'=>'%d'),
13
  'event_id' => array('name'=>'event_id','type'=>'%d'),
14
  'person_id' => array('name'=>'person_id','type'=>'%d'),
15
- 'booking_seats' => array('name'=>'seats','type'=>'%d'),
 
16
  'booking_comment' => array('name'=>'comment','type'=>'%s'),
17
- 'booking_status' => array('name'=>'status','type'=>'%d')
 
18
  );
19
  //Other Vars
 
20
  var $timestamp;
21
  var $person;
22
- var $required_fields = array('booking_id', 'event_id', 'person_id', 'booking_seats');
23
  var $feedback_message = "";
24
  var $errors = array();
 
 
 
 
 
25
  /**
26
  * If saved in this instance, you can see what previous approval status was.
27
  * @var int
28
  */
29
- var $previous_status = false;
30
  /**
31
  * The booking approval status number corresponds to a state in this array.
32
  * @var unknown_type
33
  */
34
  var $status_array = array();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
 
36
  /**
37
  * Creates booking object and retreives booking data (default is a blank booking object). Accepts either array of booking data (from db) or a booking id.
@@ -39,36 +65,34 @@ class EM_Booking extends EM_Object{
39
  * @return null
40
  */
41
  function EM_Booking( $booking_data = false ){
42
- if( !get_option('dbem_bookings_approval') ){
43
- $this->status = 1;
44
- }
45
- if( $booking_data !== false ){
46
  //Load booking data
47
  $booking = array();
48
  if( is_array($booking_data) ){
49
  $booking = $booking_data;
50
- //Also create a person out of this...
51
- $this->person = new EM_Person($booking_data);
52
- if( !empty($booking['person_id']) && $booking['person_id'] != $this->person->id){
53
- $this->person = new EM_Person($booking['booking_id']);
54
- }
55
  }elseif( is_numeric($booking_data) ){
56
  //Retreiving from the database
57
  global $wpdb;
58
- $sql = "SELECT * FROM ". $wpdb->prefix . EM_BOOKINGS_TABLE ." WHERE booking_id ='$booking_data'";
59
- $booking = $wpdb->get_row($sql, ARRAY_A);
60
- //Get the person for this booking
61
- $this->person = new EM_Person($booking['person_id']);
62
  //Booking notes
63
- $notes = $wpdb->get_results("SELECT * FROM ". $wpdb->prefix . EM_META_TABLE ." WHERE meta_key='booking-note' AND object_id ='$booking_data'", ARRAY_A);
64
  foreach($notes as $note){
65
  $this->notes[] = unserialize($note['meta_value']);
66
  }
67
  }
 
 
68
  //Save into the object
69
  $this->to_object($booking);
70
- if( !empty($booking['booking_date']) ){
71
- $this->timestamp = strtotime($booking['booking_date']);
 
 
 
72
  }
73
  }
74
  //Do it here so things appear in the po file.
@@ -76,50 +100,77 @@ class EM_Booking extends EM_Object{
76
  0 => __('Pending','dbem'),
77
  1 => __('Approved','dbem'),
78
  2 => __('Rejected','dbem'),
79
- 3 => __('Cacncelled','dbem')
 
 
80
  );
 
 
81
  }
82
 
83
  /**
84
  * Saves the booking into the database, whether a new or existing booking
 
85
  * @return boolean
86
  */
87
- function save(){
88
  global $wpdb;
89
- $table = $wpdb->prefix.EM_BOOKINGS_TABLE;
90
  do_action('em_booking_save_pre',$this);
91
- //First the person
92
- if($this->validate()){
93
- //Does this person exist?
94
- $person_result = $this->person->save();
95
- if( $person_result === false ){
96
- $this->errors = array_merge($this->errors, $this->person->errors);
97
- return false;
98
- }
99
- $this->person_id = $this->person->id;
100
-
101
- //Now we save the booking
102
- $data = $this->to_array();
103
- if($this->id != ''){
104
- $where = array( 'booking_id' => $this->id );
105
- $result = $wpdb->update($table, $data, $where, $this->get_types($data));
106
- $this->feedback_message = __('Changes saved');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
107
  }else{
108
- $result = $wpdb->insert($table, $data, $this->get_types($data));
109
- $this->id = $wpdb->insert_id;
110
- $this->feedback_message = __('Your booking has been recorded','dbem');
111
- }
112
- if( $result === false ){
113
  $this->feedback_message = __('There was a problem saving the booking.', 'dbem');
114
- $this->errors[] = __('There was a problem saving the booking.', 'dbem');
 
 
115
  }
116
- return apply_filters('em_booking_save', ( count($this->errors) == 0 ), $this);
117
  }else{
118
  $this->feedback_message = __('There was a problem saving the booking.', 'dbem');
119
- $this->errors[] = __('There was a problem saving the booking.', 'dbem');
120
- return apply_filters('em_booking_save', false, $this);
 
121
  }
122
- return true;
123
  }
124
 
125
  /**
@@ -141,6 +192,7 @@ class EM_Booking extends EM_Object{
141
  $result = $wpdb->get_row($sql, ARRAY_A);
142
  if($result){
143
  $this->to_object($result);
 
144
  return true;
145
  }else{
146
  return false;
@@ -151,34 +203,186 @@ class EM_Booking extends EM_Object{
151
  * Get posted data and save it into the object (not db)
152
  * @return boolean
153
  */
154
- function get_post(){
155
- //Currently, only editing allowed, so here we are.
156
- $this->comment = (!empty($_REQUEST['booking_comment'])) ? $_REQUEST['booking_comment']:'';
157
- $this->seats = (!empty($_REQUEST['booking_seats'])) ? $_REQUEST['booking_seats']:'';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
158
  return apply_filters('em_booking_get_post',$this->validate(),$this);
159
  }
160
 
161
  function validate(){
162
- return (
 
163
  (empty($this->event_id) || is_numeric($this->event_id)) &&
164
  (empty($this->person_id) || is_numeric($this->person_id)) &&
165
- is_numeric($this->seats)
166
  );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
167
  }
168
 
169
  /**
170
- * Smart event locator, saves a database read if possible.
 
171
  */
172
  function get_event(){
173
  global $EM_Event;
174
- if( !empty($this->event) && is_object($this->event) && get_class($this->event)=='EM_Event' && $this->event->id == $this->event_id ){
175
  return $this->event;
176
- }elseif( is_object($EM_Event) && $EM_Event->id == $this->event_id ){
177
  $this->event = $EM_Event;
178
  }else{
179
- $this->event = new EM_Event($this->event_id);
180
  }
181
- return $this->event;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
182
  }
183
 
184
  /**
@@ -186,20 +390,37 @@ class EM_Booking extends EM_Object{
186
  * @return string
187
  */
188
  function get_status(){
189
- return $this->status_array[$this->status];
 
190
  }
 
191
  /**
192
  * I wonder what this does....
193
  * @return boolean
194
  */
195
  function delete(){
196
  global $wpdb;
197
- $sql = $wpdb->prepare("DELETE FROM ". $wpdb->prefix.EM_BOOKINGS_TABLE . " WHERE booking_id=%d", $this->id);
198
- $result = $wpdb->query( $sql );
199
- return ( $result !== false );
 
 
 
 
 
 
 
 
 
 
 
 
200
  }
201
 
202
  function cancel(){
 
 
 
203
  return $this->set_status(3);
204
  }
205
 
@@ -227,29 +448,40 @@ class EM_Booking extends EM_Object{
227
 
228
  /**
229
  * Change the status of the booking. This will save to the Database too.
230
- * @param unknown_type $status
231
- * @return string|string|string
232
  */
233
- function set_status($status){
234
- $this->previous_status = $this->status;
235
- $this->status = $status;
236
- $result = $this->save();
237
  $action_string = strtolower($this->status_array[$status]);
238
- if($result){
 
 
 
 
 
 
 
 
 
 
239
  $this->feedback_message = sprintf(__('Booking %s.','dbem'), $action_string);
240
- if( $this->email() ){
241
- $this->feedback_message .= " ".__('Mail Sent.','dbem');
242
- }elseif( $this->previous_status == 0 ){
243
- //extra errors may be logged by email() in EM_Object
244
- $this->feedback_message .= ' <span style="color:red">'.__('ERROR : Mail Not Sent.','dbem').'</span>';
245
- return false;
 
 
 
246
  }
247
- return true;
248
  }else{
249
  //errors should be logged by save()
250
  $this->feedback_message = sprintf(__('Booking could not be %s.','dbem'), $action_string);
251
- return false;
252
  }
 
253
  }
254
 
255
  /**
@@ -263,7 +495,7 @@ class EM_Booking extends EM_Object{
263
  $note = array('author'=>get_current_user_id(),'note'=>$note_text,'timestamp'=>current_time('timestamp'));
264
  $this->notes[] = $note;
265
  $this->feedback_message = __('Booking note successfully added.','dbem');
266
- return $wpdb->insert($wpdb->prefix.EM_META_TABLE, array('object_id'=>$this->id, 'meta_key'=>'booking-note', 'meta_value'=> serialize($note)),array('%d','%s','%s'));
267
  }
268
  return false;
269
  }
@@ -275,66 +507,85 @@ class EM_Booking extends EM_Object{
275
  */
276
  function email(){
277
  global $EM_Mailer;
 
278
  $EM_Event = $this->get_event(); //We NEED event details here.
279
  //Make sure event matches booking, and that booking used to be approved.
280
- if( $this->previous_status == 0 || $this->status == 3 ){
281
- $contact_id = ( $EM_Event->contactperson_id != "") ? $EM_Event->contactperson_id : get_option('dbem_default_contact_person');
282
 
283
  $contact_subject = get_option('dbem_bookings_contact_email_subject');
284
  $contact_body = get_option('dbem_bookings_contact_email_body');
285
 
286
- if( (get_option('dbem_bookings_approval') == 0 && $this->previous_status === false) || $this->status == 1 ){
287
  $booker_subject = get_option('dbem_bookings_email_confirmed_subject');
288
  $booker_body = get_option('dbem_bookings_email_confirmed_body');
289
- }elseif( $this->status == 0 ){
290
  $booker_subject = get_option('dbem_bookings_email_pending_subject');
291
  $booker_body = get_option('dbem_bookings_email_pending_body');
292
- }elseif( $this->status == 2 ){
293
  $booker_subject = get_option('dbem_bookings_email_rejected_subject');
294
  $booker_body = get_option('dbem_bookings_email_rejected_body');
295
- }elseif( $this->status == 3 ){
296
  $booker_subject = get_option('dbem_bookings_email_cancelled_subject');
297
  $booker_body = get_option('dbem_bookings_email_cancelled_body');
298
  $contact_subject = get_option('dbem_contactperson_email_cancelled_subject');
299
  $contact_body = get_option('dbem_contactperson_email_cancelled_body');
 
 
300
  }
301
 
302
  // email specific placeholders
303
- $placeholders = array(
 
 
 
 
304
  '#_RESPNAME' => '#_BOOKINGNAME',//Depreciated
305
  '#_RESPEMAIL' => '#_BOOKINGEMAIL',//Depreciated
306
  '#_RESPPHONE' => '#_BOOKINGPHONE',//Depreciated
307
  '#_COMMENT' => '#_BOOKINGCOMMENT',//Depreciated
308
  '#_RESERVEDSPACES' => '#_BOOKEDSPACES',//Depreciated
309
- '#_BOOKINGNAME' => $this->person->name,
310
- '#_BOOKINGEMAIL' => $this->person->email,
 
311
  '#_BOOKINGPHONE' => $this->person->phone,
312
- '#_BOOKINGSPACES' => $this->seats,
313
- '#_BOOKINGCOMMENT' => $this->comment,
314
- );
 
 
 
 
 
 
 
 
 
 
 
 
315
  foreach($placeholders as $key => $value) {
316
  $contact_subject = str_replace($key, $value, $contact_subject);
317
  $contact_body = str_replace($key, $value, $contact_body);
318
  $booker_subject = str_replace($key, $value, $booker_subject);
319
  $booker_body = str_replace($key, $value, $booker_body);
320
  }
321
-
322
  $booker_subject = $EM_Event->output($booker_subject, 'email');
323
  $booker_body = $EM_Event->output($booker_body, 'email');
324
-
325
  //Send to the person booking
326
- if( !$this->email_send( $booker_subject,$booker_body, $this->person->email) ){
327
  return false;
328
  }
329
 
330
- //Send admin emails
331
- if( (get_option('dbem_bookings_approval') == 0 || $this->status == 0) && (get_option('dbem_bookings_contact_email') == 1 || get_option('dbem_bookings_notify_admin') != '') ){
332
  //Only gets sent if this is a pending booking, unless approvals are disabled.
333
  $contact_subject = $EM_Event->output($contact_subject, 'email');
334
  $contact_body = $EM_Event->output($contact_body, 'email');
335
 
336
  if( get_option('dbem_bookings_contact_email') == 1 ){
337
- if( !$this->email_send( $contact_subject, $contact_body, $EM_Event->contact->user_email) && current_user_can('activate_plugins')){
338
  $this->errors[] = __('Confirmation email could not be sent to contact person. Registrant should have gotten their email (only admin see this warning).','dbem');
339
  return false;
340
  }
@@ -357,7 +608,7 @@ class EM_Booking extends EM_Object{
357
  * Can the user manage this event?
358
  */
359
  function can_manage(){
360
- return ( get_option('dbem_permissions_events') || $this->get_event()->author == get_current_user_id() || em_verify_admin() );
361
  }
362
 
363
  /**
1
  <?php
2
  class EM_Booking extends EM_Object{
3
  //DB Fields
4
+ var $booking_id;
5
  var $event_id;
6
  var $person_id;
7
+ var $booking_price;
8
+ var $booking_spaces;
9
+ var $booking_comment;
10
+ var $booking_status = 0;
11
+ var $booking_meta = array();
12
  var $fields = array(
13
  'booking_id' => array('name'=>'id','type'=>'%d'),
14
  'event_id' => array('name'=>'event_id','type'=>'%d'),
15
  'person_id' => array('name'=>'person_id','type'=>'%d'),
16
+ 'booking_price' => array('name'=>'price','type'=>'%d'),
17
+ 'booking_spaces' => array('name'=>'spaces','type'=>'%d'),
18
  'booking_comment' => array('name'=>'comment','type'=>'%s'),
19
+ 'booking_status' => array('name'=>'status','type'=>'%d'),
20
+ 'booking_meta' => array('name'=>'meta','type'=>'%s')
21
  );
22
  //Other Vars
23
+ var $notes = array(); //loaded from em_meta table in construct
24
  var $timestamp;
25
  var $person;
26
+ var $required_fields = array('booking_id', 'event_id', 'person_id', 'booking_spaces');
27
  var $feedback_message = "";
28
  var $errors = array();
29
+ /**
30
+ * Contains an array of custom fields for a booking. This is loaded from em_meta, where the booking_custom name contains arrays of data.
31
+ * @var array
32
+ */
33
+ var $custom = array();
34
  /**
35
  * If saved in this instance, you can see what previous approval status was.
36
  * @var int
37
  */
38
+ var $previous_status;
39
  /**
40
  * The booking approval status number corresponds to a state in this array.
41
  * @var unknown_type
42
  */
43
  var $status_array = array();
44
+ /**
45
+ * @var EM_Tickets
46
+ */
47
+ var $tickets;
48
+ /**
49
+ * @var EM_Event
50
+ */
51
+ var $event;
52
+ /**
53
+ * @var EM_Tickets_Bookings
54
+ */
55
+ var $tickets_bookings;
56
+ /**
57
+ * If set to true, this booking can be managed by any logged in user.
58
+ * @var EM_Tickets_Bookings
59
+ */
60
+ var $manage_override;
61
 
62
  /**
63
  * Creates booking object and retreives booking data (default is a blank booking object). Accepts either array of booking data (from db) or a booking id.
65
  * @return null
66
  */
67
  function EM_Booking( $booking_data = false ){
68
+ //Get the person for this booking
69
+ if( $booking_data !== false ){
 
 
70
  //Load booking data
71
  $booking = array();
72
  if( is_array($booking_data) ){
73
  $booking = $booking_data;
 
 
 
 
 
74
  }elseif( is_numeric($booking_data) ){
75
  //Retreiving from the database
76
  global $wpdb;
77
+ $sql = "SELECT * FROM ". EM_BOOKINGS_TABLE ." LEFT JOIN ". EM_META_TABLE ." ON object_id=booking_id WHERE booking_id ='$booking_data'";
78
+ $booking = $wpdb->get_row($sql, ARRAY_A);
79
+ //Custom Fields
80
+ $custom = $wpdb->get_row("SELECT meta_key, meta_value FROM ". EM_BOOKINGS_TABLE ." LEFT JOIN ". EM_META_TABLE ." ON object_id=booking_id WHERE booking_id ='$booking_data' AND meta_key='booking_custom'");
81
  //Booking notes
82
+ $notes = $wpdb->get_results("SELECT * FROM ". EM_META_TABLE ." WHERE meta_key='booking-note' AND object_id ='$booking_data'", ARRAY_A);
83
  foreach($notes as $note){
84
  $this->notes[] = unserialize($note['meta_value']);
85
  }
86
  }
87
+ //booking meta
88
+ $booking['booking_meta'] = (!empty($booking['booking_meta'])) ? unserialize($booking['booking_meta']):array();
89
  //Save into the object
90
  $this->to_object($booking);
91
+ $this->get_person();
92
+ $this->timestamp = strtotime($booking['booking_date']);
93
+ //Add custom booking data
94
+ if( !empty($custom['meta_key']) && $custom['meta_key'] == 'booking_custom' && is_serialized($custom['meta_value']) ){
95
+ $this->custom = unserialize($custom['meta_value']);
96
  }
97
  }
98
  //Do it here so things appear in the po file.
100
  0 => __('Pending','dbem'),
101
  1 => __('Approved','dbem'),
102
  2 => __('Rejected','dbem'),
103
+ 3 => __('Cancelled','dbem'),
104
+ 4 => __('Awaiting Online Payment','dbem'),
105
+ 5 => __('Awaiting Payment','dbem')
106
  );
107
+ $this->compat_keys();
108
+ do_action('em_booking', $this, $booking_data);
109
  }
110
 
111
  /**
112
  * Saves the booking into the database, whether a new or existing booking
113
+ * @param $mail whether or not to email the user and contact people
114
  * @return boolean
115
  */
116
+ function save($mail = true){
117
  global $wpdb;
118
+ $table = EM_BOOKINGS_TABLE;
119
  do_action('em_booking_save_pre',$this);
120
+ if( $this->validate() ){
121
+ if( $this->can_manage() ){
122
+ $this->person_id = $this->get_person()->ID;
123
+ //Step 1. Save the booking
124
+ $data = $this->to_array();
125
+ $data['booking_meta'] = serialize($data['booking_meta']);
126
+ if($this->booking_id != ''){
127
+ $update = true;
128
+ //update price and spaces
129
+ $this->get_spaces(true);
130
+ $this->get_price(true);
131
+ $where = array( 'booking_id' => $this->booking_id );
132
+ $result = $wpdb->update($table, $data, $where, $this->get_types($data));
133
+ $result = ($result !== false);
134
+ $this->feedback_message = __('Changes saved','dbem');
135
+ }else{
136
+ $update = false;
137
+ $result = $wpdb->insert($table, $data, $this->get_types($data));
138
+ $this->id = $wpdb->insert_id;
139
+ $this->feedback_message = __('Your booking has been recorded','dbem');
140
+ }
141
+ //Step 2. Insert ticket bookings for this booking id if no errors so far
142
+ if( $result === false ){
143
+ $this->feedback_message = __('There was a problem saving the booking.', 'dbem');
144
+ $this->errors[] = __('There was a problem saving the booking.', 'dbem');
145
+ }else{
146
+ $tickets_bookings_result = $this->get_tickets_bookings()->save();
147
+ if( !$tickets_bookings_result ){
148
+ if( !$update ){
149
+ //delete the booking and tickets, instead of a transaction
150
+ $this->delete();
151
+ }
152
+ $this->errors[] = __('There was a problem saving the booking.', 'dbem');
153
+ $this->add_error( $this->get_tickets_bookings()->get_errors() );
154
+ }
155
+ }
156
+ //Step 3. email if necessary
157
+ if ( count($this->errors) == 0 && $mail ) {
158
+ $this->email();
159
+ }
160
+ return apply_filters('em_booking_save', ( count($this->errors) == 0 ), $this);
161
  }else{
 
 
 
 
 
162
  $this->feedback_message = __('There was a problem saving the booking.', 'dbem');
163
+ if( !$this->can_manage() ){
164
+ $this->feedback_message = sprintf(__('You cannot manage this %s.', 'dbem'),__('Booking','dbem'));
165
+ }
166
  }
 
167
  }else{
168
  $this->feedback_message = __('There was a problem saving the booking.', 'dbem');
169
+ if( !$this->can_manage() ){
170
+ $this->feedback_message = sprintf(__('You cannot manage this %s.', 'dbem'),__('Booking','dbem'));
171
+ }
172
  }
173
+ return apply_filters('em_booking_save', false, $this);
174
  }
175
 
176
  /**
192
  $result = $wpdb->get_row($sql, ARRAY_A);
193
  if($result){
194
  $this->to_object($result);
195
+ $this->person = new EM_Person($this->person_id);
196
  return true;
197
  }else{
198
  return false;
203
  * Get posted data and save it into the object (not db)
204
  * @return boolean
205
  */
206
+ function get_post( $override_availability = false ){
207
+ $this->tickets_bookings = new EM_Tickets_Bookings($this->booking_id);
208
+ do_action('em_booking_get_post_pre',$this);
209
+ $result = array();
210
+ $this->event_id = $_REQUEST['event_id'];
211
+ if( isset($_REQUEST['em_tickets']) && is_array($_REQUEST['em_tickets']) && ($_REQUEST['em_tickets'] || $override_availability) ){
212
+ foreach( $_REQUEST['em_tickets'] as $ticket_id => $values){
213
+ //make sure ticket exists
214
+ if( !empty($values['spaces']) || $override_availability ){
215
+ $args = array('ticket_id'=>$ticket_id, 'ticket_booking_spaces'=>$values['spaces'], 'booking_id'=>$this->id);
216
+ if($this->get_event()->get_bookings()->ticket_exists($ticket_id)){
217
+ $EM_Ticket_Booking = new EM_Ticket_Booking($args);
218
+ $EM_Ticket_Booking->booking = $this;
219
+ $this->tickets_bookings->add( $EM_Ticket_Booking, $override_availability );
220
+ }else{
221
+ $this->errors[]=__('You are trying to book a non-existent ticket for this event.','dbem');
222
+ }
223
+ }
224
+ }
225
+ $this->booking_comment = (!empty($_REQUEST['booking_comment'])) ? wp_kses_data(stripslashes($_REQUEST['booking_comment'])):'';
226
+ $this->get_spaces(true);
227
+ $this->get_price(true, false, false);
228
+ $this->get_person();
229
+ }
230
  return apply_filters('em_booking_get_post',$this->validate(),$this);
231
  }
232
 
233
  function validate(){
234
+ //step 1, basic info
235
+ $basic = (
236
  (empty($this->event_id) || is_numeric($this->event_id)) &&
237
  (empty($this->person_id) || is_numeric($this->person_id)) &&
238
+ is_numeric($this->booking_spaces) && $this->booking_spaces > 0
239
  );
240
+ //give some errors in step 1
241
+ if( $this->booking_spaces == 0 ){
242
+ $this->add_error(get_option('dbem_booking_feedback_min_space'));
243
+ }
244
+ //step 2, tickets bookings info
245
+ if( count($this->get_tickets_bookings()) > 0 ){
246
+ $ticket_validation = array();
247
+ foreach($this->get_tickets_bookings()->tickets_bookings as $EM_Ticket_Booking){
248
+ if ( !$EM_Ticket_Booking->validate() ){
249
+ $ticket_validation[] = false;
250
+ $result = $basic && !in_array(false,$ticket_validation);
251
+ }
252
+ $this->errors = array_merge($this->errors, $EM_Ticket_Booking->get_errors());
253
+ }
254
+ $result = $basic && !in_array(false,$ticket_validation);
255
+ }else{
256
+ $result = false;
257
+ }
258
+
259
+ return apply_filters('em_booking_validate',$result,$this);
260
+ }
261
+
262
+ /**
263
+ * Get the total number of spaces booked in THIS booking. Seting $force_refresh to true will recheck spaces, even if previously done so.
264
+ * @param unknown_type $force_refresh
265
+ * @return mixed
266
+ */
267
+ function get_spaces( $force_refresh=false ){
268
+ if($this->booking_spaces == 0 || $force_refresh == true ){
269
+ $this->booking_spaces = $this->get_tickets_bookings()->get_spaces($force_refresh);
270
+ }
271
+ return apply_filters('em_booking_get_spaces',$this->booking_spaces,$this);
272
+ }
273
+
274
+ /**
275
+ * Gets the total price for this whole booking. Seting $force_reset to true will recheck spaces, even if previously done so.
276
+ * @param boolean $force_refresh
277
+ * @param boolean $format
278
+ * @param boolean $add_tax
279
+ * @return float
280
+ */
281
+ function get_price( $force_refresh=false, $format=false, $add_tax='x' ){
282
+ if($force_refresh || $this->booking_price == 0 || $add_tax !== 'x' || get_option('dbem_bookings_tax_auto_add')){
283
+ $this->booking_price = $this->get_tickets_bookings()->get_price($force_refresh, false, $add_tax);
284
+ }
285
+ if($format){
286
+ return apply_filters('em_booking_get_price', em_get_currency_symbol().number_format($this->booking_price,2),$this);
287
+ }
288
+ return apply_filters('em_booking_get_price',$this->booking_price,$this);
289
  }
290
 
291
  /**
292
+ * Gets the event this booking belongs to and saves a refernece in the event property
293
+ * @return EM_Event
294
  */
295
  function get_event(){
296
  global $EM_Event;
297
+ if( is_object($this->event) && get_class($this->event)=='EM_Event' && $this->event->id == $this->event_id ){
298
  return $this->event;
299
+ }elseif( is_object($EM_Event) && ( (is_object($this->event) && $this->event->id == $this->event_id) || empty($this->booking_id)) ){
300
  $this->event = $EM_Event;
301
  }else{
302
+ $this->event = new EM_Event($this->event_id, 'event_id');
303
  }
304
+ return apply_filters('em_booking_get_event',$this->event);
305
+ }
306
+
307
+ /**
308
+ * Outdated, use booking meta array. Get custom fields for this booking.
309
+ * @return array
310
+ */
311
+ function get_custom(){
312
+ global $wpdb;
313
+ if( count($this->custom) == 0 ){
314
+ $sql = "SELECT * FROM ". EM_META_TABLE ." WHERE object_id ='{$this->booking_id}' AND (meta_key='booking_custom' OR meta_key IS NULL)";
315
+ $booking = $wpdb->get_row($sql, ARRAY_A);
316
+ //Add custom booking data
317
+ if( !empty($booking['meta_key']) && $booking['meta_key'] == 'booking_custom' && is_serialized($booking['meta_value']) ){
318
+ $this->custom = unserialize($booking['meta_value']);
319
+ }
320
+ }
321
+ return $this->custom;
322
+ }
323
+
324
+ /**
325
+ * Gets the ticket object this booking belongs to, saves a reference in ticket property
326
+ * @return EM_Tickets
327
+ */
328
+ function get_tickets(){
329
+ if( is_object($this->tickets) && get_class($this->tickets)=='EM_Tickets' ){
330
+ return apply_filters('em_booking_get_tickets', $this->tickets, $this);
331
+ }else{
332
+ $this->tickets = new EM_Tickets($this);
333
+ }
334
+ return apply_filters('em_booking_get_tickets', $this->tickets, $this);
335
+ }
336
+
337
+ /**
338
+ * Gets the ticket object this booking belongs to, saves a reference in ticket property
339
+ * @return EM_Tickets_Bookings
340
+ */
341
+ function get_tickets_bookings(){
342
+ global $wpdb;
343
+ if( !is_object($this->tickets_bookings) || get_class($this->tickets_bookings)!='EM_Tickets_Bookings'){
344
+ $this->tickets_bookings = new EM_Tickets_Bookings($this);
345
+ }
346
+ return apply_filters('em_booking_get_tickets_bookings', $this->tickets_bookings, $this);
347
+ }
348
+
349
+ function get_person(){
350
+ global $EM_Person;
351
+ if( is_object($this->person) && get_class($this->person)=='EM_Person' && ($this->person->ID == $this->person_id || empty($this->person_id) ) ){
352
+ //This person is already included, so don't do anything
353
+ }elseif( is_object($EM_Person) && ($EM_Person->ID === $this->person_id || $this->booking_id == '') ){
354
+ $this->person = $EM_Person;
355
+ }elseif( is_numeric($this->person_id) ){
356
+ $this->person = new EM_Person($this->person_id);
357
+ }else{
358
+ $this->person = new EM_Person(0);
359
+ }
360
+ //if this user is the parent user of disabled registrations, replace user details here:
361
+ if( get_option('dbem_bookings_registration_disable') && $this->person->ID == get_option('dbem_bookings_registration_user') ){
362
+ //override any registration data into the person objet
363
+ if( !empty($this->booking_meta['registration']) ){
364
+ foreach($this->booking_meta['registration'] as $key => $value){
365
+ $this->person->$key = $value;
366
+ }
367
+ }
368
+ $this->person->user_email = ( !empty($this->booking_meta['registration']['user_email']) ) ? $this->booking_meta['registration']['user_email']:$this->person->user_email;
369
+ if( !empty($this->booking_meta['registration']['user_name']) ){
370
+ $name_string = explode(' ',$this->booking_meta['registration']['user_name']);
371
+ $this->booking_meta['registration']['first_name'] = array_shift($name_string);
372
+ $this->booking_meta['registration']['last_name'] = implode(' ', $name_string);
373
+ }
374
+ $this->person->user_firstname = ( !empty($this->booking_meta['registration']['first_name']) ) ? $this->booking_meta['registration']['first_name']:__('Guest User','dbem');
375
+ $this->person->first_name = $this->person->user_firstname;
376
+ $this->person->user_lastname = ( !empty($this->booking_meta['registration']['last_name']) ) ? $this->booking_meta['registration']['last_name']:'';
377
+ $this->person->last_name = $this->person->user_lastname;
378
+ $this->person->phone = ( !empty($this->booking_meta['registration']['dbem_phone']) ) ? $this->booking_meta['registration']['dbem_phone']:__('Not Supplied','dbem');
379
+ //build display name
380
+ $full_name = $this->user_firstname . " " . $this->user_lastname ;
381
+ $full_name = trim($full_name);
382
+ $display_name = ( empty($full_name) ) ? __('Guest User','dbem'):$full_name;
383
+ $this->person->display_name = $display_name;
384
+ }
385
+ return apply_filters('em_booking_get_person', $this->person, $this);
386
  }
387
 
388
  /**
390
  * @return string
391
  */
392
  function get_status(){
393
+ $status = ($this->booking_status == 0 && !get_option('dbem_bookings_approval') ) ? 1:$this->booking_status;
394
+ return $this->status_array[$status];
395
  }
396
+
397
  /**
398
  * I wonder what this does....
399
  * @return boolean
400
  */
401
  function delete(){
402
  global $wpdb;
403
+ $result = false;
404
+ if( $this->can_manage('manage_bookings','manage_others_bookings') ){
405
+ $sql = $wpdb->prepare("DELETE FROM ". EM_BOOKINGS_TABLE . " WHERE booking_id=%d", $this->booking_id);
406
+ $result = $wpdb->query( $sql );
407
+ if( $result !== false ){
408
+ //delete the tickets too
409
+ $this->get_tickets_bookings()->delete();
410
+ $this->previous_status = $this->booking_status;
411
+ $this->booking_status = false;
412
+ $this->feedback_message = sprintf(__('%s deleted', 'dbem'), __('Booking','dbem'));
413
+ }else{
414
+ $this->add_error(sprintf(__('%s could not be deleted', 'dbem'), __('Booking','dbem')));
415
+ }
416
+ }
417
+ return apply_filters('em_booking_delete',( $result !== false ), $this);
418
  }
419
 
420
  function cancel(){
421
+ if( $this->person->ID == get_current_user_id() ){
422
+ $this->manage_override = true; //normally, users can't manage a bookiing, only event owners, so we allow them to mod their booking status in this case only.
423
+ }
424
  return $this->set_status(3);
425
  }
426
 
448
 
449
  /**
450
  * Change the status of the booking. This will save to the Database too.
451
+ * @param int $status
452
+ * @return boolean
453
  */
454
+ function set_status($status){
455
+ global $wpdb;
 
 
456
  $action_string = strtolower($this->status_array[$status]);
457
+ //if we're approving we can't approve a booking if spaces are full, so check before it's approved.
458
+ if($status == 1){
459
+ if( $this->get_event()->get_bookings()->get_available_spaces() < $this->get_spaces() && !get_option('dbem_bookings_approval_overbooking') ){
460
+ $this->feedback_message = sprintf(__('Not approved, spaces full.','dbem'), $action_string);
461
+ return apply_filters('em_booking_set_status', false, $this);
462
+ }
463
+ }
464
+ $this->previous_status = $this->booking_status;
465
+ $this->booking_status = $status;
466
+ $result = $wpdb->query($wpdb->prepare('UPDATE '.EM_BOOKINGS_TABLE.' SET booking_status=%d WHERE booking_id=%d', array($status, $this->booking_id)));
467
+ if($result !== false){
468
  $this->feedback_message = sprintf(__('Booking %s.','dbem'), $action_string);
469
+ if( !($this->booking_status == 0 && $this->previous_status > 0) || $this->previous_status == 4 ){
470
+ if( $this->email() ){
471
+ $this->feedback_message .= " ".__('Mail Sent.','dbem');
472
+ }elseif( $this->previous_status == 0 ){
473
+ //extra errors may be logged by email() in EM_Object
474
+ $this->feedback_message .= ' <span style="color:red">'.__('ERROR : Mail Not Sent.','dbem').'</span>';
475
+ $this->add_error(__('ERROR : Mail Not Sent.','dbem'));
476
+ $result = false;
477
+ }
478
  }
 
479
  }else{
480
  //errors should be logged by save()
481
  $this->feedback_message = sprintf(__('Booking could not be %s.','dbem'), $action_string);
482
+ $this->add_error(sprintf(__('Booking could not be %s.','dbem'), $action_string));
483
  }
484
+ return apply_filters('em_booking_set_status', $result, $this);
485
  }
486
 
487
  /**
495
  $note = array('author'=>get_current_user_id(),'note'=>$note_text,'timestamp'=>current_time('timestamp'));
496
  $this->notes[] = $note;
497
  $this->feedback_message = __('Booking note successfully added.','dbem');
498
+ return $wpdb->insert(EM_META_TABLE, array('object_id'=>$this->booking_id, 'meta_key'=>'booking-note', 'meta_value'=> serialize($note)),array('%d','%s','%s'));
499
  }
500
  return false;
501
  }
507
  */
508
  function email(){
509
  global $EM_Mailer;
510
+ //FIXME ticket logic needed
511
  $EM_Event = $this->get_event(); //We NEED event details here.
512
  //Make sure event matches booking, and that booking used to be approved.
513
+ if( !($this->booking_status == 0 && $this->previous_status > 0) || $this->previous_status == 4 ){
514
+ $contact_id = ( $EM_Event->owner != "") ? $EM_Event->owner : get_option('dbem_default_contact_person');
515
 
516
  $contact_subject = get_option('dbem_bookings_contact_email_subject');
517
  $contact_body = get_option('dbem_bookings_contact_email_body');
518
 
519
+ if( (get_option('dbem_bookings_approval') == 0 && $this->booking_status < 2) || $this->booking_status == 1 ){
520
  $booker_subject = get_option('dbem_bookings_email_confirmed_subject');
521
  $booker_body = get_option('dbem_bookings_email_confirmed_body');
522
+ }elseif( $this->booking_status == 0 || $this->booking_status == 5 || ( $this->booking_status == 0 && ($this->previous_status == 4 || $this->previous_status == 5) ) ){
523
  $booker_subject = get_option('dbem_bookings_email_pending_subject');
524
  $booker_body = get_option('dbem_bookings_email_pending_body');
525
+ }elseif( $this->booking_status == 2 ){
526
  $booker_subject = get_option('dbem_bookings_email_rejected_subject');
527
  $booker_body = get_option('dbem_bookings_email_rejected_body');
528
+ }elseif( $this->booking_status == 3 ){
529
  $booker_subject = get_option('dbem_bookings_email_cancelled_subject');
530
  $booker_body = get_option('dbem_bookings_email_cancelled_body');
531
  $contact_subject = get_option('dbem_contactperson_email_cancelled_subject');
532
  $contact_body = get_option('dbem_contactperson_email_cancelled_body');
533
+ }else{
534
+ return true;
535
  }
536
 
537
  // email specific placeholders
538
+ foreach( $this->get_tickets() as $EM_Ticket){ break; }
539
+ ob_start();
540
+ em_locate_template('emails/bookingtickets.php', true, array('EM_Booking'=>$this));
541
+ $tickets = ob_get_clean();
542
+ $placeholders = apply_filters('em_booking_email_placeholders', array(
543
  '#_RESPNAME' => '#_BOOKINGNAME',//Depreciated
544
  '#_RESPEMAIL' => '#_BOOKINGEMAIL',//Depreciated
545
  '#_RESPPHONE' => '#_BOOKINGPHONE',//Depreciated
546
  '#_COMMENT' => '#_BOOKINGCOMMENT',//Depreciated
547
  '#_RESERVEDSPACES' => '#_BOOKEDSPACES',//Depreciated
548
+ '#_BOOKINGID' => $this->booking_id,
549
+ '#_BOOKINGNAME' => $this->person->get_name(),
550
+ '#_BOOKINGEMAIL' => $this->person->user_email,
551
  '#_BOOKINGPHONE' => $this->person->phone,
552
+ '#_BOOKINGSPACES' => $this->get_spaces(),
553
+ '#_BOOKINGLISTURL' => em_get_my_bookings_url(),
554
+ '#_BOOKINGCOMMENT' => $this->booking_comment,
555
+ '#_BOOKINGPRICEWITHTAX' => em_get_currency_symbol(true)." ". number_format($this->get_price(false,false,true),2),
556
+ '#_BOOKINGPRICEWITHOUTTAX' => em_get_currency_symbol(true)." ". number_format($this->get_price(false,false,false),2),
557
+ '#_BOOKINGPRICETAX' => em_get_currency_symbol(true)." ". number_format($this->get_price(false,false,false)*(get_option('dbem_bookings_tax')/100),2),
558
+ '#_BOOKINGPRICE' => em_get_currency_symbol(true)." ". number_format($this->get_price(),2),
559
+ '#_BOOKINGTICKETNAME' => $EM_Ticket->name,
560
+ '#_BOOKINGTICKETDESCRIPTION' => $EM_Ticket->description,
561
+ '#_BOOKINGTICKETPRICEWITHTAX' => em_get_currency_symbol(true)." ". number_format($EM_Ticket->get_price(false,true),2),
562
+ '#_BOOKINGTICKETPRICEWITHOUTTAX' => em_get_currency_symbol(true)." ". number_format($EM_Ticket->get_price(false,false),2),
563
+ '#_BOOKINGTICKETTAX' => em_get_currency_symbol(true)." ". number_format($EM_Ticket->get_price(false,false)*(get_option('dbem_bookings_tax')/100),2),
564
+ '#_BOOKINGTICKETPRICE' => em_get_currency_symbol(true)." ". number_format($EM_Ticket->get_price(),2),
565
+ '#_BOOKINGTICKETS' => $tickets
566
+ ),$this);
567
  foreach($placeholders as $key => $value) {
568
  $contact_subject = str_replace($key, $value, $contact_subject);
569
  $contact_body = str_replace($key, $value, $contact_body);
570
  $booker_subject = str_replace($key, $value, $booker_subject);
571
  $booker_body = str_replace($key, $value, $booker_body);
572
  }
 
573
  $booker_subject = $EM_Event->output($booker_subject, 'email');
574
  $booker_body = $EM_Event->output($booker_body, 'email');
575
+
576
  //Send to the person booking
577
+ if( !$this->email_send( $booker_subject,$booker_body, $this->person->user_email) ){
578
  return false;
579
  }
580
 
581
+ //Send admin/contact emails
582
+ if( (get_option('dbem_bookings_approval') == 0 || in_array($this->booking_status, array(0,3,4,5)) || (in_array($this->previous_status, array(4)) && $this->booking_status == 1)) && (get_option('dbem_bookings_contact_email') == 1 || get_option('dbem_bookings_notify_admin') != '') ){
583
  //Only gets sent if this is a pending booking, unless approvals are disabled.
584
  $contact_subject = $EM_Event->output($contact_subject, 'email');
585
  $contact_body = $EM_Event->output($contact_body, 'email');
586
 
587
  if( get_option('dbem_bookings_contact_email') == 1 ){
588
+ if( !$this->email_send( $contact_subject, $contact_body, $EM_Event->get_contact()->user_email) && current_user_can('activate_plugins')){
589
  $this->errors[] = __('Confirmation email could not be sent to contact person. Registrant should have gotten their email (only admin see this warning).','dbem');
590
  return false;
591
  }
608
  * Can the user manage this event?
609
  */
610
  function can_manage(){
611
+ return $this->get_event()->can_manage('manage_bookings','manage_others_bookings') || empty($this->booking_id) || !empty($this->manage_override);
612
  }
613
 
614
  /**
classes/em-bookings.php CHANGED
@@ -4,7 +4,7 @@
4
  * @author marcus
5
  *
6
  */
7
- class EM_Bookings extends EM_Object{
8
 
9
  /**
10
  * Array of EM_Booking objects for a specific event
@@ -12,83 +12,71 @@ class EM_Bookings extends EM_Object{
12
  */
13
  var $bookings = array();
14
  /**
15
- * Event ID
 
 
 
16
  * @var int
17
  */
18
  var $event_id;
19
  /**
20
- * Number of seats for this event
21
  * @var int
22
  */
23
- var $seats;
24
-
25
- var $feedback_message = "";
26
- var $errors = array();
27
 
28
  /**
29
- * Creates an EM_Bookings instance,
30
  * @param EM_Event $event
31
  * @return null
32
  */
33
- function EM_Bookings( $event = false ){
34
- if( is_object($event) && get_class($event) == "EM_Event" ){ //Creates a blank bookings object if needed
35
  global $wpdb;
36
- $this->event_id = $event->id;
37
- $this->seats = $event->seats;
38
- $sql = "SELECT * FROM ". $wpdb->prefix . EM_BOOKINGS_TABLE ." b, ". $wpdb->prefix . EM_PEOPLE_TABLE ." p WHERE event_id ='{$this->event_id}' AND p.person_id=b.person_id";
39
  $bookings = $wpdb->get_results($sql, ARRAY_A);
40
  foreach ($bookings as $booking){
41
  $this->bookings[] = new EM_Booking($booking);
42
  }
 
 
 
 
 
 
 
43
  }
44
  }
45
 
46
  /**
47
- * Add a booking into this event (or add seats if person already booked this), checking that there's enough space for the event
48
- * @param $EM_Booking
49
  * @return boolean
50
  */
51
  function add( $EM_Booking ){
52
  global $wpdb,$EM_Mailer;
53
- if ( $this->get_available_seats() >= $EM_Booking->seats ) {
54
- $EM_Booking->event_id = $this->event_id;
55
- // checking whether the booker has already booked places
56
- $previous_booking = $this->find_previous_booking( $EM_Booking );
57
  $email = false;
58
- if ( is_object($previous_booking) ) {
59
- //Previously booked, so we add these seats to the booking
60
- $new_seats = $EM_Booking->seats;
61
- $EM_Booking = $previous_booking;
62
- $EM_Booking->seats += $new_seats;
63
- $result = $EM_Booking->save();
64
- if($result){
65
- //remove old booking
66
- foreach($this->bookings as $key=>$booking){
67
- if($booking->id == $EM_Booking->id){ unset($this->bookings[$key]); }
68
- }
69
- $this->bookings[] = $EM_Booking;
70
- $email = $EM_Booking->email();
71
- }
72
- } else {
73
- //New booking, so let's save the booking
74
- $result = $EM_Booking->save();
75
- if($result){
76
- $this->bookings[] = $EM_Booking;
77
- $email = $EM_Booking->email();
78
- }
79
  }
 
80
  if($result){
81
  //Success
82
- if( get_option('dbem_bookings_approval') == 1 ){
83
- $this->feedback_message = __('Booking successful, pending confirmation (you will also receive an email once confirmed).', 'dbem');
 
 
84
  }else{
85
- $this->feedback_message = __('Booking successful.', 'dbem');
86
  }
87
  if(!$email){
88
- $this->feedback_message .= ' '.__('However, there were some problems whilst sending confirmation emails to you and/or the event contact person. You may want to contact them directly and letting them know of this error.', 'dbem');
89
  if( current_user_can('activate_plugins') ){
90
- if( is_array($this->errors) && count($this->errors) > 0 ){
91
- $this->feedback_message .= '<br/><strong>Errors:</strong> (only admins see this message)<br/><ul><li>'. implode('</li><li>', $EM_Mailer->errors).'</li></ul>';
92
  }else{
93
  $this->feedback_message .= '<br/><strong>No errors returned by mailer</strong> (only admins see this message)';
94
  }
@@ -97,12 +85,107 @@ class EM_Bookings extends EM_Object{
97
  return true;
98
  }else{
99
  //Failure
100
- $this->errors[] = "<strong>".__('Booking could not be created','dbem').":</strong><br />". implode('<br />', $EM_Booking->errors);
101
  }
102
  } else {
103
- $this->errors[] = __('Booking cannot be made, not enough seats available!', 'dbem');
104
- return false;
105
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
106
  }
107
 
108
  /**
@@ -111,8 +194,19 @@ class EM_Bookings extends EM_Object{
111
  */
112
  function delete(){
113
  global $wpdb;
114
- $result = $wpdb->query("DELETE FROM ".$wpdb->prefix.EM_BOOKINGS_TABLE." WHERE event_id='{$this->event_id}'");
115
- return ($result);
 
 
 
 
 
 
 
 
 
 
 
116
  }
117
 
118
 
@@ -150,13 +244,18 @@ class EM_Bookings extends EM_Object{
150
  * @return bool
151
  */
152
  function set_status($status, $booking_ids){
 
153
  //FIXME there is a vulnerability where any user can approve/reject bookings if they know the ID
154
- if( EM_Object::array_is_numeric($booking_ids) ){
155
  //Get all the bookings
156
  $results = array();
157
  $mails = array();
158
  foreach( $booking_ids as $booking_id ){
159
  $EM_Booking = new EM_Booking($booking_id);
 
 
 
 
160
  $results[] = $EM_Booking->set_status($status);
161
  }
162
  if( !in_array('false',$results) ){
@@ -176,67 +275,81 @@ class EM_Bookings extends EM_Object{
176
  return false;
177
  }
178
 
 
179
  /**
180
- * Returns number of available seats for this event. If approval of bookings is on, will include pending bookings depending on em option.
 
181
  * @return int
182
  */
183
- function get_available_seats(){
184
- $booked_seats = 0;
185
- if( get_option('dbem_bookings_approval_reserved') == 1 ){
186
- return $this->seats - $this->get_booked_seats() - $this->get_pending_seats();
187
- }else{
188
- return $this->seats - $this->get_booked_seats();
189
  }
 
 
 
 
 
 
 
 
 
 
190
  }
191
 
192
  /**
193
- * Returns number of booked seats for this event. If approval of bookings is on, will return number of booked confirmed seats.
194
  * @return int
195
  */
196
- function get_booked_seats(){
197
- $booked_seats = 0;
198
- foreach ( $this->bookings as $booking ){
199
- if( $booking->status != 3 && (get_option('dbem_bookings_approval') == 0 || $booking->status == 1) ){
200
- $booked_seats += $booking->seats;
 
 
 
 
201
  }
202
  }
203
- return $booked_seats;
204
  }
205
 
206
  /**
207
- * Gets number of pending seats awaiting approval. Will return 0 if booking approval is not enabled.
208
  * @return int
209
  */
210
- function get_pending_seats(){
211
  if( get_option('dbem_bookings_approval') == 0 ){
212
  return 0;
213
  }
214
  $pending = 0;
215
  foreach ( $this->bookings as $booking ){
216
- if($booking->status == 0){
217
- $pending += $booking->seats;
218
  }
219
  }
220
- return $pending;
221
  }
222
 
223
  /**
224
- * Gets number of bookings (not seats). If booking approval is enabled, only the number of approved bookings will be shown.
225
- * @return array EM_Booking
226
  */
227
- function get_bookings(){
228
  $confirmed = array();
229
  foreach ( $this->bookings as $booking ){
230
- if( $booking->status == 1 || (get_option('dbem_bookings_approval') == 0 && $booking->status < 2) ){
231
  $confirmed[] = $booking;
232
  }
233
  }
234
- return $confirmed;
 
235
  }
236
 
237
  /**
238
  * Get pending bookings. If booking approval is disabled, will return no bookings.
239
- * @return array EM_Booking
240
  */
241
  function get_pending_bookings(){
242
  if( get_option('dbem_bookings_approval') == 0 ){
@@ -244,25 +357,27 @@ class EM_Bookings extends EM_Object{
244
  }
245
  $pending = array();
246
  foreach ( $this->bookings as $booking ){
247
- if($booking->status == 0){
248
  $pending[] = $booking;
249
  }
250
  }
251
- return $pending;
 
252
  }
253
 
254
  /**
255
- * Get rejected bookings.
256
- * @return array EM_Booking
257
  */
258
  function get_rejected_bookings(){
259
- $pending = array();
260
  foreach ( $this->bookings as $booking ){
261
- if($booking->status == 2){
262
- $pending[] = $booking;
263
  }
264
  }
265
- return $pending;
 
266
  }
267
 
268
  /**
@@ -270,13 +385,14 @@ class EM_Bookings extends EM_Object{
270
  * @return array EM_Booking
271
  */
272
  function get_cancelled_bookings(){
273
- $pending = array();
274
  foreach ( $this->bookings as $booking ){
275
- if($booking->status == 3){
276
- $pending[] = $booking;
277
  }
278
  }
279
- return $pending;
 
280
  }
281
 
282
  /**
@@ -288,10 +404,10 @@ class EM_Bookings extends EM_Object{
288
  //First see if we have a similar person on record that's making this booking
289
  $EM_Booking->person->load_similar();
290
  //If person exists on record, see if they've booked this event before, if so return the booking.
291
- if( is_numeric($EM_Booking->person->id) && $EM_Booking->person->id > 0 ){
292
- $EM_Booking->person_id = $EM_Booking->person->id;
293
  foreach ($this->bookings as $booking){
294
- if( $booking->person_id == $EM_Booking->person->id ){
295
  return $booking;
296
  }
297
  }
@@ -299,30 +415,34 @@ class EM_Bookings extends EM_Object{
299
  return false;
300
  }
301
 
302
-
303
  /**
304
- * Get all pending bookings for this event
 
305
  */
306
- function get_pending(){
307
- $pending = array();
308
- foreach($this->bookings as $booking){
309
- if($booking->status == 0){
310
- $pending[] = $booking;
311
- }
 
 
 
 
312
  }
313
- return $pending;
314
  }
315
 
316
  /**
317
- * Gets the pending number of bookings as a raw associative array.
318
  * @return array
 
319
  */
320
  function get( $args = array() ){
321
  global $wpdb,$current_user;
322
- $bookings_table = $wpdb->prefix . EM_BOOKINGS_TABLE;
323
- $events_table = $wpdb->prefix . EM_EVENTS_TABLE;
324
- $people_table = $wpdb->prefix . EM_PEOPLE_TABLE;
325
- $locations_table = $wpdb->prefix . EM_LOCATIONS_TABLE;
326
 
327
  //Quick version, we can accept an array of IDs, which is easy to retrieve
328
  if( self::array_is_numeric($args) ){ //Array of numbers, assume they are event IDs to retreive
@@ -330,14 +450,13 @@ class EM_Bookings extends EM_Object{
330
  $sql = "
331
  SELECT * FROM $bookings_table b
332
  LEFT JOIN $events_table e ON e.event_id=b.event_id
333
- LEFT JOIN $people_table p ON p.person_id=b.person_id
334
  WHERE booking_id".implode(" OR booking_id=", $args);
335
  $results = $wpdb->get_results(apply_filters('em_bookings_get_sql',$sql),ARRAY_A);
336
  $bookings = array();
337
  foreach($results as $result){
338
- $bookings[$result['event_id']] = new EM_Event($result);
339
  }
340
- return $bookings; //We return all the events matched as an EM_Event array.
341
  }
342
 
343
  //We assume it's either an empty array or array of search arguments to merge with defaults
@@ -361,13 +480,11 @@ class EM_Bookings extends EM_Object{
361
  $sql = "
362
  SELECT * FROM $bookings_table
363
  LEFT JOIN $events_table ON {$events_table}.event_id={$bookings_table}.event_id
364
- LEFT JOIN $people_table ON {$people_table}.person_id={$bookings_table}.person_id
365
  LEFT JOIN $locations_table ON {$locations_table}.location_id={$events_table}.location_id
366
  $where
367
  $orderby_sql
368
  $limit $offset
369
  ";
370
-
371
  $results = $wpdb->get_results( apply_filters('em_events_get_sql',$sql, $args), ARRAY_A);
372
 
373
  //If we want results directly in an array, why not have a shortcut here?
@@ -381,16 +498,16 @@ class EM_Bookings extends EM_Object{
381
  foreach ( $results as $booking ){
382
  $bookings[] = new EM_Booking($booking);
383
  }
384
-
385
- return apply_filters('em_bookings_get', $bookings);
386
  }
387
 
388
 
389
  //List of patients in the patient database, that a user can choose and go on to edit any previous treatment data, or add a new admission.
390
  function export_csv() {
391
  global $EM_Event;
392
- if($EM_Event->id != $this->event_id ){
393
- $event = new EM_Event($this->event_id);
394
  $event_name = $event->name;
395
  }else{
396
  $event_name = $EM_Event->name;
@@ -400,45 +517,8 @@ class EM_Bookings extends EM_Object{
400
 
401
  header("Content-Type: application/octet-stream");
402
  header("Content-Disposition: Attachment; filename=$file_name");
403
-
404
- //Headers
405
- $labels = array(
406
- 'ID',
407
- 'Name',
408
- 'Email',
409
- 'Phone',
410
- 'Date',
411
- 'Status',
412
- 'Spaces',
413
- 'Comment'
414
- );
415
- $file = sprintf(__('Booking details for "%s" as of %s','dbem'),$event_name, date_i18n('D d M Y h:i', current_time('timestamp'))) . "\n";
416
- $file = '"'. strtolower(implode('","', $labels)). '"' . "\n";
417
-
418
- //Rows
419
- foreach( $this->bookings as $EM_Booking ) {
420
- $row = array(
421
- $EM_Booking->id,
422
- $EM_Booking->person->name,
423
- $EM_Booking->person->email,
424
- $EM_Booking->person->phone,
425
- date('Y-m-d h:i', $EM_Booking->timestamp),
426
- $EM_Booking->seats,
427
- $EM_Booking->get_status(),
428
- $EM_Booking->comment
429
- );
430
- //Display all values
431
- foreach($row as $value){
432
- $value = str_replace('"', '""', $value);
433
- $value = str_replace("=", "", $value);
434
- $file .= '"' . preg_replace("/\n\r|\r\n|\n|\r/", ". ", $value) . '",';
435
- }
436
- $file .= "\n";
437
- }
438
-
439
- // $file holds the data
440
- echo $file;
441
- $file = "";
442
  }
443
 
444
  /* Overrides EM_Object method to apply a filter to result
@@ -472,17 +552,35 @@ class EM_Bookings extends EM_Object{
472
  );
473
  if( true || is_admin() ){
474
  //figure out default owning permissions
475
- switch( get_option('dbem_permissions_events') ){
476
- case 0:
477
- $defaults['owner'] = get_current_user_id();
478
- break;
479
- case 1:
480
- $defaults['owner'] = false;
481
- break;
482
  }
483
- $defaults['owner'] = ( em_verify_admin() ) ? false:$defaults['owner'];
484
  }
485
  return apply_filters('em_bookings_get_default_search', parent::get_default_search($defaults,$array), $array, $defaults);
486
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
487
  }
488
  ?>
4
  * @author marcus
5
  *
6
  */
7
+ class EM_Bookings extends EM_Object implements Iterator{
8
 
9
  /**
10
  * Array of EM_Booking objects for a specific event
12
  */
13
  var $bookings = array();
14
  /**
15
+ * @var EM_Tickets
16
+ */
17
+ var $tickets;
18
+ /**
19
  * @var int
20
  */
21
  var $event_id;
22
  /**
23
+ * How many spaces this event has
24
  * @var int
25
  */
26
+ var $spaces;
 
 
 
27
 
28
  /**
29
+ * Creates an EM_Bookings instance, currently accepts an EM_Event object (gets all bookings for that event) or array of any EM_Booking objects, which can be manipulated in bulk with helper functions.
30
  * @param EM_Event $event
31
  * @return null
32
  */
33
+ function EM_Bookings( $data = false ){
34
+ if( is_object($data) && get_class($data) == "EM_Event" ){ //Creates a blank bookings object if needed
35
  global $wpdb;
36
+ $this->event_id = $data->event_id;
37
+ $sql = "SELECT * FROM ". EM_BOOKINGS_TABLE ." WHERE event_id ='{$this->event_id}'";
 
38
  $bookings = $wpdb->get_results($sql, ARRAY_A);
39
  foreach ($bookings as $booking){
40
  $this->bookings[] = new EM_Booking($booking);
41
  }
42
+ $this->spaces = $this->get_spaces();
43
+ }elseif( is_array($data) ){
44
+ foreach( $data as $EM_Booking ){
45
+ if( get_class($EM_Booking) == 'EM_Booking'){
46
+ $this->bookings[] = $EM_Booking;
47
+ }
48
+ }
49
  }
50
  }
51
 
52
  /**
53
+ * Add a booking into this event (or add spaces if person already booked this), checking that there's enough space for the event
54
+ * @param EM_Booking $EM_Booking
55
  * @return boolean
56
  */
57
  function add( $EM_Booking ){
58
  global $wpdb,$EM_Mailer;
59
+ if ( $this->get_available_spaces() >= $EM_Booking->get_spaces(true) ) {
60
+ //Save the booking
 
 
61
  $email = false;
62
+ if( !get_option('dbem_bookings_approval') && $EM_Booking->booking_status < 2 ){
63
+ $EM_Booking->booking_status = 1;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
64
  }
65
+ $result = $EM_Booking->save(false);
66
  if($result){
67
  //Success
68
+ $this->bookings[] = $EM_Booking;
69
+ $email = $EM_Booking->email();
70
+ if( get_option('dbem_bookings_approval') == 1 && $EM_Booking->booking_status == 0){
71
+ $this->feedback_message = get_option('dbem_booking_feedback_pending');
72
  }else{
73
+ $this->feedback_message = get_option('dbem_booking_feedback');
74
  }
75
  if(!$email){
76
+ $this->feedback_message .= ' '.get_option('dbem_booking_feedback_nomail');
77
  if( current_user_can('activate_plugins') ){
78
+ if( count($EM_Booking->get_errors()) > 0 ){
79
+ $this->feedback_message .= '<br/><strong>Errors:</strong> (only admins see this message)<br/><ul><li>'. implode('</li><li>', $EM_Booking->get_errors()).'</li></ul>';
80
  }else{
81
  $this->feedback_message .= '<br/><strong>No errors returned by mailer</strong> (only admins see this message)';
82
  }
85
  return true;
86
  }else{
87
  //Failure
88
+ $this->errors[] = "<strong>".get_option('dbem_booking_feedback_error')."</strong><br />". implode('<br />', $EM_Booking->errors);
89
  }
90
  } else {
91
+ $this->add_error(get_option('dbem_booking_feedback_full'));
 
92
  }
93
+ return apply_filters('em_bookings_add', false, $EM_Booking);
94
+ }
95
+
96
+ /**
97
+ * Get POST data and create a booking for each ticket requested. If successful, a booking object is returned, false if not.
98
+ * @return false|object
99
+ */
100
+ function add_from_post(){
101
+ $EM_Booking = new EM_booking();
102
+ $result = $EM_Booking->get_post();
103
+ if($result){
104
+ $result = $this->add($EM_Booking);
105
+ if($result){
106
+ $result = $EM_Booking;
107
+ }
108
+ $this->feedback_message = sprintf(__('%s created.','dbem'),__('Booking','dbem'));
109
+ }else{
110
+ $this->errors = array_merge($this->errors, $EM_Booking->errors);
111
+ }
112
+ return apply_filters('em_bookings_add_from_post',$result,$EM_Booking,$this);
113
+ }
114
+
115
+ /**
116
+ * Smart event locator, saves a database read if possible. Note that if an event doesn't exist, a blank object will be created to prevent duplicates.
117
+ */
118
+ function get_event(){
119
+ global $EM_Event;
120
+ if( is_object($EM_Event) && $EM_Event->id == $this->event_id ){
121
+ return $EM_Event;
122
+ }else{
123
+ if( is_numeric($this->event_id) && $this->event_id > 0 ){
124
+ return new EM_Event($this->event_id, 'event_id');
125
+ }elseif( count($this->bookings) > 0 ){
126
+ foreach($this->bookings as $EM_Booking){
127
+ /* @var $EM_Booking EM_Booking */
128
+ return new EM_Event($EM_Booking->event_id, 'event_id');
129
+ }
130
+ }
131
+ }
132
+ return new EM_Event($this->event_id);
133
+ }
134
+
135
+ /**
136
+ * Retrieve and save the bookings belonging to instance. If called again will return cached version, set $force_reload to true to create a new EM_Tickets object.
137
+ * @param boolean $force_reload
138
+ * @return EM_Tickets
139
+ */
140
+ function get_tickets( $force_reload = false ){
141
+ if( !is_object($this->tickets) || $force_reload ){
142
+ $this->tickets = new EM_Tickets($this->event_id);
143
+ }else{
144
+ $this->tickets->event_id = $this->event_id;
145
+ }
146
+ return apply_filters('em_bookings_get_tickets', $this->tickets, $this);
147
+ }
148
+
149
+ /**
150
+ * Returns EM_Tickets object with available tickets
151
+ * @return EM_Tickets
152
+ */
153
+ function get_available_tickets(){
154
+ $tickets = array();
155
+ $timesamp = current_time('timestamp');
156
+ foreach ($this->get_tickets() as $EM_Ticket){
157
+ /* @var EM_Ticket $EM_Ticket */
158
+ if( $EM_Ticket->is_available() ){
159
+ //within time range
160
+ if( $EM_Ticket->get_available_spaces() > 0 ){
161
+ $tickets[] = $EM_Ticket;
162
+ }
163
+ }
164
+ }
165
+ $EM_Tickets = new EM_Tickets($tickets);
166
+ return apply_filters('em_bookings_get_tickets', $EM_Tickets, $this);
167
+ }
168
+
169
+ function get_user_list(){
170
+ $users = array();
171
+ foreach( $this->get_bookings()->bookings as $EM_Booking ){
172
+ $users[$EM_Booking->person->ID] = $EM_Booking->person;
173
+ }
174
+ return $users;
175
+ }
176
+
177
+ /**
178
+ * does this ticket exist?
179
+ * @return bool
180
+ */
181
+ function ticket_exists($ticket_id){
182
+ $EM_Tickets = $this->get_tickets();
183
+ foreach( $EM_Tickets->tickets as $EM_Ticket){
184
+ if($EM_Ticket->id == $ticket_id){
185
+ return apply_filters('em_bookings_ticket_exists',true, $EM_Ticket, $this);
186
+ }
187
+ }
188
+ return apply_filters('em_bookings_ticket_exists',false, false,$this);
189
  }
190
 
191
  /**
194
  */
195
  function delete(){
196
  global $wpdb;
197
+ $booking_ids = array();
198
+ //get the booking ids tied to this event
199
+ foreach( $this->bookings as $EM_Booking ){
200
+ $booking_ids[] = $EM_Booking->booking_id;
201
+ }
202
+ $result_tickets = true;
203
+ $result = true;
204
+ if( count($booking_ids) > 0 ){
205
+ //Delete bookings and ticket bookings
206
+ $result_tickets = $wpdb->query("DELETE FROM ". EM_TICKETS_BOOKINGS_TABLE ." WHERE booking_id IN (".implode(',',$booking_ids).");");
207
+ $result = $wpdb->query("DELETE FROM ".EM_BOOKINGS_TABLE." WHERE event_id IN (".implode(',',$booking_ids).")");
208
+ }
209
+ return ($result !== false && $result_tickets !== false);
210
  }
211
 
212
 
244
  * @return bool
245
  */
246
  function set_status($status, $booking_ids){
247
+ //FIXME status should work with instantiated object
248
  //FIXME there is a vulnerability where any user can approve/reject bookings if they know the ID
249
+ if( $this->array_is_numeric($booking_ids) ){
250
  //Get all the bookings
251
  $results = array();
252
  $mails = array();
253
  foreach( $booking_ids as $booking_id ){
254
  $EM_Booking = new EM_Booking($booking_id);
255
+ if( !$EM_Booking->can_manage() ){
256
+ $this->feedback_message = __('Bookings %s. Mails Sent.', 'dbem');
257
+ return false;
258
+ }
259
  $results[] = $EM_Booking->set_status($status);
260
  }
261
  if( !in_array('false',$results) ){
275
  return false;
276
  }
277
 
278
+
279
  /**
280
+ * Get the total number of spaces this event has. This will show the lower value of event global spaces limit or total ticket spaces. Setting $force_refresh to true will recheck spaces, even if previously done so.
281
+ * @param boolean $force_refresh
282
  * @return int
283
  */
284
+ function get_spaces( $force_refresh=false ){
285
+ if($force_refresh || $this->spaces == 0){
286
+ $this->spaces = $this->get_tickets()->get_spaces();
 
 
 
287
  }
288
+ return apply_filters('em_booking_get_spaces',$this->spaces,$this);
289
+ }
290
+
291
+ /**
292
+ * Returns number of available spaces for this event. If approval of bookings is on, will include pending bookings depending on em option.
293
+ * @return int
294
+ */
295
+ function get_available_spaces(){
296
+ $available_spaces = $this->get_spaces() - $this->get_booked_spaces();
297
+ return apply_filters('em_booking_get_available_spaces', $available_spaces, $this);
298
  }
299
 
300
  /**
301
+ * Returns number of booked spaces for this event. If approval of bookings is on, will return number of booked confirmed spaces.
302
  * @return int
303
  */
304
+ function get_booked_spaces($force_refresh = false){
305
+ $booked_spaces = 0;
306
+ $EM_Bookings = $this->get_bookings(true);
307
+ $reserved_pending = get_option('dbem_bookings_approval_reserved');
308
+ $auto_approval = get_option('dbem_bookings_approval');
309
+ foreach ( $EM_Bookings->bookings as $EM_Booking ){
310
+ //never show cancelled status, nor pending if approvals required
311
+ if( $EM_Booking->booking_status == 1 || ((!$auto_approval || $reserved_pending) && $EM_Booking->booking_status == 0) ){
312
+ $booked_spaces += $EM_Booking->get_spaces($force_refresh);
313
  }
314
  }
315
+ return $booked_spaces;
316
  }
317
 
318
  /**
319
+ * Gets number of pending spaces awaiting approval. Will return 0 if booking approval is not enabled.
320
  * @return int
321
  */
322
+ function get_pending_spaces(){
323
  if( get_option('dbem_bookings_approval') == 0 ){
324
  return 0;
325
  }
326
  $pending = 0;
327
  foreach ( $this->bookings as $booking ){
328
+ if($booking->booking_status == 0){
329
+ $pending += $booking->get_spaces();
330
  }
331
  }
332
+ return apply_filters('em_bookings_get_pending_spaces', $pending, $this);
333
  }
334
 
335
  /**
336
+ * Gets number of bookings (not spaces). If booking approval is enabled, only the number of approved bookings will be shown.
337
+ * @return EM_Bookings
338
  */
339
+ function get_bookings( $all_bookings = false ){
340
  $confirmed = array();
341
  foreach ( $this->bookings as $booking ){
342
+ if( $booking->booking_status == 1 || (get_option('dbem_bookings_approval') == 0 && $booking->booking_status == 0) || $all_bookings ){
343
  $confirmed[] = $booking;
344
  }
345
  }
346
+ $EM_Bookings = new EM_Bookings($confirmed);
347
+ return $EM_Bookings;
348
  }
349
 
350
  /**
351
  * Get pending bookings. If booking approval is disabled, will return no bookings.
352
+ * @return EM_Bookings
353
  */
354
  function get_pending_bookings(){
355
  if( get_option('dbem_bookings_approval') == 0 ){
357
  }
358
  $pending = array();
359
  foreach ( $this->bookings as $booking ){
360
+ if($booking->booking_status == 0){
361
  $pending[] = $booking;
362
  }
363
  }
364
+ $EM_Bookings = new EM_Bookings($pending);
365
+ return $EM_Bookings;
366
  }
367
 
368
  /**
369
+ * Get rejected bookings. If booking approval is disabled, will return no bookings.
370
+ * @return array EM_Bookings
371
  */
372
  function get_rejected_bookings(){
373
+ $rejected = array();
374
  foreach ( $this->bookings as $booking ){
375
+ if($booking->booking_status == 2){
376
+ $rejected[] = $booking;
377
  }
378
  }
379
+ $EM_Bookings = new EM_Bookings($rejected);
380
+ return $EM_Bookings;
381
  }
382
 
383
  /**
385
  * @return array EM_Booking
386
  */
387
  function get_cancelled_bookings(){
388
+ $cancelled = array();
389
  foreach ( $this->bookings as $booking ){
390
+ if($booking->booking_status == 3){
391
+ $cancelled[] = $booking;
392
  }
393
  }
394
+ $EM_Bookings = new EM_Bookings($cancelled);
395
+ return $EM_Bookings;
396
  }
397
 
398
  /**
404
  //First see if we have a similar person on record that's making this booking
405
  $EM_Booking->person->load_similar();
406
  //If person exists on record, see if they've booked this event before, if so return the booking.
407
+ if( is_numeric($EM_Booking->person->ID) && $EM_Booking->person->ID > 0 ){
408
+ $EM_Booking->person_id = $EM_Booking->person->ID;
409
  foreach ($this->bookings as $booking){
410
+ if( $booking->person_id == $EM_Booking->person->ID ){
411
  return $booking;
412
  }
413
  }
415
  return false;
416
  }
417
 
 
418
  /**
419
+ * Checks to see if user has a booking for this event
420
+ * @param unknown_type $user_id
421
  */
422
+ function has_booking( $user_id = false ){
423
+ if( $user_id === false ){
424
+ $user_id = get_current_user_id();
425
+ }
426
+ if( is_numeric($user_id) && $user_id > 0 ){
427
+ foreach ($this->bookings as $EM_Booking){
428
+ if( $EM_Booking->person->ID == $user_id && $EM_Booking->booking_status != 3 ){
429
+ return apply_filters('em_bookings_has_booking', $EM_Booking, $this);
430
+ }
431
+ }
432
  }
433
+ return apply_filters('em_bookings_has_booking', false, $this);
434
  }
435
 
436
  /**
437
+ * Get bookings that match the array of arguments passed.
438
  * @return array
439
+ * @static
440
  */
441
  function get( $args = array() ){
442
  global $wpdb,$current_user;
443
+ $bookings_table = EM_BOOKINGS_TABLE;
444
+ $events_table = EM_EVENTS_TABLE;
445
+ $locations_table = EM_LOCATIONS_TABLE;
 
446
 
447
  //Quick version, we can accept an array of IDs, which is easy to retrieve
448
  if( self::array_is_numeric($args) ){ //Array of numbers, assume they are event IDs to retreive
450
  $sql = "
451
  SELECT * FROM $bookings_table b
452
  LEFT JOIN $events_table e ON e.event_id=b.event_id
 
453
  WHERE booking_id".implode(" OR booking_id=", $args);
454
  $results = $wpdb->get_results(apply_filters('em_bookings_get_sql',$sql),ARRAY_A);
455
  $bookings = array();
456
  foreach($results as $result){
457
+ $bookings[] = new EM_Booking($result);
458
  }
459
+ return $bookings; //We return all the bookings matched as an EM_Booking array.
460
  }
461
 
462
  //We assume it's either an empty array or array of search arguments to merge with defaults
480
  $sql = "
481
  SELECT * FROM $bookings_table
482
  LEFT JOIN $events_table ON {$events_table}.event_id={$bookings_table}.event_id
 
483
  LEFT JOIN $locations_table ON {$locations_table}.location_id={$events_table}.location_id
484
  $where
485
  $orderby_sql
486
  $limit $offset
487
  ";
 
488
  $results = $wpdb->get_results( apply_filters('em_events_get_sql',$sql, $args), ARRAY_A);
489
 
490
  //If we want results directly in an array, why not have a shortcut here?
498
  foreach ( $results as $booking ){
499
  $bookings[] = new EM_Booking($booking);
500
  }
501
+ $EM_Bookings = new EM_Bookings($bookings);
502
+ return apply_filters('em_bookings_get', $EM_Bookings);
503
  }
504
 
505
 
506
  //List of patients in the patient database, that a user can choose and go on to edit any previous treatment data, or add a new admission.
507
  function export_csv() {
508
  global $EM_Event;
509
+ if($EM_Event->event_id != $this->event_id ){
510
+ $event = $this->get_event();
511
  $event_name = $event->name;
512
  }else{
513
  $event_name = $EM_Event->name;
517
 
518
  header("Content-Type: application/octet-stream");
519
  header("Content-Disposition: Attachment; filename=$file_name");
520
+ em_locate_template('templates/csv-event-bookings.php', true);
521
+ exit();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
522
  }
523
 
524
  /* Overrides EM_Object method to apply a filter to result
552
  );
553
  if( true || is_admin() ){
554
  //figure out default owning permissions
555
+ if( !current_user_can('edit_others_events') ){
556
+ $defaults['owner'] = get_current_user_id();
557
+ }else{
558
+ $defaults['owner'] = false;
 
 
 
559
  }
 
560
  }
561
  return apply_filters('em_bookings_get_default_search', parent::get_default_search($defaults,$array), $array, $defaults);
562
  }
563
+
564
+ //Iterator Implementation
565
+ public function rewind(){
566
+ reset($this->bookings);
567
+ }
568
+ public function current(){
569
+ $var = current($this->bookings);
570
+ return $var;
571
+ }
572
+ public function key(){
573
+ $var = key($this->bookings);
574
+ return $var;
575
+ }
576
+ public function next(){
577
+ $var = next($this->bookings);
578
+ return $var;
579
+ }
580
+ public function valid(){
581
+ $key = key($this->bookings);
582
+ $var = ($key !== NULL && $key !== FALSE);
583
+ return $var;
584
+ }
585
  }
586
  ?>
classes/em-calendar.php CHANGED
@@ -2,12 +2,16 @@
2
  class EM_Calendar extends EM_Object {
3
 
4
  function init(){
5
- add_action('wp_head', array('EM_Calendar', 'insert_js'));
6
  }
7
 
8
- function output($args = array()) {
 
9
  global $wpdb;
10
 
 
 
 
11
  $args = self::get_default_search($args);
12
  $full = $args['full']; //For ZDE, don't delete pls
13
  $month = $args['month'];
@@ -26,6 +30,8 @@ class EM_Calendar extends EM_Object {
26
 
27
  // Get the first day of the month
28
  $month_start = mktime(0,0,0,$month, 1, $year);
 
 
29
  // Get friendly month name
30
  $month_name = date('M',$month_start);
31
  // Figure out which day of the week
@@ -49,12 +55,21 @@ class EM_Calendar extends EM_Object {
49
  // determine how many days are in the last month.
50
  $month_last = $month-1;
51
  $month_next = $month+1;
 
52
  $year_last = $year;
53
  $year_next = $year;
 
 
54
  if($month == 1) {
55
  $month_last = 12;
56
  $year_last = $year -1;
 
 
 
57
  }
 
 
 
58
  $num_days_last = self::days_in_month($month_last, $year_last);
59
 
60
  // determine how many days are in the current month.
@@ -90,9 +105,7 @@ class EM_Calendar extends EM_Object {
90
  // we need to fill in 35 TDs
91
  // so, we will have to figure out
92
  // how many days to appened to the end
93
- // of the final array to make it 35 days.
94
-
95
-
96
  if($current_num > 35){
97
  $num_weeks = 6;
98
  $outset = (42 - $current_num);
@@ -111,40 +124,13 @@ class EM_Calendar extends EM_Object {
111
  // Now let's "chunk" the $all_days array
112
  // into weeks. Each week has 7 days
113
  // so we will array_chunk it into 7 days.
114
- $weeks = array_chunk($new_count, 7);
115
-
116
-
117
-
118
- // Build Previous and Next Links
119
- $base_link = "?".$_SERVER['QUERY_STRING']."&amp;";
120
 
121
- $full ? $link_extra_class = "full-link" : $link_extra_class = '';
122
  //Get an array of arguments that don't include default valued args
123
  $link_args = self::get_link_args($args);
124
 
125
- //Get the previous link
126
- if($month == 1){
127
- $back_month = 12;
128
- $back_year = $year-1;
129
- } else {
130
- $back_month = $month -1;
131
- $back_year = $year;
132
- }
133
- $previous_link = "<a class='em-calnav $link_extra_class' href='?ajaxCalendar=1&amp;month={$back_month}&amp;year={$back_year}&amp;{$link_args}'>&lt;&lt;</a>";
134
-
135
- //Now the next
136
- if($month == 12){
137
- $next_month = 1;
138
- $next_year = $year+1;
139
- } else {
140
- $next_month = $month + 1;
141
- $next_year = $year;
142
- }
143
- $next_link = "<a class='em-calnav $link_extra_class' href='?ajaxCalendar=1&amp;month={$next_month}&amp;year={$next_year}&amp;{$link_args}'>&gt;&gt;</a>";
144
-
145
-
146
- $class = ($full) ? 'dbem-calendar-full' : 'dbem-calendar';
147
- $calendar="<div class='$class'><div style='display:none' class='month_n'>$month</div><div class='year_n' style='display:none' >$year</div>";
148
 
149
  $weekdays = array('Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday');
150
  $n = 0 ;
@@ -154,51 +140,42 @@ class EM_Calendar extends EM_Object {
154
  $n++;
155
  }
156
 
157
- $days_initials = "";
158
  foreach($weekdays as $weekday) {
159
- $days_initials .= "<td>".self::translate_and_trim($weekday)."</td>";
160
  }
161
- $full ? $fullclass = 'fullcalendar' : $fullclass='';
162
- // Build the heading portion of the calendar table
163
- $calendar .= "<table class='dbem-calendar-table $fullclass'>\n".
164
- "<thead>\n<tr>\n".
165
- "<td>$previous_link</td><td class='month_name' colspan='5'>". apply_filters('dbem_calendar_output_month', ucfirst(date_i18n('M', $month_start)), $month_start, $args)." $year</td><td>$next_link</td>\n".
166
- "</tr>\n</thead>\n".
167
- "<tr class='days-names'>\n".
168
- $days_initials.
169
- "</tr>\n";
170
-
171
  // Now we break each key of the array
172
  // into a week and create a new table row for each
173
  // week with the days of that week in the table data
174
 
175
  $i = 0;
176
  $current_date = date('Y-m-d', current_time('timestamp'));
 
177
  foreach ( $weeks as $week ) {
178
- $calendar .= "<tr>\n";
179
  foreach ( $week as $d ) {
 
 
180
  if ($i < $offset_count) { //if it is PREVIOUS month
181
- $calendar .= "<td class='eventless-pre'>" . date ( 'j', $d ) . "</td>\n";
182
  }
183
  if (($i >= $offset_count) && ($i < ($num_weeks * 7) - $outset)) { // if it is THIS month
184
- $day = date ( 'j', $d );
185
- if ( $current_date == date('Y-m-d', $d) ){
186
- $calendar .= "<td class='eventless-today'>$day</td>\n";
187
- } else {
188
- $calendar .= "<td class='eventless'>$day</td>\n";
189
  }
190
  } elseif (($outset > 0)) { //if it is NEXT month
191
  if (($i >= ($num_weeks * 7) - $outset)) {
192
- $calendar .= "<td class='eventless-post'>" . date ( 'j', $d ) . "</td>\n";
193
  }
194
  }
195
  $i ++;
196
  }
197
- $calendar .= "</tr>\n";
198
  }
199
 
200
- $calendar .= " </table>\n</div>";
201
-
202
  // query the database for events in this time span
203
  if ($month == 1) {
204
  $month_pre=12;
@@ -220,6 +197,10 @@ class EM_Calendar extends EM_Object {
220
  $args['month'] = array($month_pre, $month_post);
221
  $events = EM_Events::get($args);
222
 
 
 
 
 
223
  $eventful_days= array();
224
  if($events){
225
  //Go through the events and slot them into the right d-m index
@@ -244,77 +225,54 @@ class EM_Calendar extends EM_Object {
244
  }
245
  }else{
246
  //Only show events on the day that they start
247
- if( isset($eventful_days[$event->start_date]) && is_array($eventful_days[$event->start_date]) ){
248
- $eventful_days[$event->start_date][] = $event;
249
  } else {
250
- $eventful_days[$event->start_date] = array($event);
251
  }
252
  }
253
- $event = apply_filters('em_calendar_output_loop_end', $event);
254
  }
255
  }
256
-
257
- $event_format = get_option('dbem_full_calendar_event_format');
258
- $event_title_format = get_option('dbem_small_calendar_event_title_format');
259
- $event_title_separator_format = get_option('dbem_small_calendar_event_title_separator');
260
- $cells = array() ;
261
  foreach($eventful_days as $day_key => $events) {
262
- //Set the date into the key
263
- $event_start_date = explode('-', $day_key);
264
- $cells[$day_key]['day'] = ltrim($event_start_date[2],'0');
265
- $cells[$day_key]['month'] = $event_start_date[1];
266
- $cells[$day_key]['year'] = $event_start_date[0];
267
- $events_titles = array();
268
- foreach($events as $event) {
269
- $events_titles[] = $event->output($event_title_format);
270
- }
271
- $link_title = implode( $event_title_separator_format, $events_titles);
272
-
273
- $events_page_id = get_option('dbem_events_page');
274
- $event_page_link = get_permalink($events_page_id);
275
- if (stristr($event_page_link, "?"))
276
- $joiner = "&amp;";
277
- else
278
- $joiner = "?";
279
-
280
-
281
- $cells[$day_key]['cell'] = "<a title='$link_title' href='".$event_page_link.$joiner."calendar_day={$day_key}'>{$cells[$day_key]['day']}</a>";
282
- if ($full) {
283
- $cells[$day_key]['cell'] .= "<ul>";
284
-
285
- foreach($events as $event) {
286
- $cells[$day_key]['cell'] .= $event->output($event_format);
287
- }
288
- $cells[$day_key]['cell'] .= "</ul>";
289
- }
290
- }
291
-
292
- if($events){
293
- foreach($cells as $cell) {
294
- if ($cell['month'] == $month_pre && $cell['year'] == $year_pre) {
295
- $calendar = str_replace("<td class='eventless-pre'>".$cell['day']."</td>","<td class='eventful-pre'>".$cell['cell']."</td>",$calendar);
296
- } elseif($cell['month'] == $month_post && $cell['year'] == $year_post) {
297
- $calendar = str_replace("<td class='eventless-post'>".$cell['day']."</td>","<td class='eventful-post'>".$cell['cell']."</td>",$calendar);
298
- } elseif( date('Y-m-j', current_time('timestamp')) == $cell['year']."-".$cell['month']."-".$cell['day'] ) {
299
- $calendar = str_replace("<td class='eventless-today'>".$cell['day']."</td>","<td class='eventful-today'>".$cell['cell']."</td>",$calendar);
300
- } elseif( $cell['month'] == $month && $cell['year'] == $year){
301
- $calendar = str_replace("<td class='eventless'>".$cell['day']."</td>","<td class='eventful'>".$cell['cell']."</td>",$calendar);
302
- }
303
  }
304
- }
305
- return apply_filters('em_calendar_output', '<div id="em-calendar-'.rand(100,200).'" class="em-calendar-wrapper">'.$calendar.'</div>');
306
  }
307
-
308
- /**
309
- * Echoes the calendar external JS contents directly into the head of the document
310
- * @return unknown_type
311
- */
312
- function insert_js() {
313
- ?>
314
- <script type='text/javascript'>
315
- <?php include(WP_PLUGIN_DIR.'/events-manager/includes/js/em_calendar_ajax.js'); ?>
316
- </script>
317
- <?php
318
  }
319
 
320
 
@@ -323,7 +281,11 @@ class EM_Calendar extends EM_Object {
323
  }
324
 
325
  function translate_and_trim($string, $length = 1) {
326
- return substr(__($string), 0, $length);
 
 
 
 
327
  }
328
 
329
  /**
@@ -353,14 +315,27 @@ class EM_Calendar extends EM_Object {
353
  $defaults = array(
354
  'full' => 0, //Will display a full calendar with event names
355
  'long_events' => 0, //Events that last longer than a day
356
- 'scope' => 'all',
357
- 'owner' => false
 
 
 
 
 
358
  );
 
 
 
 
 
 
 
 
 
359
  $atts = parent::get_default_search($defaults, $array);
360
  $atts['full'] = ($atts['full']==true) ? 1:0;
361
  $atts['long_events'] = ($atts['long_events']==true) ? 1:0;
362
  return apply_filters('em_calendar_get_default_search', $atts, $array, $defaults);
363
  }
364
  }
365
- add_action('init', array('EM_Calendar', 'init'));
366
- ?>
2
  class EM_Calendar extends EM_Object {
3
 
4
  function init(){
5
+ //nothing to init anymore
6
  }
7
 
8
+ function get( $args ){
9
+
10
  global $wpdb;
11
 
12
+ $calendar_array = array();
13
+ $calendar_array['cells'] = array();
14
+
15
  $args = self::get_default_search($args);
16
  $full = $args['full']; //For ZDE, don't delete pls
17
  $month = $args['month'];
30
 
31
  // Get the first day of the month
32
  $month_start = mktime(0,0,0,$month, 1, $year);
33
+ $calendar_array['month_start'] = $month_start;
34
+
35
  // Get friendly month name
36
  $month_name = date('M',$month_start);
37
  // Figure out which day of the week
55
  // determine how many days are in the last month.
56
  $month_last = $month-1;
57
  $month_next = $month+1;
58
+ $calendar_array['month_next'] = $month_next;
59
  $year_last = $year;
60
  $year_next = $year;
61
+ $calendar_array['year_next'] = $year_next;
62
+
63
  if($month == 1) {
64
  $month_last = 12;
65
  $year_last = $year -1;
66
+ }elseif($month == 12){
67
+ $month_next = 1;
68
+ $year_next = $year + 1;
69
  }
70
+ $calendar_array['month_last'] = $month_last;
71
+ $calendar_array['year_last'] = $year_last;
72
+
73
  $num_days_last = self::days_in_month($month_last, $year_last);
74
 
75
  // determine how many days are in the current month.
105
  // we need to fill in 35 TDs
106
  // so, we will have to figure out
107
  // how many days to appened to the end
108
+ // of the final array to make it 35 days.
 
 
109
  if($current_num > 35){
110
  $num_weeks = 6;
111
  $outset = (42 - $current_num);
124
  // Now let's "chunk" the $all_days array
125
  // into weeks. Each week has 7 days
126
  // so we will array_chunk it into 7 days.
127
+ $weeks = array_chunk($new_count, 7);
 
 
 
 
 
128
 
 
129
  //Get an array of arguments that don't include default valued args
130
  $link_args = self::get_link_args($args);
131
 
132
+ $previous_url = "?ajaxCalendar=1&amp;month={$month_last}&amp;year={$year_last}&amp;{$link_args}";
133
+ $next_url = "?ajaxCalendar=1&amp;month={$month_next}&amp;year={$year_next}&amp;{$link_args}";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
134
 
135
  $weekdays = array('Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday');
136
  $n = 0 ;
140
  $n++;
141
  }
142
 
143
+ $days_initials_array = array();
144
  foreach($weekdays as $weekday) {
145
+ $days_initials_array[] = self::translate_and_trim($weekday);
146
  }
147
+
148
+ $calendar_array['links'] = array( 'previous_url'=>$previous_url, 'next_url'=>$next_url);
149
+ $calendar_array['row_headers'] = $days_initials_array;
150
+
 
 
 
 
 
 
151
  // Now we break each key of the array
152
  // into a week and create a new table row for each
153
  // week with the days of that week in the table data
154
 
155
  $i = 0;
156
  $current_date = date('Y-m-d', current_time('timestamp'));
157
+ $week_count = 0;
158
  foreach ( $weeks as $week ) {
 
159
  foreach ( $week as $d ) {
160
+ $date = date('Y-m-d', $d);
161
+ $calendar_array['cells'][$date] = array('date'=>$d); //set it up so we have the exact array of dates to be filled
162
  if ($i < $offset_count) { //if it is PREVIOUS month
163
+ $calendar_array['cells'][$date]['type'] = 'pre';
164
  }
165
  if (($i >= $offset_count) && ($i < ($num_weeks * 7) - $outset)) { // if it is THIS month
166
+ if ( $current_date == $date ){
167
+ $calendar_array['cells'][$date]['type'] = 'today';
 
 
 
168
  }
169
  } elseif (($outset > 0)) { //if it is NEXT month
170
  if (($i >= ($num_weeks * 7) - $outset)) {
171
+ $calendar_array['cells'][$date]['type'] = 'post';
172
  }
173
  }
174
  $i ++;
175
  }
176
+ $week_count++;
177
  }
178
 
 
 
179
  // query the database for events in this time span
180
  if ($month == 1) {
181
  $month_pre=12;
197
  $args['month'] = array($month_pre, $month_post);
198
  $events = EM_Events::get($args);
199
 
200
+ $event_format = get_option('dbem_full_calendar_event_format');
201
+ $event_title_format = get_option('dbem_small_calendar_event_title_format');
202
+ $event_title_separator_format = get_option('dbem_small_calendar_event_title_separator');
203
+
204
  $eventful_days= array();
205
  if($events){
206
  //Go through the events and slot them into the right d-m index
225
  }
226
  }else{
227
  //Only show events on the day that they start
228
+ if( isset($eventful_days[$event->event_start_date]) && is_array($eventful_days[$event->event_start_date]) ){
229
+ $eventful_days[$event->event_start_date][] = $event;
230
  } else {
231
+ $eventful_days[$event->event_start_date] = array($event);
232
  }
233
  }
 
234
  }
235
  }
 
 
 
 
 
236
  foreach($eventful_days as $day_key => $events) {
237
+ if( array_key_exists($day_key, $calendar_array['cells']) ){
238
+ //Get link title for this date
239
+ $events_titles = array();
240
+ foreach($events as $event) {
241
+ $events_titles[] = $event->output($event_title_format);
242
+ }
243
+ $calendar_array['cells'][$day_key]['link_title'] = implode( $event_title_separator_format, $events_titles);
244
+
245
+ //Get the link to this calendar day
246
+ global $wp_rewrite;
247
+ if( get_option("dbem_events_page") > 0 ){
248
+ $event_page_link = get_permalink(get_option("dbem_events_page")); //PAGE URI OF EM
249
+ }else{
250
+ if( $wp_rewrite->using_permalinks() ){
251
+ $event_page_link = trailingslashit(home_url()).EM_POST_TYPE_EVENT_SLUG.'/'; //don't use EM_URI here, since ajax calls this before EM_URI is defined.
252
+ }else{
253
+ $event_page_link = trailingslashit(home_url()).'?post_type='.EM_POST_TYPE_EVENT; //don't use EM_URI here, since ajax calls this before EM_URI is defined.
254
+ }
255
+ }
256
+ if( $wp_rewrite->using_permalinks() && !defined('EM_DISABLE_PERMALINKS') ){
257
+ $calendar_array['cells'][$day_key]['link'] = $event_page_link.$day_key."/";
258
+ }else{
259
+ $joiner = (stristr($event_page_link, "?")) ? "&amp;" : "?";
260
+ $calendar_array['cells'][$day_key]['link'] = $event_page_link.$joiner."calendar_day=".$day_key;
261
+ }
262
+ //Add events to array
263
+ $calendar_array['cells'][$day_key]['events'] = $events;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
264
  }
265
+ }
266
+ return apply_filters('em_calendar_get',$calendar_array, $args);
267
  }
268
+
269
+ function output($args = array()) {
270
+ $calendar_array = self::get($args);
271
+ $template = (!empty($args['full'])) ? 'templates/calendar-full.php':'templates/calendar-small.php';
272
+ ob_start();
273
+ em_locate_template($template, true, array('calendar'=>$calendar_array,'args'=>$args));
274
+ $calendar = '<div id="em-calendar-'.rand(100,200).'" class="em-calendar-wrapper">'.ob_get_clean().'</div>';
275
+ return apply_filters('em_calendar_output', $calendar, $args);
 
 
 
276
  }
277
 
278
 
281
  }
282
 
283
  function translate_and_trim($string, $length = 1) {
284
+ if(function_exists('mb_substr')){ //fix for diacritic calendar names
285
+ return mb_substr(__($string), 0, $length);
286
+ }else{
287
+ return substr(__($string), 0, $length);
288
+ }
289
  }
290
 
291
  /**
315
  $defaults = array(
316
  'full' => 0, //Will display a full calendar with event names
317
  'long_events' => 0, //Events that last longer than a day
318
+ 'scope' => 'future',
319
+ 'status' => 1, //approved events only
320
+ 'town' => false,
321
+ 'state' => false,
322
+ 'country' => false,
323
+ 'region' => false,
324
+ 'blog' => get_current_blog_id(),
325
  );
326
+ if(is_multisite()){
327
+ global $bp;
328
+ if( !is_main_site() && !array_key_exists('blog',$array) ){
329
+ //not the main blog, force single blog search
330
+ $array['blog'] = get_current_blog_id();
331
+ }elseif( empty($array['blog']) && get_site_option('dbem_ms_global_events') ) {
332
+ $array['blog'] = false;
333
+ }
334
+ }
335
  $atts = parent::get_default_search($defaults, $array);
336
  $atts['full'] = ($atts['full']==true) ? 1:0;
337
  $atts['long_events'] = ($atts['long_events']==true) ? 1:0;
338
  return apply_filters('em_calendar_get_default_search', $atts, $array, $defaults);
339
  }
340
  }
341
+ add_action('init', array('EM_Calendar', 'init'));
 
classes/em-categories-taxonomy.php ADDED
@@ -0,0 +1,87 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class EM_Categories_Taxonomy{
3
+ function init(){
4
+ add_action( EM_TAXONOMY_CATEGORY.'_edit_form_fields', array('EM_Categories_Taxonomy','form'), 10, 1);
5
+ add_action( EM_TAXONOMY_CATEGORY.'_add_form_fields', array('EM_Categories_Taxonomy','form'), 10, 1);
6
+ add_action( 'edited_'.EM_TAXONOMY_CATEGORY, array('EM_Categories_Taxonomy','save'), 10, 2);
7
+ add_action( 'create_'.EM_TAXONOMY_CATEGORY, array('EM_Categories_Taxonomy','save'), 10, 2);
8
+ self::admin_init();
9
+ }
10
+
11
+ function admin_init(){
12
+ global $pagenow;
13
+ if($pagenow == 'edit-tags.php' && !empty($_GET['taxonomy']) && $_GET['taxonomy'] == EM_TAXONOMY_CATEGORY){
14
+ wp_enqueue_style( 'farbtastic' );
15
+ wp_enqueue_style( 'thickbox' );
16
+
17
+ wp_enqueue_script( 'em-categories-admin', plugins_url().'/events-manager/includes/js/categories-admin.js', array( 'jquery','media-upload','thickbox','farbtastic' ) );
18
+ }
19
+ }
20
+
21
+ function form($tag){
22
+ $category_color = '#FFFFFF';
23
+ $category_image = '';
24
+ if( $tag != EM_TAXONOMY_CATEGORY ){ //not an add new tag form
25
+ $EM_Category = new EM_Category($tag);
26
+ $category_color = $EM_Category->get_color();
27
+ $category_image = $EM_Category->get_image_url();
28
+ }
29
+ ?>
30
+ <tr class="form-field">
31
+ <th scope="row" valign="top"><label for="category-bgcolor">Calendar Color</label></th>
32
+ <td>
33
+ <input type="text" name="category_bgcolor" id="category-bgcolor" class="colorwell" value="<?php echo esc_attr($category_color); ?>" style="width:100px;"/><br />
34
+ <p class="description"><?php echo sprintf(__('Choose a color for your category. You can access this using the %s placeholder.','dbem'),'<code>#_CATEGORYCOLOR</code>'); ?></p>
35
+ <div id="picker" style="position:absolute; display:none; background:#DEDEDE"></div>
36
+ </td>
37
+ </tr>
38
+ <tr class="form-field">
39
+ <th scope="row" valign="top"><label for="product_package_unit_price">Image</label></th>
40
+ <td>
41
+ <?php if( !empty($category_image) ): ?>
42
+ <p><img src="<?php echo $category_image; ?>" /></p>
43
+ <?php endif; ?>
44
+ <input type="text" name="category_image" id="category-image" value="<?php echo esc_attr($category_image); ?>" style="width:300px;" />
45
+ <input id="upload_image_button" type="button" value="<?php _e('Choose/Upload Image','dbem'); ?>" class="button-secondary" style="width:auto;" /><br />
46
+ <p class="description"><?php echo sprintf(__('Choose an image for your category, which can be displayed using the %s placeholder.','dbem'),'<code>#_CATEGORYIMAGE</code>'); ?></p>
47
+ </td>
48
+ </tr>
49
+ <?php
50
+ }
51
+
52
+ function save($term_id, $tt_id){
53
+ global $wpdb;
54
+ if (!$term_id) return;
55
+ if( !empty($_POST['category_bgcolor']) && preg_match('/^#[a-zA-Z0-9]{6}$/', $_POST['category_bgcolor']) ){
56
+ //get results and save/update
57
+ $prev_settings = $wpdb->get_results('SELECT meta_value FROM '.EM_META_TABLE." WHERE object_id='{$term_id}' AND meta_key='category-bgcolor'");
58
+ if( count($prev_settings) > 0 ){
59
+ $wpdb->update(EM_META_TABLE, array('object_id'=>$term_id,'meta_value'=>$_POST['category_bgcolor']), array('object_id'=>$term_id,'meta_key'=>'category-bgcolor'));
60
+ }else{
61
+ $wpdb->insert(EM_META_TABLE, array('object_id'=>$term_id,'meta_key'=>'category-bgcolor','meta_value'=>$_POST['category_bgcolor']));
62
+ }
63
+ }
64
+ if( !empty($_POST['category_image']) ){
65
+ //get results and save/update
66
+ $prev_settings = $wpdb->get_results('SELECT meta_value FROM '.EM_META_TABLE." WHERE object_id='{$term_id}' AND meta_key='category-image'");
67
+ if( count($prev_settings) > 0 ){
68
+ $wpdb->update(EM_META_TABLE, array('object_id'=>$term_id,'meta_value'=>$_POST['category_image']), array('object_id'=>$term_id,'meta_key'=>'category-image'));
69
+ }else{
70
+ $wpdb->insert(EM_META_TABLE, array('object_id'=>$term_id,'meta_key'=>'category-image','meta_value'=>$_POST['category_image']));
71
+ }
72
+ }
73
+ //if in MS mode with global tables, we want to mirror categories in the categories table
74
+ if( EM_MS_GLOBAL ){
75
+ $prev_settings = $wpdb->get_results('SELECT term_id FROM '.EM_CATEGORIES_TABLE." WHERE term_id='{$term_id}'");
76
+ $term = get_term_by('term_id',$term_id, EM_TAXONOMY_CATEGORY);
77
+ if( $term !== false ){
78
+ if( count($prev_settings) > 0 ){
79
+ $wpdb->update(EM_CATEGORIES_TABLE, array('term_id'=>$term_id,'category_slug'=>$term->slug,'category_name'=>$term->name,'category_description'=>$term->description), array('term_id'=>$term_id));
80
+ }else{
81
+ $wpdb->insert(EM_CATEGORIES_TABLE, array('term_id'=>$term_id,'category_slug'=>$term->slug,'category_name'=>$term->name,'category_description'=>$term->description,'category_owner'=>get_current_user_id()));
82
+ }
83
+ }
84
+ }
85
+ }
86
+ }
87
+ add_action('admin_init',array('EM_Categories_Taxonomy','init'));
classes/em-categories.php CHANGED
@@ -1,115 +1,244 @@
1
  <?php
2
- class EM_Categories extends EM_Object {
3
-
4
- function get( $args = array() ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
  global $wpdb;
6
- $categories_table = $wpdb->prefix.EM_CATEGORIES_TABLE;
7
- $events_table = $wpdb->prefix.EM_EVENTS_TABLE;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
 
 
9
  //Quick version, we can accept an array of IDs, which is easy to retrieve
 
10
  if( self::array_is_numeric($args) ){ //Array of numbers, assume they are event IDs to retreive
11
- //We can just get all the events here and return them
12
- $sql = "SELECT * FROM $categories_table WHERE category_id=".implode(" OR category_id=", $args);
13
- $results = $wpdb->get_results(apply_filters('em_categories_get_sql',$sql),ARRAY_A);
14
  $categories = array();
15
  foreach($results as $result){
16
- $categories[$result['category_id']] = new EM_Category($result);
 
 
17
  }
18
- return $categories; //We return all the categories matched as an EM_Event array.
19
- }
20
-
21
- //We assume it's either an empty array or array of search arguments to merge with defaults
22
- $args = self::get_default_search($args);
23
- $limit = ( $args['limit'] && is_numeric($args['limit'])) ? "LIMIT {$args['limit']}" : '';
24
- $offset = ( $limit != "" && is_numeric($args['offset']) ) ? "OFFSET {$args['offset']}" : '';
25
-
26
- //Get the default conditions
27
- $conditions = self::build_sql_conditions($args);
28
- //Put it all together
29
- $where = ( count($conditions) > 0 ) ? " WHERE " . implode ( " AND ", $conditions ):'';
30
-
31
- //Get ordering instructions
32
- $EM_Category = new EM_Category();
33
- $accepted_fields = $EM_Category->get_fields(true);
34
- $orderby = self::build_sql_orderby($args, $accepted_fields, get_option('dbem_categories_default_order'));
35
- //Now, build orderby sql
36
- $orderby_sql = ( count($orderby) > 0 ) ? 'ORDER BY '. implode(', ', $orderby) : '';
37
 
38
- //Create the SQL statement and execute
39
- $sql = "
40
- SELECT * FROM $categories_table
41
- LEFT JOIN $events_table ON {$events_table}.event_category_id={$categories_table}.category_id
42
- $where
43
- GROUP BY category_id
44
- $orderby_sql
45
- $limit $offset
46
- ";
47
- $results = $wpdb->get_results( apply_filters('em_categories_get_sql',$sql, $args), ARRAY_A);
48
- //If we want results directly in an array, why not have a shortcut here?
49
- if( $args['array'] == true ){
50
- return $results;
51
  }
52
-
53
- //Make returned results EM_Event objects
54
- $results = (is_array($results)) ? $results:array();
55
- $categories = array();
56
- foreach ( $results as $category_array ){
57
- $categories[$category_array['category_id']] = new EM_Category($category_array);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
58
  }
 
 
59
 
60
- return apply_filters('em_categories_get', $categories);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
61
  }
62
 
63
- /**
64
- * Will delete given an array of category_ids or EM_Event objects
65
- * @param unknown_type $id_array
66
- */
67
- function delete( $array ){
68
- global $wpdb;
69
- //Detect array type and generate SQL for event IDs
70
- $category_ids = array();
71
- if( @get_class(current($array)) == 'EM_Category' ){
72
- foreach($array as $EM_Category){
73
- $category_ids[] = $EM_Category->id;
74
  }
75
  }else{
76
- $category_ids = $array;
 
 
 
 
 
 
 
 
 
 
 
 
77
  }
78
- if(self::array_is_numeric($category_ids)){
79
- apply_filters('em_categories_delete', $category_ids);
80
- $condition = implode(" OR category_id=", $category_ids);
81
- //Delete all the bookings
82
- $result_bookings = $wpdb->query("DELETE FROM ". $wpdb->prefix . EM_BOOKINGS_TABLE ." WHERE category_id=$condition;");
83
- //Now delete the categories
84
- $result = $wpdb->query ( "DELETE FROM ". $wpdb->prefix . EM_CATEGORIES_TABLE ." WHERE category_id=$condition;" );
85
- do_action('em_categories_delete', $category_ids);
 
 
 
 
86
  }
87
- //TODO add error detection on categories delete fails
88
- return apply_filters('em_categories_delete', true, $category_ids);
89
  }
90
 
91
- /* Overrides EM_Object method to apply a filter to result
92
  * @see wp-content/plugins/categories-manager/classes/EM_Object#build_sql_conditions()
93
  */
94
  function build_sql_conditions( $args = array() ){
95
  global $wpdb;
96
- $events_table = $wpdb->prefix . EM_EVENTS_TABLE;
97
- $locations_table = $wpdb->prefix . EM_LOCATIONS_TABLE;
98
 
99
- //FIXME EM_Categories doesn't build sql conditions in EM_Object
100
  $conditions = array();
101
- //eventful locations
102
- if( true == $args['eventful'] ){
103
- $conditions['eventful'] = "{$events_table}.event_id IS NOT NULL";
104
- }elseif( true == $args['eventless'] ){
105
- $conditions['eventless'] = "{$events_table}.event_id IS NULL";
106
  }
107
- //owner lookup
108
- if( is_numeric($args['owner']) ){
109
- $conditions['owner'] = "category_owner=".get_current_user_id();
110
- }elseif( preg_match('/^([0-9],?)+$/', $args['owner']) ){
111
- $conditions['owner'] = "category_owner IN (".explode(',', $args['owner']).")";
112
- }
113
  return apply_filters( 'em_categories_build_sql_conditions', $conditions, $args );
114
  }
115
 
@@ -128,30 +257,53 @@ class EM_Categories extends EM_Object {
128
  */
129
  function get_default_search( $array = array() ){
130
  $defaults = array(
131
- 'scope'=>false,
132
- 'eventful' => false, //cats that have an event (scope will also play a part here
133
- 'eventless' => false, //cats WITHOUT events, eventful takes precedence
 
 
 
134
  );
135
- if( is_admin() ){
136
- //by default, we only get categories the owner can manage
137
- switch( get_option('dbem_permissions_categories') ){
138
- case 0:
139
- $defaults['owner'] = get_current_user_id();
140
- break;
141
- case 1:
142
- $wp_user_search = new WP_User_Search(null, null, 'administrator');
143
- $users = $wp_user_search->get_results();
144
- $users[] = get_current_user_id();
145
- $users[] = 0;
146
- $defaults['owner'] = implode(',', $users);
147
- break;
148
- case 2:
149
- $defaults['owner'] = false;
150
- break;
151
- }
152
- $defaults['owner'] = ( em_verify_admin() ) ? false:$defaults['owner'];
153
- }
154
  return apply_filters('em_categories_get_default_search', parent::get_default_search($defaults,$array), $array, $defaults);
155
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
156
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
157
  }
1
  <?php
2
+ class EM_Categories extends EM_Object implements Iterator{
3
+
4
+ /**
5
+ * Array of EM_Category objects for a specific event
6
+ * @var array
7
+ */
8
+ var $categories = array();
9
+ /**
10
+ * Event ID of this set of categories
11
+ * @var int
12
+ */
13
+ var $event_id;
14
+ /**
15
+ * Post ID of this set of categories
16
+ * @var int
17
+ */
18
+ var $post_id;
19
+
20
+ /**
21
+ * Creates an EM_Categories instance, currently accepts an EM_Event object (gets all Categories for that event) or array of any EM_Category objects, which can be manipulated in bulk with helper functions.
22
+ * @param mixed $data
23
+ * @return null
24
+ */
25
+ function EM_Categories( $data = false ){
26
  global $wpdb;
27
+ $this->ms_global_switch();
28
+ if( is_object($data) && get_class($data) == "EM_Event" && !empty($data->post_id) ){ //Creates a blank categories object if needed
29
+ $this->event_id = $data->event_id;
30
+ $this->post_id = $data->post_id;
31
+ if( EM_MS_GLOBAL && !is_main_site() ){
32
+ $cat_ids = $wpdb->get_col('SELECT meta_value FROM '.EM_META_TABLE." WHERE object_id='{$this->event_id}' AND meta_key='event-category'");
33
+ foreach($cat_ids as $cat_id){
34
+ $this->categories[$cat_id] = new EM_Category($cat_id);
35
+ }
36
+ }else{
37
+ $results = get_the_terms( $data->post_id, EM_TAXONOMY_CATEGORY );
38
+ if( is_array($results) ){
39
+ foreach($results as $result){
40
+ $this->categories[$result->term_id] = new EM_Category($result);
41
+ }
42
+ }
43
+ }
44
+ }elseif( is_array($data) && $this->array_is_numeric($data) ){
45
+ foreach($data as $category_id){
46
+ $this->categories[$category_id] = new EM_Category($category_id);
47
+ }
48
+ }elseif( is_array($data) ){
49
+ foreach( $data as $EM_Category ){
50
+ if( get_class($EM_Category) == 'EM_Category'){
51
+ $this->categories[] = $EM_Category;
52
+ }
53
+ }
54
+ }
55
+ $this->ms_global_switch_back();
56
+ do_action('em_categories', $this);
57
+ }
58
+
59
+ function get_post(){
60
+ $this->ms_global_switch();
61
+ if(!empty($_POST['event_categories']) && $this->array_is_numeric($_POST['event_categories'])){
62
+ foreach( $_POST['event_categories'] as $term ){
63
+ $this->categories[$term] = new EM_Category($term);
64
+ }
65
+ }
66
+ $this->ms_global_switch_back();
67
+ do_action('em_categories_get_post', $this);
68
+ }
69
+
70
+ function save(){
71
+ $term_slugs = array();
72
+ foreach($this->categories as $EM_Category){
73
+ /* @var $EM_Category EM_Category */
74
+ if( !empty($EM_Category->slug) ) $term_slugs[] = $EM_Category->slug; //save of category will soft-fail if slug is empty
75
+ }
76
+ if( count($term_slugs) > 0 ){
77
+ if( is_multisite() ){
78
+ //In MS Global mode, we also save category meta information for global lookups
79
+ if( EM_MS_GLOBAL && !empty($this->event_id) ){
80
+ //delete categories
81
+ $this->save_index();
82
+ }
83
+ if( !EM_MS_GLOBAL || is_main_site() ){
84
+ wp_set_object_terms($this->post_id, $term_slugs, EM_TAXONOMY_CATEGORY);
85
+ }
86
+ }else{
87
+ wp_set_object_terms($this->post_id, $term_slugs, EM_TAXONOMY_CATEGORY);
88
+ }
89
+ }
90
+ do_action('em_categories_save', $this);
91
+ }
92
+
93
+ function save_index(){
94
+ global $wpdb;
95
+ $wpdb->query('DELETE FROM '.EM_META_TABLE." WHERE object_id='{$this->event_id}' AND meta_key='event-category'");
96
+ foreach($this->categories as $EM_Category){
97
+ $wpdb->insert(EM_META_TABLE, array('meta_value'=>$EM_Category->term_id,'object_id'=>$this->event_id,'meta_key'=>'event-category'));
98
+ }
99
+ }
100
 
101
+ function get( $args = array() ) {
102
  //Quick version, we can accept an array of IDs, which is easy to retrieve
103
+ self::ms_global_switch();
104
  if( self::array_is_numeric($args) ){ //Array of numbers, assume they are event IDs to retreive
105
+ $results = get_terms( EM_TAXONOMY_CATEGORY );
 
 
106
  $categories = array();
107
  foreach($results as $result){
108
+ if( in_array($result->term_id, $args) ){
109
+ $categories[$result->term_id] = new EM_Category($result);
110
+ }
111
  }
112
+ }else{
113
+ //We assume it's either an empty array or array of search arguments to merge with defaults
114
+ $term_args = self::get_default_search($args);
115
+ $results = get_terms( EM_TAXONOMY_CATEGORY, $term_args);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
116
 
117
+ //If we want results directly in an array, why not have a shortcut here? We don't use this in code, so if you're using it and filter the em_categories_get hook, you may want to do this one too.
118
+ if( $args['array'] == true ){
119
+ return apply_filters('em_categories_get_array', $results, $args);
120
+ }
121
+
122
+ //Make returned results EM_Category objects
123
+ $results = (is_array($results)) ? $results:array();
124
+ $categories = array();
125
+ foreach ( $results as $category ){
126
+ $categories[$category->term_id] = new EM_Category($category);
127
+ }
 
 
128
  }
129
+ self::ms_global_switch_back();
130
+ return apply_filters('em_categories_get', $categories, $args);
131
+ }
132
+
133
+ function output( $args ){
134
+ global $EM_Category;
135
+ $EM_Category_old = $EM_Category; //When looping, we can replace EM_Category global with the current event in the loop
136
+ //Can be either an array for the get search or an array of EM_Category objects
137
+ if( is_object(current($args)) && get_class((current($args))) == 'EM_Category' ){
138
+ $func_args = func_get_args();
139
+ $categories = $func_args[0];
140
+ $args = (!empty($func_args[1])) ? $func_args[1] : array();
141
+ $args = apply_filters('em_categories_output_args', self::get_default_search($args), $categories);
142
+ $limit = ( !empty($args['limit']) && is_numeric($args['limit']) ) ? $args['limit']:false;
143
+ $offset = ( !empty($args['offset']) && is_numeric($args['offset']) ) ? $args['offset']:0;
144
+ $page = ( !empty($args['page']) && is_numeric($args['page']) ) ? $args['page']:1;
145
+ }else{
146
+ $args = apply_filters('em_categories_output_args', self::get_default_search($args) );
147
+ $limit = ( !empty($args['limit']) && is_numeric($args['limit']) ) ? $args['limit']:false;
148
+ $offset = ( !empty($args['offset']) && is_numeric($args['offset']) ) ? $args['offset']:0;
149
+ $page = ( !empty($args['page']) && is_numeric($args['page']) ) ? $args['page']:1;
150
+ $args['limit'] = false;
151
+ $args['offset'] = false;
152
+ $args['page'] = false;
153
+ $categories = self::get( $args );
154
  }
155
+ //What format shall we output this to, or use default
156
+ $format = ( $args['format'] == '' ) ? get_option( 'dbem_categories_list_item_format' ) : $args['format'] ;
157
 
158
+ $output = "";
159
+ $categories_count = count($categories);
160
+ $categories = apply_filters('em_categories_output_categories', $categories);
161
+ if ( count($categories) > 0 ) {
162
+ $category_count = 0;
163
+ $categories_shown = 0;
164
+ foreach ( $categories as $EM_Category ) {
165
+ if( ($categories_shown < $limit || empty($limit)) && ($category_count >= $offset || $offset === 0) ){
166
+ $output .= $EM_Category->output($format);
167
+ $categories_shown++;
168
+ }
169
+ $category_count++;
170
+ }
171
+ //Add headers and footers to output
172
+ if( $format == get_option ( 'dbem_categories_list_item_format' ) ){
173
+ $single_event_format_header = get_option ( 'dbem_categories_list_item_format_header' );
174
+ $single_event_format_header = ( $single_event_format_header != '' ) ? $single_event_format_header : "<ul class='em-categories-list'>";
175
+ $single_event_format_footer = get_option ( 'dbem_categories_list_item_format_footer' );
176
+ $single_event_format_footer = ( $single_event_format_footer != '' ) ? $single_event_format_footer : "</ul>";
177
+ $output = $single_event_format_header . $output . $single_event_format_footer;
178
+ }
179
+ //Pagination (if needed/requested)
180
+ if( !empty($args['pagination']) && !empty($limit) && $categories_count >= $limit ){
181
+ //Show the pagination links (unless there's less than 10 events, or the custom limit)
182
+ $page_link_template = preg_replace('/(&|\?)page=\d+/i','',$_SERVER['REQUEST_URI']);
183
+ $page_link_template = em_add_get_params($page_link_template, array('page'=>'%PAGE%'), false); //don't html encode, so em_paginate does its thing
184
+ $output .= apply_filters('em_events_output_pagination', em_paginate( $page_link_template, $categories_count, $limit, $page), $page_link_template, $categories_count, $limit, $page);
185
+ }
186
+ } else {
187
+ $output = get_option ( 'dbem_no_categories_message' );
188
+ }
189
+ //FIXME check if reference is ok when restoring object, due to changes in php5 v 4
190
+ $EM_Category_old= $EM_Category;
191
+ return apply_filters('em_categories_output', $output, $categories, $args);
192
  }
193
 
194
+ function has( $search ){
195
+ if( is_numeric($search) ){
196
+ foreach($this->categories as $EM_Category){
197
+ if($EM_Category->term_id == $search) return apply_filters('em_categories_has', true, $search, $this);
 
 
 
 
 
 
 
198
  }
199
  }else{
200
+ foreach($this->categories as $EM_Category){
201
+ if($EM_Category->slug == $search) return apply_filters('em_categories_has', true, $search, $this);
202
+ }
203
+ }
204
+ return apply_filters('em_categories_has', false, $search, $this);
205
+ }
206
+
207
+ function get_ids(){
208
+ $ids = array();
209
+ foreach($this->categories as $EM_Category){
210
+ if( !empty($EM_Category->term_id) ){
211
+ $ids[] = $EM_Category->term_id;
212
+ }
213
  }
214
+ return $ids;
215
+ }
216
+
217
+ /**
218
+ * Gets the event for this object, or a blank event if none exists
219
+ * @return EM_Event
220
+ */
221
+ function get_event(){
222
+ if( is_numeric($this->event_id) ){
223
+ return em_get_event($this->event_id);
224
+ }else{
225
+ return new EM_Event();
226
  }
 
 
227
  }
228
 
229
+ /* Overrides EM_Object method to apply a filter to result. Categories won't accept many arguments as you tend to search with events for much else.
230
  * @see wp-content/plugins/categories-manager/classes/EM_Object#build_sql_conditions()
231
  */
232
  function build_sql_conditions( $args = array() ){
233
  global $wpdb;
234
+ $events_table = EM_EVENTS_TABLE;
235
+ $locations_table = EM_LOCATIONS_TABLE;
236
 
237
+ $temp_conditions = parent::build_sql_conditions($args);
238
  $conditions = array();
239
+ if( !empty($temp_conditions['category']) ){
240
+ $conditions['category'] = $temp_conditions['category'];
 
 
 
241
  }
 
 
 
 
 
 
242
  return apply_filters( 'em_categories_build_sql_conditions', $conditions, $args );
243
  }
244
 
257
  */
258
  function get_default_search( $array = array() ){
259
  $defaults = array(
260
+ //added from get_terms, so they don't get filtered out
261
+ 'orderby' => 'name', 'order' => 'ASC',
262
+ 'hide_empty' => true, 'exclude' => array(), 'exclude_tree' => array(), 'include' => array(),
263
+ 'number' => '', 'fields' => 'all', 'slug' => '', 'parent' => '',
264
+ 'hierarchical' => true, 'child_of' => 0, 'get' => '', 'name__like' => '',
265
+ 'pad_counts' => false, 'offset' => '', 'search' => '', 'cache_domain' => 'core'
266
  );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
267
  return apply_filters('em_categories_get_default_search', parent::get_default_search($defaults,$array), $array, $defaults);
268
  }
269
+
270
+ /**
271
+ * will return the default search parameter to use according to permission settings
272
+ * @return string
273
+ */
274
+ function get_default_search_owner(){
275
+ //by default, we only get categories the owner can manage
276
+ $defaults = array('owner'=>false);
277
+ //by default, we only get categories the owner can manage
278
+ if( !current_user_can('edit_categories') ){
279
+ $defaults['owner'] = get_current_user_id();
280
+ break;
281
+ }else{
282
+ $defaults['owner'] = false;
283
+ break;
284
+ }
285
+ return $defaults['owner'];
286
+ }
287
 
288
+ //Iterator Implementation
289
+ public function rewind(){
290
+ reset($this->categories);
291
+ }
292
+ public function current(){
293
+ $var = current($this->categories);
294
+ return $var;
295
+ }
296
+ public function key(){
297
+ $var = key($this->categories);
298
+ return $var;
299
+ }
300
+ public function next(){
301
+ $var = next($this->categories);
302
+ return $var;
303
+ }
304
+ public function valid(){
305
+ $key = key($this->categories);
306
+ $var = ($key !== NULL && $key !== FALSE);
307
+ return $var;
308
+ }
309
  }
classes/em-category-taxonomy.php ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class EM_Category_Taxonomy{
4
+ function init(){
5
+ if( !is_admin() ){
6
+ add_filter('archive_template', array('EM_Category_Taxonomy','template'));
7
+ add_filter('category_template', array('EM_Category_Taxonomy','template'));
8
+ add_filter('parse_query', array('EM_Category_Taxonomy','parse_query'));
9
+ }
10
+ }
11
+ /**
12
+ * Overrides archive pages e.g. locations, events, event categories, event tags based on user settings
13
+ * @param string $template
14
+ * @return string
15
+ */
16
+ function template($template){
17
+ global $wp_query;
18
+ if( is_archive() ){
19
+ if( !empty($wp_query->queried_object->taxonomy) && $wp_query->queried_object->taxonomy == EM_TAXONOMY_CATEGORY && get_option('dbem_cp_categories_formats', true)){
20
+ add_filter('the_content', array('EM_Category_Taxonomy','the_content'));
21
+ $wp_query->posts = array();
22
+ $wp_query->posts[0] = new stdClass();
23
+ $wp_query->posts[0]->post_title = $wp_query->queried_object->name;
24
+ $wp_query->posts[0]->post_content = '';
25
+ $wp_query->post = $wp_query->posts[0];
26
+ $wp_query->post_count = 1;
27
+ $wp_query->found_posts = 1;
28
+ $wp_query->max_num_pages = 1;
29
+ //echo "<pre>"; print_r($wp_query); echo "</pre>";
30
+ $template = locate_template(array('page.php','index.php'),false); //category becomes a page
31
+ }
32
+ }
33
+ return $template;
34
+ }
35
+
36
+ function the_content($content){
37
+ global $wp_query, $EM_Category;
38
+ $EM_Category = new EM_Category($wp_query->queried_object);
39
+ ob_start();
40
+ em_locate_template('templates/category-single.php',true);
41
+ return ob_get_clean();
42
+ }
43
+
44
+ function parse_query( ){
45
+ global $wp_query;
46
+ if( !empty($wp_query->tax_query->queries[0]['taxonomy']) && $wp_query->tax_query->queries[0]['taxonomy'] == EM_TAXONOMY_CATEGORY) {
47
+ if( get_option('dbem_categories_default_archive_orderby') == 'title'){
48
+ $wp_query->query_vars['orderby'] = 'title';
49
+ }else{
50
+ $wp_query->query_vars['orderby'] = 'meta_value_num';
51
+ $wp_query->query_vars['meta_key'] = get_option('dbem_categories_default_archive_orderby','_start_ts');
52
+ }
53
+ $wp_query->query_vars['order'] = get_option('dbem_categories_default_archive_order','ASC');
54
+ }
55
+ }
56
+ }
57
+ EM_Category_Taxonomy::init();
classes/em-category.php CHANGED
@@ -1,152 +1,193 @@
1
  <?php
2
  //TODO expand em_category to be like other classes
3
  class EM_Category extends EM_Object {
4
- //DB Fields
5
  var $id = '';
6
- var $owner = '';
7
- var $name = '';
8
- //Other Vars
9
- var $fields = array(
10
- 'category_id' => array('name'=>'id','type'=>'%d'),
11
- 'category_owner' => array('name'=>'owner','type'=>'%d'),
12
- 'category_name' => array('name'=>'name','type'=>'%s')
13
- );
14
- var $required_fields;
15
- var $feedback_message = "";
16
- var $errors = array();
 
17
 
18
  /**
19
  * Gets data from POST (default), supplied array, or from the database if an ID is supplied
20
- * @param $location_data
21
  * @return null
22
  */
23
  function EM_Category( $category_data = false ) {
 
 
24
  //Initialize
25
- $this->required_fields = array("category_name" => __('The category name', 'dbem'));
26
  $category = array();
27
- if( $category_data != false ){
28
- //Load location data
29
- if( is_array($category_data) && isset($category_data['category_name']) ){
30
  $category = $category_data;
31
- }elseif( is_numeric($category_data) ){
32
- //Retreiving from the database
33
- global $wpdb;
34
- $sql = "SELECT * FROM ". $wpdb->prefix.EM_CATEGORIES_TABLE ." WHERE category_id ='{$category_data}'";
35
- $category = $wpdb->get_row($sql, ARRAY_A);
36
  }
37
- //Save into the object
38
- $this->to_object($category);
39
- }
 
 
 
 
40
  }
41
 
42
- function get_post(){
43
- //We are getting the values via POST or GET
44
- do_action('em_location_get_post_pre', $this);
45
- $category = array();
46
- $category['category_id'] = ( !empty($_POST['category_id']) ) ? $_POST['category_id']:'';
47
- $category['category_name'] = ( !empty($_POST['category_name']) ) ? stripslashes($_POST['category_name']):'';
48
- $category['category_owner'] = ( !empty($_POST['category_owner']) && is_numeric($_POST['category_owner']) ) ? $_POST['category_owner']:get_current_user_id();
49
- $this->to_object( apply_filters('em_category_get_post', $category, $this) );
50
  }
51
 
52
- function save(){
53
- global $wpdb;
54
- do_action('em_category_save_pre', $this);
55
- $table = $wpdb->prefix.EM_CATEGORIES_TABLE;
56
- $data = $this->to_array();
57
- unset($data['category_id']);
58
- if($this->id != ''){
59
- $where = array( 'category_id' => $this->id );
60
- $wpdb->update($table, $data, $where, $this->get_types($data));
61
- }else{
62
- $wpdb->insert($table, $data, $this->get_types($data));
63
- $this->id = $wpdb->insert_id;
64
  }
65
- return apply_filters('em_category_save', ( $this->id > 0 && $image_upload ), $this, $image_upload);
66
  }
67
 
68
- function delete(){
69
- global $wpdb;
70
- do_action('em_category_delete_pre', $this);
71
- $table_name = $wpdb->prefix.EM_CATEGORIES_TABLE;
72
- $sql = "DELETE FROM $table_name WHERE category_id = '{$this->id}';";
73
- $result = $wpdb->query($sql);
74
- return apply_filters('em_category_delete', $result, $this);
75
- }
76
-
77
- /**
78
- * Validates the category. Should be run during any form submission or saving operation.
79
- * @return boolean
80
- */
81
- function validate(){
82
- $missing_fields = Array ();
83
- foreach ( $this->required_fields as $key => $field ) {
84
- $true_field = $this->fields[$key]['name'];
85
- if ( $this->$true_field == "") {
86
- $missing_fields[] = $field;
87
- }
88
- }
89
- if ( count($missing_fields) > 0){
90
- // TODO Create friendly equivelant names for missing fields notice in validation
91
- $this->errors[] = __ ( 'Missing fields: ' ) . implode ( ", ", $missing_fields ) . ". ";
92
  }
93
- return apply_filters('em_category_validate', ( count($this->errors) == 0 ), $this);
94
  }
95
 
96
  function has_events(){
97
- global $wpdb;
98
- $events_table = $wpdb->prefix.EM_EVENTS_TABLE;
 
99
  $sql = "SELECT count(event_id) as events_no FROM $events_table WHERE category_id = {$this->id}";
100
  $affected_events = $wpdb->get_row($sql);
101
  return apply_filters('em_category_has_events', (count($affected_events) > 0), $this);
102
  }
103
 
104
  function output_single($target = 'html'){
105
- $format = get_option ( 'dbem_single_category_format' );
106
  return apply_filters('em_category_output_single', $this->output($format, $target), $this, $target);
107
  }
108
 
109
  function output($format, $target="html") {
 
 
 
 
 
 
 
110
  $category_string = $format;
111
- preg_match_all("/#_[A-Za-z]+/", $format, $placeholders);
112
- foreach($placeholders[0] as $result) {
113
  $match = true;
114
  $replace = '';
 
115
  switch( $result ){
116
  case '#_CATEGORYNAME':
117
  $replace = $this->name;
118
  break;
119
  case '#_CATEGORYID':
120
- $replace = $this->id;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
121
  break;
122
  default:
123
- $match = false;
124
  break;
125
  }
126
- if($match){ //if true, we've got a placeholder that needs replacing
127
- //TODO FILTER - placeholder filter
128
- $replace = apply_filters('em_category_output_placeholder', $replace, $this, $result, $target); //USE WITH CAUTION! THIS MIGHT GET RENAMED
129
- $category_string = str_replace($result, $replace , $category_string );
130
- }
131
  }
132
  $name_filter = ($target == "html") ? 'dbem_general':'dbem_general_rss'; //TODO remove dbem_ filters
133
  $category_string = str_replace('#_CATEGORY', apply_filters($name_filter, $this->name) , $category_string ); //Depreciated
134
  return apply_filters('em_category_output', $category_string, $this, $format, $target);
135
  }
136
 
137
- function can_manage(){
138
- return ( get_option('dbem_permissions_categories') == 2 || $this->owner == get_current_user_id() || empty($this->id) || em_verify_admin() );
139
- }
140
-
141
- function can_use(){
142
- switch( get_option('dbem_permissions_locations') ){
143
- case 0:
144
- return $this->owner == get_current_user_id();
145
- case 1:
146
- return em_verify_admin($this->owner);
147
- case 2:
148
- return true;
 
149
  }
 
150
  }
151
  }
152
  ?>
1
  <?php
2
  //TODO expand em_category to be like other classes
3
  class EM_Category extends EM_Object {
4
+ //Taxonomy Fields
5
  var $id = '';
6
+ var $term_id;
7
+ var $name;
8
+ var $slug;
9
+ var $term_group;
10
+ var $term_taxonomy_id;
11
+ var $taxonomy;
12
+ var $description = '';
13
+ var $parent = 0;
14
+ var $count;
15
+ //extra attributes imposed by EM_Category
16
+ var $image_url = '';
17
+ var $color;
18
 
19
  /**
20
  * Gets data from POST (default), supplied array, or from the database if an ID is supplied
21
+ * @param $category_data
22
  * @return null
23
  */
24
  function EM_Category( $category_data = false ) {
25
+ global $wpdb;
26
+ $this->ms_global_switch();
27
  //Initialize
 
28
  $category = array();
29
+ if( !empty($category_data) ){
30
+ //Load category data
31
+ if( is_object($category_data) && !empty($category_data->taxonomy) && $category_data->taxonomy == EM_TAXONOMY_CATEGORY ){
32
  $category = $category_data;
33
+ }elseif( !is_numeric($category_data) ){
34
+ $category = get_term_by('slug', $category_data, EM_TAXONOMY_CATEGORY);
35
+ }else{
36
+ $category = get_term_by('id', $category_data, EM_TAXONOMY_CATEGORY);
 
37
  }
38
+ }
39
+ foreach($category as $key => $value){
40
+ $this->$key = $value;
41
+ }
42
+ $this->id = $this->term_id; //backward compatability
43
+ $this->ms_global_switch_back();
44
+ do_action('em_category',$this, $category_data);
45
  }
46
 
47
+ function get_color(){
48
+ if( empty($this->color) ){
49
+ global $wpdb;
50
+ $color = $wpdb->get_var('SELECT meta_value FROM '.EM_META_TABLE." WHERE object_id='{$this->term_id}' AND meta_key='category-bgcolor' LIMIT 1");
51
+ $this->color = ($color != '') ? $color:'#FFFFFF';
52
+ }
53
+ return $this->color;
 
54
  }
55
 
56
+ function get_image_url(){
57
+ if( empty($this->image_url) ){
58
+ global $wpdb;
59
+ $image_url = $wpdb->get_var('SELECT meta_value FROM '.EM_META_TABLE." WHERE object_id='{$this->term_id}' AND meta_key='category-image' LIMIT 1");
60
+ $this->image_url = ($image_url != '') ? $image_url:'';
 
 
 
 
 
 
 
61
  }
62
+ return $this->image_url;
63
  }
64
 
65
+ function get_url(){
66
+ if( empty($this->link) ){
67
+ $this->ms_global_switch();
68
+ $this->link = get_term_link($this->slug, EM_TAXONOMY_CATEGORY);
69
+ $this->ms_global_switch_back();
70
+ if ( is_wp_error($this->link) ) $this->link = '';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
71
  }
72
+ return $this->link;
73
  }
74
 
75
  function has_events(){
76
+ global $wpdb;
77
+ //FIXME old event category checking
78
+ $events_table = EM_EVENTS_TABLE;
79
  $sql = "SELECT count(event_id) as events_no FROM $events_table WHERE category_id = {$this->id}";
80
  $affected_events = $wpdb->get_row($sql);
81
  return apply_filters('em_category_has_events', (count($affected_events) > 0), $this);
82
  }
83
 
84
  function output_single($target = 'html'){
85
+ $format = get_option ( 'dbem_category_page_format' );
86
  return apply_filters('em_category_output_single', $this->output($format, $target), $this, $target);
87
  }
88
 
89
  function output($format, $target="html") {
90
+ preg_match_all('/\{([a-zA-Z0-9_]+)\}([^{]+)\{\/[a-zA-Z0-9_]+\}/', $format, $conditionals);
91
+ if( count($conditionals[0]) > 0 ){
92
+ //Check if the language we want exists, if not we take the first language there
93
+ foreach($conditionals[1] as $key => $condition){
94
+ $format = str_replace($conditionals[0][$key], apply_filters('em_category_output_condition', '', $condition, $conditionals[0][$key], $this), $format);
95
+ }
96
+ }
97
  $category_string = $format;
98
+ preg_match_all("/(#@?_?[A-Za-z0-9]+)({([a-zA-Z0-9,]+)})?/", $format, $placeholders);
99
+ foreach($placeholders[1] as $key => $result) {
100
  $match = true;
101
  $replace = '';
102
+ $full_result = $placeholders[0][$key];
103
  switch( $result ){
104
  case '#_CATEGORYNAME':
105
  $replace = $this->name;
106
  break;
107
  case '#_CATEGORYID':
108
+ $replace = $this->term_id;
109
+ break;
110
+ case '#_CATEGORYNOTES':
111
+ case '#_CATEGORYDESCRIPTION':
112
+ $replace = $this->description;
113
+ break;
114
+ case '#_CATEGORYIMAGE':
115
+ case '#_CATEGORYIMAGEURL':
116
+ if( $this->get_image_url() != ''){
117
+ if($result == '#_CATEGORYIMAGEURL'){
118
+ $replace = $this->get_image_url();
119
+ }else{
120
+ if( empty($placeholders[3][$key]) ){
121
+ $replace = "<img src='".esc_url($this->get_image_url())."' alt='".esc_attr($this->name)."'/>";
122
+ }else{
123
+ $image_size = explode(',', $placeholders[3][$key]);
124
+ if( $this->array_is_numeric($image_size) && count($image_size) > 1 ){
125
+ $replace = "<img src='".em_get_thumbnail_url($this->get_image_url(), $image_size[0], $image_size[1])."' alt='".esc_attr($this->name)."'/>";
126
+ }else{
127
+ $replace = "<img src='".esc_url($this->get_image_url())."' alt='".esc_attr($this->name)."'/>";
128
+ }
129
+ }
130
+ }
131
+ }
132
+ break;
133
+ case '#_CATEGORYCOLOR':
134
+ $replace = $this->get_color();
135
+ break;
136
+ case '#_CATEGORYLINK':
137
+ case '#_CATEGORYURL':
138
+ $link = $this->get_url();
139
+ $replace = ($result == '#_CATEGORYURL') ? $link : '<a href="'.$link.'">'.esc_html($this->name).'</a>';
140
+ break;
141
+ case '#_CATEGORYEVENTSPAST': //depreciated, erroneous documentation, left for compatability
142
+ case '#_CATEGORYEVENTSNEXT': //depreciated, erroneous documentation, left for compatability
143
+ case '#_CATEGORYEVENTSALL': //depreciated, erroneous documentation, left for compatability
144
+ case '#_CATEGORYPASTEVENTS':
145
+ case '#_CATEGORYNEXTEVENTS':
146
+ case '#_CATEGORYALLEVENTS':
147
+ //convert depreciated placeholders for compatability
148
+ $result = ($result == '#_CATEGORYEVENTSPAST') ? '#_CATEGORYPASTEVENTS':$result;
149
+ $result = ($result == '#_CATEGORYEVENTSNEXT') ? '#_CATEGORYNEXTEVENTS':$result;
150
+ $result = ($result == '#_CATEGORYEVENTSALL') ? '#_CATEGORYALLEVENTS':$result;
151
+ //forget it ever happened? :/
152
+ if ($result == '#_CATEGORYPASTEVENTS'){ $scope = 'past'; }
153
+ elseif ( $result == '#_CATEGORYNEXTEVENTS' ){ $scope = 'future'; }
154
+ else{ $scope = 'all'; }
155
+ $events = EM_Events::get( array('category'=>$this->term_id, 'scope'=>$scope) );
156
+ if ( count($events) > 0 ){
157
+ foreach($events as $EM_Event){
158
+ $replace .= $EM_Event->output(get_option('dbem_category_event_list_item_format'));
159
+ }
160
+ } else {
161
+ $replace = get_option('dbem_category_no_events_message');
162
+ }
163
  break;
164
  default:
165
+ $replace = $full_result;
166
  break;
167
  }
168
+ $replace = apply_filters('em_category_output_placeholder', $replace, $this, $full_result, $target); //USE WITH CAUTION! THIS MIGHT GET RENAMED
169
+ $category_string = str_replace($full_result, $replace , $category_string );
 
 
 
170
  }
171
  $name_filter = ($target == "html") ? 'dbem_general':'dbem_general_rss'; //TODO remove dbem_ filters
172
  $category_string = str_replace('#_CATEGORY', apply_filters($name_filter, $this->name) , $category_string ); //Depreciated
173
  return apply_filters('em_category_output', $category_string, $this, $format, $target);
174
  }
175
 
176
+ function can_manage( $capability_owner = 'edit_categories', $capability_admin = false ){
177
+ global $em_capabilities_array;
178
+ //Figure out if this is multisite and require an extra bit of validation
179
+ $multisite_check = true;
180
+ $can_manage = current_user_can($capability_owner);
181
+ //if multisite and supoer admin, just return true
182
+ if( is_multisite() && is_super_admin() ){ return true; }
183
+ if( EM_MS_GLOBAL && !is_main_site() ){
184
+ //User can't admin this bit, as they're on a sub-blog
185
+ $can_manage = false;
186
+ if(array_key_exists($capability_owner, $em_capabilities_array) ){
187
+ $this->add_error( $em_capabilities_array[$capability_owner]);
188
+ }
189
  }
190
+ return $can_manage;
191
  }
192
  }
193
  ?>
classes/em-event-post-admin.php ADDED
@@ -0,0 +1,372 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Events Edit Page
4
+ */
5
+ class EM_Event_Post_Admin{
6
+ function init(){
7
+ global $pagenow;
8
+ if($pagenow == 'post.php' || $pagenow == 'post-new.php' ){ //only needed if editing post
9
+ add_action('admin_head', array('EM_Event_Post_Admin','admin_head'));
10
+ //Meta Boxes
11
+ add_action('add_meta_boxes', array('EM_Event_Post_Admin','meta_boxes'));
12
+ //Notices
13
+ add_action('admin_notices',array('EM_Event_Post_Admin','admin_notices'));
14
+ }
15
+ //Save/Edit actions
16
+ add_action('save_post',array('EM_Event_Post_Admin','save_post'),10,1);
17
+ add_action('before_delete_post',array('EM_Event_Post_Admin','before_delete_post'),10,1);
18
+ add_action('trashed_post',array('EM_Event_Post_Admin','trashed_post'),10,1);
19
+ add_action('untrash_post',array('EM_Event_Post_Admin','untrash_post'),10,1);
20
+ add_action('untrashed_post',array('EM_Event_Post_Admin','untrashed_post'),10,1);
21
+ //Notices
22
+ add_action('post_updated_messages',array('EM_Event_Post_Admin','admin_notices_filter'),1,1);
23
+ }
24
+
25
+ function admin_head(){
26
+ global $post, $EM_Event;
27
+ if( !empty($post) && $post->post_type == EM_POST_TYPE_EVENT ){
28
+ $EM_Event = em_get_event($post->ID, 'post_id');
29
+ }
30
+ }
31
+
32
+ function admin_notices(){
33
+ //When editing
34
+ global $post, $EM_Event, $pagenow;
35
+ if( $pagenow == 'post.php' && ($post->post_type == EM_POST_TYPE_EVENT || $post->post_type == 'event-recurring') ){
36
+ if ( $EM_Event->is_recurring() ) {
37
+ $warning = "<p><strong>".__( 'WARNING: This is a recurring event.', 'dbem' )."</strong></p>";
38
+ $warning .= "<p>". __( 'Modifications to this event will cause all recurrences of this event to be deleted and recreated and previous bookings will be deleted! You can edit individual recurrences and disassociate them with this recurring event.', 'dbem' );
39
+ ?><div class="updated"><?php echo $warning; ?></div><?php
40
+ } elseif ( $EM_Event->is_recurrence() ) {
41
+ $warning = "<p><strong>".__('WARNING: This is a recurrence in a set of recurring events.', 'dbem')."</strong></p>";
42
+ $warning .= "<p>". sprintf(__('If you update this event data and save, it could get overwritten if you edit the recurring event template. To make it an independent, <a href="%s">detach it</a>.', 'dbem' ), $EM_Event->get_detach_url())."</p>";
43
+ $warning .= "<p>".sprintf(__('To manage the whole set, <a href="%s">edit the recurring event template</a>.', 'dbem'),admin_url().'post.php?action=edit&amp;post='.$EM_Event->recurrence_id)."</p>";
44
+ ?><div class="updated"><?php echo $warning; ?></div><?php
45
+ }
46
+ if( !empty($EM_Event->group_id) && function_exists('groups_get_group') ){
47
+ $group = groups_get_group(array('group_id'=>$EM_Event->group_id));
48
+ $warning = sprintf(__('WARNING: This is a event belonging to the group "%s". Other group admins can also modify this event.', 'dbem'), $group->name);
49
+ ?><div class="updated"><p><?php echo $warning; ?></p></div><?php
50
+ }
51
+ }
52
+ }
53
+
54
+ function admin_notices_filter($messages){
55
+ //When editing
56
+ global $post, $EM_Notices;
57
+ if( $post->post_type == EM_POST_TYPE_EVENT || $post->post_type == 'event-recurring' ){
58
+ if ( $EM_Notices->count_errors() > 0 ) {
59
+ unset($_GET['message']);
60
+ }
61
+ }
62
+ return $messages;
63
+ }
64
+
65
+ function save_post($post_id){
66
+ global $wpdb, $EM_Event, $EM_Location, $EM_Notices;
67
+ $post_type = get_post_type($post_id);
68
+ $is_post_type = $post_type == EM_POST_TYPE_EVENT || $post_type == 'event-recurring';
69
+ $saving_status = !in_array(get_post_status($post_id), array('trash','auto-draft')) && !defined('DOING_AUTOSAVE');
70
+ if(!defined('UNTRASHING_'.$post_id) && $is_post_type && $saving_status ){
71
+ if( wp_verify_nonce($_REQUEST['_emnonce'], 'edit_event') ){
72
+ //this is only run if we know form data was submitted, hence the nonce
73
+ do_action('em_event_save_pre', $EM_Event); //technically, the event is saved... but the meta isn't. wp doesn't give an pre-intervention action for this (or does it?)
74
+ $EM_Event = em_get_event($post_id, 'post_id');
75
+ //Handle Errors by making post draft
76
+ $get_meta = $EM_Event->get_post_meta();
77
+ $save_meta = $EM_Event->save_meta();
78
+ if( !$get_meta || !$save_meta ){
79
+ //failed somewhere, set to draft, don't publish
80
+ $EM_Event->set_status(null, true);
81
+ if( $EM_Event->is_recurring() ){
82
+ $EM_Notices->add_error( '<strong>'.__('Your event details are incorrect and recurrences cannot be created, please correct these errors first:','dbem').'</strong>', true); //Always seems to redirect, so we make it static
83
+ }else{
84
+ $EM_Notices->add_error( '<strong>'.sprintf(__('Your %s details are incorrect and cannot be published, please correct these errors first:','dbem'),__('event','dbem')).'</strong>', true); //Always seems to redirect, so we make it static
85
+ }
86
+ $EM_Notices->add_error($EM_Event->get_errors(), true); //Always seems to redirect, so we make it static
87
+ apply_filters('em_event_save', false, $EM_Event);
88
+ }else{
89
+ //if this is just published, we need to email the user about the publication, or send to pending mode again for review
90
+ if( (!$EM_Event->is_recurring() && !current_user_can('publish_events')) || ($EM_Event->is_recurring() && !current_user_can('publish_recurring_events')) ){
91
+ if( $EM_Event->is_published() ){ $EM_Event->set_status(0, true); } //no publishing and editing... security threat
92
+ }else{
93
+ $EM_Event->send_approval_notification();
94
+ }
95
+ apply_filters('em_event_save', true, $EM_Event);
96
+ }
97
+ }else{
98
+ //we're updating only the quick-edit style information, which is only post info saved into the index
99
+ $EM_Event = em_get_event($post_id, 'post_id'); //grab event, via post info
100
+ if( $EM_Event->validate() ){
101
+ //we can save the status now
102
+ $event_status = $EM_Event->get_status(true);
103
+ //if this is just published, we need to email the user about the publication, or send to pending mode again for review
104
+ if( (!$EM_Event->is_recurring() && !current_user_can('publish_events')) || ($EM_Event->is_recurring() && !current_user_can('publish_recurring_events')) ){
105
+ if( $EM_Event->is_published() ){ $EM_Event->set_status(0, true); } //no publishing and editing... security threat
106
+ }else{
107
+ $EM_Event->previous_status = $EM_Event->get_previous_status(); //save previous status into object before approving
108
+ $EM_Event->send_approval_notification();
109
+ }
110
+ //now update the db
111
+ $wpdb->query("UPDATE ".EM_EVENTS_TABLE." SET event_name='{$EM_Event->event_name}', event_slug='{$EM_Event->event_slug}', event_status={$event_status}, event_private={$EM_Event->event_private} WHERE event_id='{$EM_Event->event_id}'");
112
+ if( $EM_Event->is_recurring() && $EM_Event->is_published()){
113
+ //recurrences are (re)saved only if event is published
114
+ $EM_Event->save_events();
115
+ }
116
+ apply_filters('em_event_save', true, $EM_Event);
117
+ }else{
118
+ //Event doesn't validate, so set status to null
119
+ $EM_Event->set_status(null, true);
120
+ apply_filters('em_event_save', false, $EM_Event);
121
+ }
122
+ }
123
+ self::maybe_publish_location($EM_Event);
124
+ }
125
+ }
126
+
127
+ /**
128
+ * Publish the location if the event has just been approved and the location is pending. We assume an editor published the event and approves the location too.
129
+ * @param EM_Event $EM_Event
130
+ */
131
+ function maybe_publish_location($EM_Event){
132
+ //do a dirty update for location too if it's not published
133
+ if( $EM_Event->is_published() && !empty($EM_Event->location_id) ){
134
+ $EM_Location = $EM_Event->get_location();
135
+ if( $EM_Location->location_status !== 1 ){
136
+ //let's also publish the location
137
+ $EM_Location->set_status(1);
138
+ }
139
+ }
140
+ }
141
+
142
+ function before_delete_post($post_id){
143
+ if(get_post_type($post_id) == EM_POST_TYPE_EVENT){
144
+ $EM_Event = em_get_event($post_id,'post_id');
145
+ $EM_Event->delete_meta();
146
+ }
147
+ }
148
+
149
+ function trashed_post($post_id){
150
+ if(get_post_type($post_id) == EM_POST_TYPE_EVENT){
151
+ global $EM_Notices;
152
+ $EM_Event = em_get_event($post_id,'post_id');
153
+ $EM_Event->set_status(null);
154
+ $EM_Notices->remove_all(); //no validation/notices needed
155
+ }
156
+ }
157
+
158
+ function untrash_post($post_id){
159
+ if(get_post_type($post_id) == EM_POST_TYPE_EVENT){
160
+ //set a constant so we know this event doesn't need 'saving'
161
+ if(!defined('UNTRASHING_'.$post_id)) define('UNTRASHING_'.$post_id, true);
162
+ }
163
+ }
164
+
165
+ function untrashed_post($post_id){
166
+ if(get_post_type($post_id) == EM_POST_TYPE_EVENT){
167
+ global $EM_Notices;
168
+ $EM_Event = em_get_event($post_id,'post_id');
169
+
170
+ $EM_Event->set_status(1);
171
+ $EM_Notices->remove_all(); //no validation/notices needed
172
+ }
173
+ }
174
+
175
+ function meta_boxes(){
176
+ global $EM_Event;
177
+ add_meta_box('em-event-when', __('When','dbem'), array('EM_Event_Post_Admin','meta_box_date'),EM_POST_TYPE_EVENT, 'side','high');
178
+ if(get_option('dbem_locations_enabled', true)){
179
+ add_meta_box('em-event-where', __('Where','dbem'), array('EM_Event_Post_Admin','meta_box_location'),EM_POST_TYPE_EVENT, 'normal','high');
180
+ }
181
+ //add_meta_box('em-event-meta', 'Event Meta (debugging only)', array('EM_Event_Post_Admin','meta_box_metadump'),EM_POST_TYPE_EVENT, 'normal','high');
182
+ if(get_option('dbem_rsvp_enabled', true)){
183
+ add_meta_box('em-event-bookings', __('Bookings/Registration','dbem'), array('EM_Event_Post_Admin','meta_box_bookings'),EM_POST_TYPE_EVENT, 'normal','high');
184
+ if( !empty($EM_Event->event_id) && $EM_Event->event_rsvp ){
185
+ add_meta_box('em-event-bookings-stats', __('Bookings Stats','dbem'), array('EM_Event_Post_Admin','meta_box_bookings_stats'),EM_POST_TYPE_EVENT, 'side','core');
186
+ }
187
+ }
188
+ if( get_option('dbem_attributes_enabled', true) ){
189
+ add_meta_box('em-event-attributes', __('Attributes','dbem'), array('EM_Event_Post_Admin','meta_box_attributes'),EM_POST_TYPE_EVENT, 'normal','default');
190
+ }
191
+ if( (empty($EM_Event->id) || !empty($EM_Event->group_id)) && function_exists('groups_get_user_groups') ){
192
+ add_meta_box('em-event-group', __('Group Ownership','dbem'), array('EM_Event_Post_Admin','meta_box_group'),EM_POST_TYPE_EVENT, 'side','low');
193
+ }
194
+ if( EM_MS_GLOBAL && !is_main_site() && get_option('dbem_categories_enabled') ){
195
+ add_meta_box('em-event-categories', __('Site Categories','dbem'), array('EM_Event_Post_Admin','meta_box_ms_categories'),EM_POST_TYPE_EVENT, 'side','low');
196
+ }
197
+ }
198
+ function meta_box_metadump(){
199
+ global $post,$EM_Event;
200
+ echo "<pre>"; print_r($EM_Event); echo "</pre>";
201
+ }
202
+ function meta_box_date(){
203
+ //create meta box check of date nonce
204
+ ?><input type="hidden" name="_emnonce" value="<?php echo wp_create_nonce('edit_event'); ?>" /><?php
205
+ em_locate_template('forms/event/when.php', true);
206
+ }
207
+
208
+ function meta_box_bookings_stats(){
209
+ em_locate_template('forms/event/booking-stats.php',true);
210
+ }
211
+
212
+ function meta_box_bookings(){
213
+ em_locate_template('forms/event/bookings.php', true);
214
+ if( !get_option('dbem_bookings_tickets_single') ){
215
+ add_action('admin_footer',array('EM_Event_Post_Admin','meta_box_bookings_overlay'));
216
+ }
217
+ }
218
+
219
+ function meta_box_bookings_overlay(){
220
+ em_locate_template('forms/tickets-form.php', true); //put here as it can't be in the add event form
221
+ }
222
+
223
+ function meta_box_attributes(){
224
+ em_locate_template('forms/event/attributes.php',true);
225
+ }
226
+
227
+ function meta_box_group(){
228
+ em_locate_template('forms/event/group.php',true);
229
+ }
230
+
231
+ function meta_box_location(){
232
+ em_locate_template('forms/event/location.php',true);
233
+ }
234
+
235
+ function meta_box_ms_categories(){
236
+ global $EM_Event;
237
+ $categories = EM_Categories::get(array('orderby'=>'category_name','hide_empty'=>false));
238
+ ?>
239
+ <?php if( count($categories) > 0 ): ?>
240
+ <p>
241
+ <?php foreach( $categories as $EM_Category ):?>
242
+ <label><input type="checkbox" name="event_categories[]" value="<?php echo $EM_Category->id; ?>" <?php if($EM_Event->get_categories()->has($EM_Category->id)) echo 'checked="checked"'; ?> /> <?php echo $EM_Category->name ?></label><br />
243
+ <?php endforeach; ?>
244
+ </p>
245
+ <?php else: ?>
246
+ <p><?php sprintf(__('No categories available, <a href="%s">create one here first</a>','dbem'), get_bloginfo('wpurl').'/wp-admin/admin.php?page=events-manager-categories'); ?></p>
247
+ <?php endif; ?>
248
+ <!-- END Categories -->
249
+ <?php
250
+ }
251
+ }
252
+ add_action('admin_init',array('EM_Event_Post_Admin','init'));
253
+
254
+ /*
255
+ * Recurring Events
256
+ */
257
+ class EM_Event_Recurring_Post_Admin{
258
+ function init(){
259
+ global $pagenow;
260
+ if($pagenow == 'post.php' || $pagenow == 'post-new.php' ){ //only needed if editing post
261
+ add_action('admin_head', array('EM_Event_Recurring_Post_Admin','admin_head'));
262
+ //Meta Boxes
263
+ add_action('add_meta_boxes', array('EM_Event_Recurring_Post_Admin','meta_boxes'));
264
+ //Notices
265
+ add_action('admin_notices',array('EM_Event_Post_Admin','admin_notices')); //shared with posts
266
+ }
267
+ //Save/Edit actions
268
+ add_action('before_delete_post',array('EM_Event_Recurring_Post_Admin','before_delete_post'),10,1);
269
+ add_action('trashed_post',array('EM_Event_Recurring_Post_Admin','trashed_post'),10,1);
270
+ add_action('untrash_post',array('EM_Event_Recurring_Post_Admin','untrash_post'),10,1);
271
+ add_action('untrashed_post',array('EM_Event_Recurring_Post_Admin','untrashed_post'),10,1);
272
+ //Notices
273
+ add_action('post_updated_messages',array('EM_Event_Post_Admin','admin_notices_filter'),1,1); //shared with posts
274
+ }
275
+
276
+ function admin_head(){
277
+ global $post, $EM_Event;
278
+ if( !empty($post) && $post->post_type == 'event-recurring' ){
279
+ $EM_Event = em_get_event($post->ID, 'post_id');
280
+ //quick hacks to make event admin table make more sense for events
281
+ ?>
282
+ <script type="text/javascript">
283
+ jQuery(document).ready( function($){
284
+ if(!EM.recurrences_menu){
285
+ $('#menu-posts-'+EM.event_post_type+', #menu-posts-'+EM.event_post_type+' > a').addClass('wp-has-current-submenu');
286
+ }
287
+ });
288
+ </script>
289
+ <?php
290
+ }
291
+ }
292
+
293
+ function before_delete_post($post_id){
294
+ if(get_post_type($post_id) == 'event-recurring'){
295
+ $EM_Event = em_get_event($post_id,'post_id');
296
+ //now delete recurrences
297
+ $events_array = EM_Events::get( array('recurrence'=>$EM_Event->event_id, 'scope'=>'all', 'status'=>false ) );
298
+ foreach($events_array as $event){
299
+ /* @var $event EM_Event */
300
+ if($EM_Event->event_id == $event->recurrence_id ){ //double check the event is a recurrence of this event
301
+ wp_delete_post($event->post_id, true);
302
+ }
303
+ }
304
+ $EM_Event->post_type = EM_POST_TYPE_EVENT; //trick it into thinking it's one event.
305
+ $EM_Event->delete_meta();
306
+ }
307
+ }
308
+
309
+ function trashed_post($post_id){
310
+ if(get_post_type($post_id) == 'event-recurring'){
311
+ global $EM_Notices, $wpdb;
312
+ $EM_Event = em_get_event($post_id,'post_id');
313
+ $EM_Event->set_status(null);
314
+ //now trash recurrences
315
+ $events_array = EM_Events::get( array('recurrence_id'=>$EM_Event->event_id, 'scope'=>'all', 'status'=>false ) );
316
+ foreach($events_array as $event){
317
+ /* @var $event EM_Event */
318
+ if($EM_Event->event_id == $event->recurrence_id ){ //double check the event is a recurrence of this event
319
+ wp_trash_post($event->post_id);
320
+ }
321
+ }
322
+ $EM_Notices->remove_all(); //no validation/notices needed
323
+ }
324
+ }
325
+
326
+ function untrash_post($post_id){
327
+ if(get_post_type($post_id) == 'event-recurring'){
328
+ global $wpdb;
329
+ //set a constant so we know this event doesn't need 'saving'
330
+ if(!defined('UNTRASHING_'.$post_id)) define('UNTRASHING_'.$post_id, true);
331
+ $EM_Event = em_get_event($post_id,'post_id');
332
+ $wpdb->query('UPDATE '.EM_EVENTS_TABLE.' SET event_status='.$EM_Event->event_status.' WHERE event_id='.$EM_Event->event_id);
333
+ $events_array = EM_Events::get( array('recurrence_id'=>$EM_Event->event_id, 'scope'=>'all', 'status'=>false ) );
334
+ foreach($events_array as $event){
335
+ /* @var $event EM_Event */
336
+ if($EM_Event->event_id == $event->recurrence_id){
337
+ wp_untrash_post($event->post_id);
338
+ }
339
+ }
340
+ }
341
+ }
342
+
343
+ function untrashed_post($post_id){
344
+ if(get_post_type($post_id) == 'event-recurring'){
345
+ global $EM_Notices;
346
+ $EM_Notices->remove_all(); //no validation/notices needed
347
+ }
348
+ }
349
+
350
+ function meta_boxes(){
351
+ add_meta_box('em-event-recurring', __('Recurrences','dbem'), array('EM_Event_Recurring_Post_Admin','meta_box_recurrence'),'event-recurring', 'normal','high');
352
+ //add_meta_box('em-event-meta', 'Event Meta (debugging only)', array('EM_Event_Post_Admin','meta_box_metadump'),'event-recurring', 'normal','high');
353
+ add_meta_box('em-event-where', __('Where','dbem'), array('EM_Event_Post_Admin','meta_box_location'),'event-recurring', 'normal','high');
354
+ if(get_option('dbem_rsvp_enabled')){
355
+ add_meta_box('em-event-bookings', __('Bookings/Registration','dbem'), array('EM_Event_Post_Admin','meta_box_bookings'),'event-recurring', 'normal','high');
356
+ }
357
+ if( empty($EM_Event->id) && function_exists('groups_get_user_groups') ){
358
+ add_meta_box('em-event-group', __('Group Ownership','dbem'), array('EM_Event_Post_Admin','meta_box_group'),'event-recurring', 'side','low');
359
+ }
360
+ if( get_option('dbem_attributes_enabled') ){
361
+ add_meta_box('em-event-attributes', __('Attributes','dbem'), array('EM_Event_Post_Admin','meta_box_attributes'),'event-recurring', 'normal','default');
362
+ }
363
+ if( (empty($EM_Event->id) || !empty($EM_Event->group_id)) && function_exists('groups_get_user_groups') ){
364
+ add_meta_box('em-event-group', __('Group Ownership','dbem'), array('EM_Event_Post_Admin','meta_box_group'),'event-recurring', 'side','low');
365
+ }
366
+ }
367
+
368
+ function meta_box_recurrence(){
369
+ em_locate_template('forms/event/recurring-when.php', true);
370
+ }
371
+ }
372
+ add_action('admin_init',array('EM_Event_Recurring_Post_Admin','init'));
classes/em-event-post.php ADDED
@@ -0,0 +1,250 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Controls how events are queried and displayed via the WordPress Custom Post APIs
4
+ * @author marcus
5
+ *
6
+ */
7
+ class EM_Event_Post {
8
+ function init(){
9
+ global $wp_query;
10
+ //Front Side Modifiers
11
+ if( !is_admin() ){
12
+ //override single page with formats?
13
+ add_filter('the_content', array('EM_Event_Post','the_content'));
14
+ //display as page template?
15
+ if( get_option('dbem_cp_events_template_page') ){
16
+ add_filter('single_template',array('EM_Event_Post','single_template'));
17
+ }
18
+ //Override post template tags
19
+ add_filter('the_date',array('EM_Event_Post','the_date'));
20
+ add_filter('get_the_date',array('EM_Event_Post','the_date'),10,2);
21
+ add_filter('the_category',array('EM_Event_Post','the_category'),10,3);
22
+ }
23
+ add_action('parse_query', array('EM_Event_Post','parse_query'));
24
+ }
25
+
26
+ /**
27
+ * Overrides the default post format of an event and can display an event as a page, which uses the page.php template.
28
+ * @param string $template
29
+ * @return string
30
+ */
31
+ function single_template($template){
32
+ global $post;
33
+ if( $post->post_type == EM_POST_TYPE_EVENT ){
34
+ $template = locate_template(array('page.php','index.php'),false);
35
+ }
36
+ return $template;
37
+ }
38
+
39
+ function the_content( $content ){
40
+ global $post, $EM_Event;
41
+ if( $post->post_type == EM_POST_TYPE_EVENT ){
42
+ if( is_archive() || is_search() ){
43
+ if(get_option('dbem_cp_events_archive_formats')){
44
+ $EM_Event = em_get_event($post);
45
+ $content = $EM_Event->output(get_option('dbem_event_list_item_format'));
46
+ }
47
+ }else{
48
+ if( get_option('dbem_cp_events_formats') && !post_password_required() ){
49
+ $EM_Event = em_get_event($post);
50
+ //general defaults
51
+ $args = array(
52
+ 'owner' => false,
53
+ 'pagination' => 1
54
+ );
55
+ ob_start();
56
+ em_locate_template('templates/event-single.php',true, array('args'=>$args));
57
+ $content = ob_get_clean();
58
+ }
59
+ }
60
+ }
61
+ return $content;
62
+ }
63
+
64
+ function the_date( $the_date, $d = '' ){
65
+ global $post;
66
+ if( $post->post_type == EM_POST_TYPE_EVENT ){
67
+ $EM_Event = em_get_event($post);
68
+ if ( '' == $d ){
69
+ $the_date = date(get_option('date_format'), $EM_Event->start);
70
+ }else{
71
+ $the_date = date($d, $EM_Event->start);
72
+ }
73
+ }
74
+ return $the_date;
75
+ }
76
+
77
+ function the_category( $thelist, $separator = '', $parents='' ){
78
+ global $post, $wp_rewrite;
79
+ if( $post->post_type == EM_POST_TYPE_EVENT ){
80
+ $EM_Event = em_get_event($post);
81
+ $categories = $EM_Event->get_categories();
82
+ if( empty($categories) ) return '';
83
+
84
+ /* Copied from get_the_category_list function, with a few minor edits to make urls work, and removing parent stuff (for now) */
85
+ $rel = ( is_object( $wp_rewrite ) && $wp_rewrite->using_permalinks() ) ? 'rel="category tag"' : 'rel="category"';
86
+
87
+ $thelist = '';
88
+ if ( '' == $separator ) {
89
+ $thelist .= '<ul class="post-categories">';
90
+ foreach ( $categories as $category ) {
91
+ $thelist .= "\n\t<li>";
92
+ switch ( strtolower( $parents ) ) {
93
+ case 'multiple':
94
+ $thelist .= '<a href="' . $category->get_url() . '" title="' . esc_attr( sprintf( __( "View all posts in %s" ), $category->name ) ) . '" ' . $rel . '>' . $category->name.'</a></li>';
95
+ break;
96
+ case 'single':
97
+ $thelist .= '<a href="' . $category->get_url() . '" title="' . esc_attr( sprintf( __( "View all posts in %s" ), $category->name ) ) . '" ' . $rel . '>';
98
+ $thelist .= $category->name.'</a></li>';
99
+ break;
100
+ case '':
101
+ default:
102
+ $thelist .= '<a href="' . $category->get_url() . '" title="' . esc_attr( sprintf( __( "View all posts in %s" ), $category->name ) ) . '" ' . $rel . '>' . $category->name.'</a></li>';
103
+ }
104
+ }
105
+ $thelist .= '</ul>';
106
+ } else {
107
+ $i = 0;
108
+ foreach ( $categories as $category ) {
109
+ if ( 0 < $i )
110
+ $thelist .= $separator;
111
+ switch ( strtolower( $parents ) ) {
112
+ case 'multiple':
113
+ $thelist .= '<a href="' . $category->get_url() . '" title="' . esc_attr( sprintf( __( "View all posts in %s" ), $category->name ) ) . '" ' . $rel . '>' . $category->name.'</a>';
114
+ break;
115
+ case 'single':
116
+ $thelist .= '<a href="' . $category->get_url() . '" title="' . esc_attr( sprintf( __( "View all posts in %s" ), $category->name ) ) . '" ' . $rel . '>';
117
+ $thelist .= "$category->name</a>";
118
+ break;
119
+ case '':
120
+ default:
121
+ $thelist .= '<a href="' . $category->get_url() . '" title="' . esc_attr( sprintf( __( "View all posts in %s" ), $category->name ) ) . '" ' . $rel . '>' . $category->name.'</a>';
122
+ }
123
+ ++$i;
124
+ }
125
+ }
126
+ /* End copying */
127
+ }
128
+ return $thelist;
129
+ }
130
+
131
+ function parse_query( ){
132
+ global $wp_query;
133
+ if( ($wp_query->query_vars['post_type'] == EM_POST_TYPE_EVENT || $wp_query->query_vars['post_type'] == 'event-recurring') && !in_array($wp_query->query_vars['post_status'],array('trash','pending','draft'))) {
134
+ //Let's deal with the scope - default is future
135
+ if( is_admin() ){
136
+ $scope = $wp_query->query_vars['scope'] = (!empty($_REQUEST['scope'])) ? $_REQUEST['scope']:'future';
137
+ //TODO limit what a user can see admin side for events/locations/recurring events
138
+ }else{
139
+ if( empty($wp_query->query_vars['scope']) ){
140
+ if( is_archive() ){
141
+ $scope = $wp_query->query_vars['scope'] = get_option('dbem_events_page_scope');
142
+ }else{
143
+ $scope = $wp_query->query_vars['scope'] = 'all'; //otherwise we'll get 404s for past events
144
+ }
145
+ }else{
146
+ $scope = $wp_query->query_vars['scope'];
147
+ }
148
+ }
149
+ $query = array();
150
+ $time = current_time('timestamp');
151
+ if ( preg_match ( "/^[0-9]{4}-[0-9]{2}-[0-9]{2}$/", $scope ) ) {
152
+ $today = strtotime($scope);
153
+ $tomorrow = $today + 60*60*24-1;
154
+ if( get_option('dbem_events_current_are_past') && $wp_query->query_vars['post_type'] != 'event-recurring' ){
155
+ $query[] = array( 'key' => '_start_ts', 'value' => array($today,$tomorrow), 'compare' => 'BETWEEN' );
156
+ }else{
157
+ $query[] = array( 'key' => '_start_ts', 'value' => $tomorrow, 'compare' => '<=' );
158
+ $query[] = array( 'key' => '_end_ts', 'value' => $today, 'compare' => '>=' );
159
+ }
160
+ }elseif ($scope == "future"){
161
+ $today = strtotime(date('Y-m-d', $time));
162
+ if( get_option('dbem_events_current_are_past') && $wp_query->query_vars['post_type'] != 'event-recurring' ){
163
+ $query[] = array( 'key' => '_start_ts', 'value' => $today, 'compare' => '>=' );
164
+ }else{
165
+ $query[] = array( 'key' => '_end_ts', 'value' => $today, 'compare' => '>=' );
166
+ }
167
+ }elseif ($scope == "past"){
168
+ $today = strtotime(date('Y-m-d', $time));
169
+ if( get_option('dbem_events_current_are_past') && $wp_query->query_vars['post_type'] != 'event-recurring' ){
170
+ $query[] = array( 'key' => '_start_ts', 'value' => $today, 'compare' => '<' );
171
+ }else{
172
+ $query[] = array( 'key' => '_end_ts', 'value' => $today, 'compare' => '<' );
173
+ }
174
+ }elseif ($scope == "today"){
175
+ $today = strtotime(date('Y-m-d', $time));
176
+ if( get_option('dbem_events_current_are_past') && $wp_query->query_vars['post_type'] != 'event-recurring' ){
177
+ //date must be only today
178
+ $query[] = array( 'key' => '_start_ts', 'value' => $today, 'compare' => '=');
179
+ }else{
180
+ $query[] = array( 'key' => '_start_ts', 'value' => $today, 'compare' => '<=' );
181
+ $query[] = array( 'key' => '_end_ts', 'value' => $today, 'compare' => '>=' );
182
+ }
183
+ }elseif ($scope == "tomorrow"){
184
+ $tomorrow = strtotime(date('Y-m-d',$time+60*60*24));
185
+ if( get_option('dbem_events_current_are_past') && $wp_query->query_vars['post_type'] != 'event-recurring' ){
186
+ //date must be only tomorrow
187
+ $query[] = array( 'key' => '_start_ts', 'value' => $tomorrow, 'compare' => '=');
188
+ }else{
189
+ $query[] = array( 'key' => '_start_ts', 'value' => $tomorrow, 'compare' => '<=' );
190
+ $query[] = array( 'key' => '_end_ts', 'value' => $tomorrow, 'compare' => '>=' );
191
+ }
192
+ }elseif ($scope == "month"){
193
+ $start_month = strtotime(date('Y-m-d',$time));
194
+ $end_month = strtotime(date('Y-m-t',$time));
195
+ if( get_option('dbem_events_current_are_past') && $wp_query->query_vars['post_type'] != 'event-recurring' ){
196
+ $query[] = array( 'key' => '_start_ts', 'value' => array($start_month,$end_month), 'type' => 'numeric', 'compare' => 'BETWEEN');
197
+ }else{
198
+ $query[] = array( 'key' => '_start_ts', 'value' => $end_month, 'compare' => '<=' );
199
+ $query[] = array( 'key' => '_end_ts', 'value' => $start_month, 'compare' => '>=' );
200
+ }
201
+ }elseif ($scope == "next-month"){
202
+ $start_month_timestamp = strtotime('+1 month', $time); //get the end of this month + 1 day
203
+ $start_month = strtotime(date('Y-m-1',$start_month_timestamp));
204
+ $end_month = strtotime(date('Y-m-t',$start_month_timestamp));
205
+ if( get_option('dbem_events_current_are_past') && $wp_query->query_vars['post_type'] != 'event-recurring' ){
206
+ $query[] = array( 'key' => '_start_ts', 'value' => array($start_month,$end_month), 'type' => 'numeric', 'compare' => 'BETWEEN');
207
+ }else{
208
+ $query[] = array( 'key' => '_start_ts', 'value' => $end_month, 'compare' => '<=' );
209
+ $query[] = array( 'key' => '_end_ts', 'value' => $start_month, 'compare' => '>=' );
210
+ }
211
+ }elseif( preg_match('/(\d\d?)\-months/',$scope,$matches) ){ // next x months means this month (what's left of it), plus the following x months until the end of that month.
212
+ $months_to_add = $matches[1];
213
+ $start_month = strtotime(date('Y-m-d',$time));
214
+ $end_month = strtotime(date('Y-m-t',strtotime("+$months_to_add month", $time)));
215
+ if( get_option('dbem_events_current_are_past') && $wp_query->query_vars['post_type'] != 'event-recurring' ){
216
+ $query[] = array( 'key' => '_start_ts', 'value' => array($start_month,$end_month), 'type' => 'numeric', 'compare' => 'BETWEEN');
217
+ }else{
218
+ $query[] = array( 'key' => '_start_ts', 'value' => $end_month, 'compare' => '<=' );
219
+ $query[] = array( 'key' => '_end_ts', 'value' => $start_month, 'compare' => '>=' );
220
+ }
221
+ }
222
+ if( !empty($query) && is_array($query) ){
223
+ $wp_query->query_vars['meta_query'] = $query;
224
+ }
225
+ if( is_admin() ){
226
+ //admin areas don't need special ordering, so make it simple
227
+ $wp_query->query_vars['orderby'] = (!empty($_REQUEST['orderby'])) ? $_REQUEST['orderby']:'meta_value_num';
228
+ $wp_query->query_vars['meta_key'] = '_start_ts';
229
+ $wp_query->query_vars['order'] = (!empty($_REQUEST['order'])) ? $_REQUEST['order']:'ASC';
230
+ }else{
231
+ if( get_option('dbem_events_default_archive_orderby') == 'title'){
232
+ $wp_query->query_vars['orderby'] = 'title';
233
+ $wp_query->query_vars['order'] = get_option('dbem_events_default_archive_orderby','ASC');
234
+ }else{
235
+ $wp_query->query_vars['orderby'] = 'meta_value_num';
236
+ $wp_query->query_vars['meta_key'] = '_start_ts';
237
+ }
238
+ $wp_query->query_vars['order'] = get_option('dbem_events_default_archive_orderby','ASC');
239
+ }
240
+ }elseif( $wp_query->query_vars['post_type'] == EM_POST_TYPE_EVENT ){
241
+ $wp_query->query_vars['scope'] = 'all';
242
+ if( $wp_query->query_vars['post_status'] == 'pending' ){
243
+ $wp_query->query_vars['orderby'] = 'meta_value_num';
244
+ $wp_query->query_vars['order'] = 'ASC';
245
+ $wp_query->query_vars['meta_key'] = '_start_ts';
246
+ }
247
+ }
248
+ }
249
+ }
250
+ EM_Event_Post::init();
classes/em-event-posts-admin.php ADDED
@@ -0,0 +1,243 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class EM_Event_Posts_Admin{
3
+ function init(){
4
+ global $pagenow;
5
+ if( $pagenow == 'edit.php' && !empty($_REQUEST['post_type']) && $_REQUEST['post_type'] == EM_POST_TYPE_EVENT ){ //only needed for events list
6
+ $row_action_type = is_post_type_hierarchical( EM_POST_TYPE_EVENT ) ? 'page_row_actions' : 'post_row_actions';
7
+ add_filter($row_action_type, array('EM_Event_Posts_Admin','row_actions'),10,2);
8
+ add_action('admin_head', array('EM_Event_Posts_Admin','admin_head'));
9
+ //collumns
10
+ add_filter('manage_edit-'.EM_POST_TYPE_EVENT.'_columns' , array('EM_Event_Posts_Admin','columns_add'));
11
+ add_filter('manage_'.EM_POST_TYPE_EVENT.'_posts_custom_column' , array('EM_Event_Posts_Admin','columns_output'),10,2 );
12
+ //TODO alter views of locations, events and recurrences, specifically find a good way to alter the wp_count_posts method to force user owned posts only
13
+ //add_filter('views_edit-'.EM_POST_TYPE_EVENT, array('EM_Event_Posts_Admin','views'),10,1);
14
+ }
15
+ add_action('restrict_manage_posts', array('EM_Event_Posts_Admin','restrict_manage_posts'));
16
+ }
17
+
18
+ function admin_head(){
19
+ //quick hacks to make event admin table make more sense for events
20
+ ?>
21
+ <script type="text/javascript">
22
+ jQuery(document).ready( function($){
23
+ $('.inline-edit-date').prev().css('display','none').next().css('display','none').next().css('display','none');
24
+ $('.em-detach-link').click(function( event ){
25
+ if( !confirm(EM.event_detach_warning) ){
26
+ event.preventDefault();
27
+ return false;
28
+ }
29
+ });
30
+ $('.em-delete-recurrence-link').click(function( event ){
31
+ if( !confirm(EM.delete_recurrence_warning) ){
32
+ event.preventDefault();
33
+ return false;
34
+ }
35
+ });
36
+ });
37
+ </script>
38
+ <style>
39
+ table.fixed{ table-layout:auto !important; }
40
+ .tablenav select[name="m"] { display:none; }
41
+ </style>
42
+ <?php
43
+ }
44
+
45
+ function restrict_manage_posts(){
46
+ global $wp_query;
47
+ if( $wp_query->query_vars['post_type'] == EM_POST_TYPE_EVENT || $wp_query->query_vars['post_type'] == 'event-recurring' ){
48
+ ?>
49
+ <select name="scope">
50
+ <?php
51
+ $scope = (!empty($wp_query->query_vars['scope'])) ? $wp_query->query_vars['scope']:'future';
52
+ foreach ( em_get_scopes() as $key => $value ) {
53
+ $selected = "";
54
+ if ($key == $scope)
55
+ $selected = "selected='selected'";
56
+ echo "<option value='$key' $selected>$value</option> ";
57
+ }
58
+ ?>
59
+ </select>
60
+ <?php
61
+ if( get_option('dbem_categories_enabled') ){
62
+ //Categories
63
+ $terms = get_terms(EM_TAXONOMY_CATEGORY);
64
+ // output html for taxonomy dropdown filter
65
+ echo '<select name="'.EM_TAXONOMY_CATEGORY.'" id="'.EM_TAXONOMY_CATEGORY.'" class="postform">';
66
+ echo '<option value="">'.__('View all categories').'&nbsp;</option>';
67
+ foreach ($terms as $term) {
68
+ // output each select option line, check against the last $_GET to show the current option selected
69
+ $selected = (!empty($_GET[EM_TAXONOMY_CATEGORY]) && $_GET[EM_TAXONOMY_CATEGORY] == $term->slug) ? 'selected="selected"':'';
70
+ echo '<option value="'. $term->slug.'" '.$selected.'>'.$term->name.'</option>';
71
+ }
72
+ echo "</select>";
73
+ }
74
+ if( !empty($_REQUEST['author']) ){
75
+ ?>
76
+ <input type="hidden" name="author" value="<?php echo $_REQUEST['author'] ?>" />
77
+ <?php
78
+ }
79
+ }
80
+ }
81
+
82
+ function views($views){
83
+ if( !current_user_can('edit_others_events') ){
84
+ //alter the views to reflect correct numbering
85
+
86
+ }
87
+ return $views;
88
+ }
89
+
90
+ function columns_add($columns) {
91
+ unset($columns['comments']);
92
+ unset($columns['date']);
93
+ unset($columns['author']);
94
+ $columns = array_merge($columns, array(
95
+ 'location' => __('Location'),
96
+ 'date-time' => __('Date and Time'),
97
+ 'author' => __('Owner','dbem'),
98
+ 'extra' => ''
99
+ ));
100
+ if( !get_option('dbem_locations_enabled') ){
101
+ unset($columns['location']);
102
+ }
103
+ return $columns;
104
+ }
105
+
106
+ function columns_output( $column ) {
107
+ global $post, $EM_Event;
108
+ $EM_Event = em_get_event($post, 'post_id');
109
+ /* @var $post EM_Event */
110
+ switch ( $column ) {
111
+ case 'location':
112
+ //get meta value to see if post has location, otherwise
113
+ $EM_Location = $EM_Event->get_location();
114
+ if( !empty($EM_Location->location_id) ){
115
+ echo "<strong>" . $EM_Location->location_name . "</strong><br/>" . $EM_Location->location_address . " - " . $EM_Location->location_town;
116
+ }else{
117
+ echo __('None','dbem');
118
+ }
119
+ break;
120
+ case 'date-time':
121
+ //get meta value to see if post has location, otherwise
122
+ $localised_start_date = date_i18n('D d M Y', $EM_Event->start);
123
+ $localised_end_date = date_i18n('D d M Y', $EM_Event->end);
124
+ echo $localised_start_date;
125
+ echo ($localised_end_date != $localised_start_date) ? " - $localised_end_date":'';
126
+ echo "<br />";
127
+ if(!$EM_Event->event_all_day){
128
+ echo substr ( $EM_Event->start_time, 0, 5 ) . " - " . substr ( $EM_Event->end_time, 0, 5 );
129
+ }else{
130
+ echo get_option('dbem_event_all_day_message');
131
+ }
132
+ break;
133
+ case 'extra':
134
+ if( get_option('dbem_rsvp_enabled') == 1 && $EM_Event->rsvp == 1 && $EM_Event->can_manage('manage_bookings','manage_others_bookings')){
135
+ ?>
136
+ <a href="<?php echo EM_ADMIN_URL; ?>&amp;page=events-manager-bookings&amp;event_id=<?php echo $EM_Event->id ?>"><?php echo __("Bookings",'dbem'); ?></a> &ndash;
137
+ <?php _e("Booked",'dbem'); ?>: <?php echo $EM_Event->get_bookings()->get_booked_spaces()."/".$EM_Event->get_spaces(); ?>
138
+ <?php if( get_option('dbem_bookings_approval') == 1 ): ?>
139
+ | <?php _e("Pending",'dbem') ?>: <?php echo $EM_Event->get_bookings()->get_pending_spaces(); ?>
140
+ <?php endif;
141
+ echo ($EM_Event->is_recurrence()) ? '<br />':'';
142
+ }
143
+ if ( $EM_Event->is_recurrence() && $EM_Event->can_manage('edit_recurring_events','edit_others_recurring_events') ) {
144
+ $recurrence_delete_confirm = __('WARNING! You will delete ALL recurrences of this event, including booking history associated with any event in this recurrence. To keep booking information, go to the relevant single event and save it to detach it from this recurrence series.','dbem');
145
+ ?>
146
+ <strong>
147
+ <?php echo $EM_Event->get_recurrence_description(); ?> <br />
148
+ </strong>
149
+ <div class="row-actions">
150
+ <a href="<?php echo admin_url(); ?>post.php?action=edit&amp;post=<?php echo $EM_Event->get_event_recurrence()->post_id ?>"><?php _e ( 'Reschedule Events', 'dbem' ); ?></a> | <span class="trash"><a class="em-delete-recurrence-link" href="<?php echo get_delete_post_link($EM_Event->get_event_recurrence()->post_id); ?>"><?php _e('Delete','dbem'); ?></a></span> | <a class="em-detach-link" href="<?php echo $EM_Event->get_detach_url(); ?>"><?php _e('Detach', 'dbem'); ?></a>
151
+ </div>
152
+ <?php
153
+ }
154
+
155
+ break;
156
+ }
157
+ }
158
+
159
+ function row_actions($actions, $post){
160
+ if($post->post_type == EM_POST_TYPE_EVENT){
161
+ global $post, $EM_Event;
162
+ $EM_Event = em_get_event($post, 'post_id');
163
+ $actions['duplicate'] = '<a href="'.admin_url().'edit.php?action=event_duplicate&amp;event_id='.$EM_Event->event_id.'" title="'.sprintf(__('Duplicate %s','dbem'), __('Event','dbem')).'">'.__('Duplicate','dbem').'</a>';
164
+ }
165
+ return $actions;
166
+ }
167
+ }
168
+ add_action('admin_init', array('EM_Event_Posts_Admin','init'));
169
+
170
+ /*
171
+ * Recurring Events
172
+ */
173
+ class EM_Event_Recurring_Posts_Admin{
174
+ function init(){
175
+ global $pagenow;
176
+ if( $pagenow == 'edit.php' && !empty($_REQUEST['post_type']) && $_REQUEST['post_type'] == 'event-recurring' ){
177
+ add_action('admin_notices',array('EM_Event_Recurring_Posts_Admin','admin_notices'));
178
+ add_action('admin_head', array('EM_Event_Recurring_Posts_Admin','admin_head'));
179
+ //collumns
180
+ add_filter('manage_edit-event-recurring_columns' , array('EM_Event_Recurring_Posts_Admin','columns_add'));
181
+ add_filter('manage_posts_custom_column' , array('EM_Event_Recurring_Posts_Admin','columns_output'),10,1 );
182
+ add_action('restrict_manage_posts', array('EM_Event_Posts_Admin','restrict_manage_posts'));
183
+ }
184
+ }
185
+
186
+ function admin_notices(){
187
+ $warning = sprintf(__( 'Modifications to these events will cause all recurrences of each event to be deleted and recreated and previous bookings will be deleted! You can edit individual recurrences and detach them from recurring events by visiting the <a href="%s">events page</a>.', 'dbem' ), admin_url().'edit.php?post_type='.EM_POST_TYPE_EVENT);
188
+ ?><div class="updated"><p><?php echo $warning; ?></p></div><?php
189
+ }
190
+
191
+ function admin_head(){
192
+ //quick hacks to make event admin table make more sense for events
193
+ ?>
194
+ <script type="text/javascript">
195
+ jQuery(document).ready( function($){
196
+ $('.inline-edit-date').prev().css('display','none').next().css('display','none').next().css('display','none');
197
+ if(!EM.recurrences_menu){
198
+ $('#menu-posts-'+EM.event_post_type+', #menu-posts-'+EM.event_post_type+' > a').addClass('wp-has-current-submenu');
199
+ }
200
+ });
201
+ </script>
202
+ <style>
203
+ table.fixed{ table-layout:auto !important; }
204
+ .tablenav select[name="m"] { display:none; }
205
+ </style>
206
+ <?php
207
+ }
208
+
209
+ function columns_add($columns) {
210
+ unset($columns['comments']);
211
+ unset($columns['date']);
212
+ unset($columns['author']);
213
+ return array_merge($columns, array(
214
+ 'location' => __('Location'),
215
+ 'date-time' => __('Date and Time'),
216
+ 'author' => __('Owner','dbem'),
217
+ ));
218
+ }
219
+
220
+
221
+ function columns_output( $column ) {
222
+ global $post, $EM_Event;
223
+ if( $post->post_type == 'event-recurring' ){
224
+ $post = $EM_Event = em_get_event($post);
225
+ /* @var $post EM_Event */
226
+ switch ( $column ) {
227
+ case 'location':
228
+ //get meta value to see if post has location, otherwise
229
+ $EM_Location = $EM_Event->get_location();
230
+ if( !empty($EM_Location->location_id) ){
231
+ echo "<strong>" . $EM_Location->location_name . "</strong><br/>" . $EM_Location->location_address . " - " . $EM_Location->location_town;
232
+ }else{
233
+ echo __('None','dbem');
234
+ }
235
+ break;
236
+ case 'date-time':
237
+ echo $EM_Event->get_recurrence_description();
238
+ break;
239
+ }
240
+ }
241
+ }
242
+ }
243
+ add_action('admin_init', array('EM_Event_Recurring_Posts_Admin','init'));
classes/em-event.php CHANGED
@@ -1,4 +1,28 @@
1
  <?php
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
  /**
3
  * Event Object. This holds all the info pertaining to an event, including location and recurrence info.
4
  * An event object can be one of three "types" a recurring event, recurrence of a recurring event, or a single event.
@@ -11,59 +35,76 @@
11
  //TODO Integrate recurrences into events table
12
  //FIXME If you create a super long recurrence timespan, there could be thousands of events... need an upper limit here.
13
  class EM_Event extends EM_Object{
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
  /**
15
- * Assoc array where keys are names of database fields and values are array corresponding object property name, regex, data types, etc.
16
- * for use when importing/exporting event data between database and object
 
 
 
 
 
 
 
 
 
 
 
17
  * @var array
18
  */
19
  var $fields = array(
20
  'event_id' => array( 'name'=>'id', 'type'=>'%d' ),
21
- 'event_author' => array( 'name'=>'author', 'type'=>'%d' ),
22
- 'event_name' => array( 'name'=>'name', 'type'=>'%s' ),
23
- 'event_start_time' => array( 'name'=>'start_time', 'type'=>'%s' ),
24
- 'event_end_time' => array( 'name'=>'end_time', 'type'=>'%s' ),
25
- 'event_start_date' => array( 'name'=>'start_date', 'type'=>'%s' ),
26
- 'event_end_date' => array( 'name'=>'end_date', 'type'=>'%s' ),
27
- 'event_notes' => array( 'name'=>'notes', 'type'=>'%s' ),
28
- 'event_rsvp' => array( 'name'=>'rsvp', 'type'=>'%d' ),
29
- 'event_seats' => array( 'name'=>'seats', 'type'=>'%d' ),
30
- 'event_contactperson_id' => array( 'name'=>'contactperson_id', 'type'=>'%d' ),
31
- 'location_id' => array( 'name'=>'location_id', 'type'=>'%d' ),
32
- 'recurrence_id' => array( 'name'=>'recurrence_id', 'type'=>'%d' ),
33
- 'event_category_id' => array( 'name'=>'category_id', 'type'=>'%d' ),
34
- 'event_attributes' => array( 'name'=>'attributes', 'type'=>'%s' ),
35
- 'recurrence' => array( 'name'=>'recurrence', 'type'=>'%d' ),
36
- 'recurrence_interval' => array( 'name'=>'interval', 'type'=>'%d' ), //every x day(s)/week(s)/month(s)
37
- 'recurrence_freq' => array( 'name'=>'freq', 'type'=>'%s' ), //daily,weekly,monthly?
38
- 'recurrence_byday' => array( 'name'=>'byday', 'type'=>'%s' ), //if weekly or monthly, what days of the week?
39
- 'recurrence_byweekno' => array( 'name'=>'byweekno', 'type'=>'%d' ), //if monthly which week (-1 is last)
40
- 'event_date_created' => array( 'name'=>'date_created', 'type'=>'%s' ),
41
- 'event_date_modified' => array( 'name'=>'date_modified', 'type'=>'%s' )
 
 
 
 
 
 
42
  );
43
- /* Field Names - see above for matching DB field names and other field meta data */
44
- var $id;
45
- var $author;
46
- var $name;
47
- var $start_time;
48
- var $end_time;
49
- var $start_date;
50
- var $end_date;
51
- var $notes;
52
- var $rsvp;
53
- var $seats;
54
- var $contactperson_id;
55
- var $location_id;
56
- var $recurrence_id;
57
- var $category_id;
58
- var $attributes;
59
- var $recurrence;
60
- var $interval;
61
- var $freq;
62
- var $byday;
63
- var $byweekno;
64
- var $date_created;
65
- var $date_modified;
66
 
 
67
  /**
68
  * Timestamp of start date/time
69
  * @var int
@@ -113,275 +154,440 @@ class EM_Event extends EM_Object{
113
  * @var string
114
  */
115
  var $feedback_message;
 
 
 
 
 
116
  /**
117
  * Array of dbem_event field names required to create an event
118
  * @var array
119
  */
120
  var $required_fields = array('event_name', 'event_start_date');
 
 
 
 
 
 
 
121
 
122
  /**
123
  * Initialize an event. You can provide event data in an associative array (using database table field names), an id number, or false (default) to create empty event.
124
  * @param mixed $event_data
125
- * @param boolean $recurrent
126
  * @return null
127
  */
128
- function EM_Event($event_data = false, $recurrent = false) {
129
- global $wpdb, $EM_Recurrences;
130
- //TODO Change the way we deal with time, maybe revert to timestamps for manipulation, and worry about output in html and db writes?
131
- if( $event_data !== false ){
132
- $event = array();
133
- if( is_array($event_data) ){
134
- //Accepts a raw array that'll just be imported directly into the object with no DB lookups (same for event and recurrence)
135
- $event = $event_data;
136
- $this->location = new EM_Location( $event );
137
- $this->category = new EM_Category( $event );
138
- }elseif( is_numeric($event_data) && $event_data > 0 ){
139
- //Retreiving from the database
140
- $events_table = $wpdb->prefix . EM_EVENTS_TABLE;
141
- $locations_table = $wpdb->prefix . EM_LOCATIONS_TABLE;
142
- $categories_table = $wpdb->prefix . EM_CATEGORIES_TABLE;
143
- $sql = "
144
- SELECT * FROM $events_table
145
- LEFT JOIN $locations_table ON {$locations_table}.location_id={$events_table}.location_id
146
- LEFT JOIN $categories_table ON {$categories_table}.category_id={$events_table}.event_category_id
147
- WHERE event_id = $event_data
148
- "; //We get event and location data here to avoid extra queries
149
- $event = $wpdb->get_row ( $sql, ARRAY_A );
150
- //Sort Location
151
- $this->location = new EM_Location ( $event );
152
- $this->category = new EM_Category( $event );
153
- }
154
- //Sort out attributes
155
- if( !empty($event['event_attributes']) ){
156
- if( is_serialized($event['event_attributes']) ){
157
- $event['event_attributes'] = @unserialize($event['event_attributes']);
158
  }
159
- $event['event_attributes'] = (!is_array($event['event_attributes'])) ? array() : $event['event_attributes'] ;
160
- }
161
- $event['recurrence_byday'] = ( $event['recurrence_byday'] == 7 ) ? 0:$event['recurrence_byday']; //Backward compatibility (since 3.0.3), using 0 makes more sense due to date() function
162
- $this->to_object($event, true);
163
-
164
- //Start/End times should be available as timestamp
165
- $this->start = strtotime($this->start_date." ".$this->start_time);
166
- $this->end = strtotime($this->end_date." ".$this->end_time);
167
- $this->modified = strtotime($event['event_date_modified']);
168
- $this->created = strtotime($event['event_date_created']);
169
-
170
- //Add Contact Person
171
- if($this->contactperson_id){
172
- if($this->contactperson_id > 0){
173
- $this->contact = get_userdata($this->contactperson_id);
174
  }
175
  }
176
- if( !is_object($this->contact) ){
177
- $this->contactperson_id = get_option('dbem_default_contact_person');
178
- $this->contact = get_userdata($this->contactperson_id);
179
- }
180
- if( is_object($this->contact) ){
181
- $this->contact->phone = get_metadata('user', $this->contact->ID, 'dbem_phone', true);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
182
  }
183
- //Now, if this is a recurrence, get the recurring for caching to the $EM_Recurrences
184
- if( $this->is_recurrence() && !array_key_exists($this->recurrence_id, $EM_Recurrences) ){
185
- $EM_Recurrences[$this->recurrence_id] = new EM_Event($this->recurrence_id);
 
 
 
 
 
 
186
  }
187
- }else{
188
- $this->location = new EM_Location(); //blank location
189
- $this->category = new EM_Category(); //blank category
 
190
  }
191
  }
192
 
193
  /**
194
- * Retrieve event, location and recurring information via POST
195
  * @return boolean
196
  */
197
- function get_post(){
198
- //Build Event Array
199
- do_action('em_event_get_post_pre', $this);
200
- $this->name = ( !empty($_POST['event_name']) ) ? stripslashes($_POST['event_name']) : '' ;
201
- $this->start_date = ( !empty($_POST['event_start_date']) ) ? $_POST['event_start_date'] : '';
202
- $this->end_date = ( !empty($_POST['event_end_date']) ) ? $_POST['event_end_date'] : $this->start_date;
203
- $this->rsvp = ( !empty($_POST['event_rsvp']) ) ? 1:0;
204
- $this->seats = ( !empty($_POST['event_seats']) && is_numeric($_POST['event_seats']) ) ? $_POST['event_seats']:0;
205
- $this->notes = ( !empty($_POST['content']) ) ? stripslashes($_POST['content']) : ''; //WP TinyMCE field
206
- //Sort out time
207
- //TODO make time handling less painful
208
- $match = array();
209
- if( !empty($_POST['event_start_time']) && preg_match ( '/^([01]\d|2[0-3]):([0-5]\d)(AM|PM)?$/', $_POST['event_start_time'], $match ) ){
210
- if( $match[3] == 'PM' && $match[1] != 12 ){
211
- $match[1] = 12+$match[1];
212
- }elseif( $match[3] == 'AM' && $match[1] == 12 ){
213
- $match[1] = '00';
214
- }
215
- $this->start_time = $match[1].":".$match[2].":00";
 
 
 
 
 
 
 
 
 
 
 
 
 
216
  }else{
217
- $this->start_time = "00:00:00";
218
- }
219
- if( !empty($_POST['event_end_time']) && preg_match ( '/^([01]\d|2[0-3]):([0-5]\d)(AM|PM)?$/', $_POST['event_end_time'], $match ) ){
220
- if( $match[3] == 'PM' && $match[1] != 12 ){
221
- $match[1] = 12+$match[1];
222
- }elseif( $match[3] == 'AM' && $match[1] == 12 ){
223
- $match[1] = '00';
224
- }
225
- $this->end_time = $match[1].":".$match[2].":00";
 
 
 
 
 
 
 
 
 
 
 
226
  }else{
227
- $this->end_time = $this->start_time;
228
  }
229
  //Start/End times should be available as timestamp
230
- $this->start = strtotime($this->start_date." ".$this->start_time);
231
- $this->end = strtotime($this->end_date." ".$this->end_time);
232
- //Contact Person
233
- if ( !empty($_POST['event_contactperson_id']) && is_numeric($_POST['event_contactperson_id']) ) {
234
- //TODO contactperson choices needs limiting depending on role
235
- $this->contactperson_id = $_POST['event_contactperson_id'];
236
- }
237
- //category
238
- if( !empty($_POST['event_category_id']) && is_numeric($_POST['event_category_id']) ){
239
- $this->category_id = $_POST['event_category_id'];
240
- }
241
- //Attributes
242
- $event_attributes = array();
243
- for($i=1 ; !empty($_POST["mtm_{$i}_ref"]) && trim($_POST["mtm_{$i}_ref"]) != '' ; $i++ ){
244
- if( !empty($_POST["mtm_{$i}_name"]) && trim($_POST["mtm_{$i}_name"]) != '' ){
245
- $event_attributes[$_POST["mtm_{$i}_ref"]] = stripslashes($_POST["mtm_{$i}_name"]);
246
- }
247
- }
248
- $this->attributes = $event_attributes;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
249
  //Recurrence data
250
- $this->recurrence_id = ( !empty($_POST['recurrence_id']) && is_numeric($_POST['recurrence_id']) ) ? $_POST['recurrence_id'] : 0 ;
251
- if( !empty($_POST['repeated_event']) ){
252
- $this->recurrence = 1;
253
- $this->freq = ( !empty($_POST['recurrence_freq']) && in_array($_POST['recurrence_freq'], array('daily','weekly','monthly')) ) ? $_POST['recurrence_freq']:'daily';
254
- if( !empty($_POST['recurrence_bydays']) && $this->freq == 'weekly' && self::array_is_numeric($_POST['recurrence_bydays']) ){
255
- $this->byday = implode ( ",", $_POST['recurrence_bydays'] );
256
- }elseif( !empty($_POST['recurrence_byday']) && $this->freq == 'monthly' ){
257
- $this->byday = $_POST['recurrence_byday'];
258
  }
259
- $this->interval = ( !empty($_POST['recurrence_interval']) ) ? $_POST['recurrence_interval']:1;
260
- $this->byweekno = ( !empty($_POST['recurrence_byweekno']) ) ? $_POST['recurrence_byweekno']:'';
 
261
  }
262
-
263
- //Add location information, or just link to previous location, this is a requirement...
264
- if( !empty($_POST['location-select-id']) ) {
265
- $this->location = new EM_Location($_POST['location-select-id']);
266
- } else {
267
- $this->location = new EM_Location($_POST);
268
- $this->location->load_similar($_POST);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
269
  }
270
- return apply_filters('em_event_get_post', $this->validate(), $this);
271
  }
272
 
273
  /**
274
  * Will save the current instance into the database, along with location information if a new one was created and return true if successful, false if not.
275
- * Will automatically detect what type of event it is (recurrent, recurrence or normal) and whether it's a new or existing event.
276
  * @return boolean
277
  */
278
  function save(){
279
- //FIXME Event doesn't save title when inserting first time
280
- global $wpdb, $current_user;
281
- if( !$this->can_manage(true) ){
282
  return apply_filters('em_event_save', false, $this);
283
  }
 
284
  do_action('em_event_save_pre', $this);
285
- get_currentuserinfo();
286
- $events_table = $wpdb->prefix.EM_EVENTS_TABLE;
287
- //First let's save the location, no location no event!
288
- if ( !$this->location->id && !$this->location->save() ){ //shouldn't try to save if location exists
289
- $this->errors[] = __ ( 'There was a problem saving the location so event was not saved.', 'dbem' );
290
- return apply_filters('em_event_save', false, $this);
291
- }
292
- $this->location_id = $this->location->id;
293
- //Contact person can be anyone the admin wants, but the creator if not.
294
- if( em_verify_admin() ){
295
- $this->contactperson_id = ( $this->contactperson_id > 0 ) ? $this->contactperson_id:0;
296
- }else{
297
- //force
298
- $this->contactperson_id = get_current_user_id();
299
- }
300
- //Now save the event
301
- if ( !$this->id ) {
302
- // Insert New Event
303
- $this->author = $current_user->ID; //Record creator of event
304
- $event = $this->to_array(false, true);
305
- $event['event_attributes'] = serialize($this->attributes);
306
- $event['recurrence_id'] = ( is_numeric($this->recurrence_id) ) ? $this->recurrence_id : 0;
307
- $event = apply_filters('em_event_save_pre',$event,$this);
308
- $result = $wpdb->insert ( $events_table, $event, $this->get_types($event) );
309
- if($result !== false){
310
- $this->id = $wpdb->insert_id;
311
- //Deal with recurrences
312
- if ( $this->is_recurring() ) {
313
- //Recurrence master event saved, now Save Events & check errors
314
- if( !$this->save_events() ){
315
- $this->errors[] = __ ( 'Something went wrong with the recurrence update...', 'dbem' ).
316
- __ ( 'There was a problem saving the recurring events.', 'dbem' );
317
- $this->delete();
318
- return apply_filters('em_event_save', false, $this);
319
- }
320
- //All good! Event Saved
321
- $this->feedback_message = __ ( 'New recurrent event inserted!', 'dbem' );
322
- return apply_filters('em_event_save', true, $this);
323
- }
324
- //Successful individual save
325
- $this->feedback_message = __ ( 'New event successfully inserted!', 'dbem' );
326
- return apply_filters('em_event_save', true, $this);
327
- }else{
328
- $this->errors[] = __ ( 'Could not save the event details due to a database error.', 'dbem' );
329
- }
330
- } else {
331
- // Update Event
332
- //TODO event privacy protection, only authors and authorized users can edit events
333
- //$this->author = $current_user->ID; //Record creator of event
334
- //FIXME Saving recurrence and disabling recurrence doesn't work
335
- $this->recurrence_id = 0; // If it's saved here, it becomes individual
336
- $event = $this->to_array();
337
- $event['event_attributes'] = serialize($event['event_attributes']);
338
- $event['event_date_modified'] = current_time('mysql');
339
- $event = apply_filters('em_event_save_pre',$event,$this);
340
- $result = $wpdb->update ( $events_table, $event, array('event_id' => $this->id), $this->get_types($event) );
341
- if($result !== false){ //Can't just do $result since if you don't make an actual record details change, it'll return 0 for no changes made
342
- //Deal with recurrences
343
- if ( $this->is_recurring() ) {
344
- if( !$this->save_events() ){
345
- $this->errors[] = __ ( 'Something went wrong with the recurrence update...', 'dbem' ).
346
- __ ( 'There was a problem saving the recurring events.', 'dbem' );
347
- return apply_filters('em_event_save', false, $this);
348
- }
349
- $this->feedback_message = __ ( 'Recurrence updated!', 'dbem' );
350
- return apply_filters('em_event_save', true, $this);
351
- }
352
  }else{
353
- $this->errors[] = __('Could not save the event details due to a database error.', 'dbem');
354
- return apply_filters('em_event_save', false, $this);
355
- }
356
- //Successful individual or recurrence save
357
- $this->feedback_message = "{$this->name} " . __ ( 'updated', 'dbem' ) . "!";
358
- if($this->rsvp == 0){
359
- $this->delete_bookings();
360
  }
361
- return apply_filters('em_event_save', true, $this);
362
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
363
  }
364
 
365
- /**
366
- * Delete whole event, including recurrence and recurring data
367
- * @param $recurrence_id
368
- * @return boolean
369
- */
370
- function delete(){
371
  global $wpdb;
372
- do_action('em_event_delete_pre', $this);
373
- $result = false;
374
- if( $this->can_manage(true) ){
375
- if( $this->is_recurring() ){
376
- //Delete the recurrences then this recurrence event
377
- $this->delete_events();
 
 
 
 
 
 
 
 
378
  }
379
- $result = $wpdb->query ( $wpdb->prepare("DELETE FROM ". $wpdb->prefix . EM_EVENTS_TABLE ." WHERE event_id=%d", $this->id) );
380
- if($result !== false){
381
- $result = $this->get_bookings()->delete();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
382
  }
383
  }
384
- return apply_filters('em_event_delete', $result, $this);
385
  }
386
 
387
  /**
@@ -391,13 +597,27 @@ class EM_Event extends EM_Object{
391
  function duplicate(){
392
  global $wpdb, $EZSQL_ERROR;
393
  //First, duplicate.
394
- if( $this->can_manage(true) ){
395
- $event_table_name = $wpdb->prefix . EM_EVENTS_TABLE;
396
- $eventArray = $this->to_array(true);
397
- unset($eventArray['event_id']);
398
- $EM_Event = new EM_Event( $eventArray );
399
- if( $EM_Event->save() ){
400
- $EM_Event->feedback_message = __("You are now viewing the duplicated event", 'dbem');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
401
  return apply_filters('em_event_duplicate', $EM_Event, $this);
402
  }
403
  }
@@ -405,72 +625,199 @@ class EM_Event extends EM_Object{
405
  return apply_filters('em_event_duplicate', false, $this);;
406
  }
407
 
408
-
409
  /**
410
- * Validates the event. Should be run during any form submission or saving operation.
411
  * @return boolean
412
  */
413
- function validate() {
414
- $missing_fields = Array ();
415
- foreach ( $this->required_fields as $field ) {
416
- $true_field = $this->fields[$field]['name'];
417
- if ( $this->$true_field == "") {
418
- $missing_fields[] = $field;
 
 
419
  }
 
 
420
  }
421
- if ( count($missing_fields) > 0){
422
- // TODO Create friendly equivelant names for missing fields notice in validation
423
- $this->errors[] = __ ( 'Missing fields: ' ) . implode ( ", ", $missing_fields ) . ". ";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
424
  }
425
- if ( !empty($_POST['repeated_event']) && $_POST['repeated_event'] == "1" && $this->end_date == "" ){
426
- $this->errors[] = __ ( 'Since the event is repeated, you must specify an event date.', 'dbem' );
 
 
 
 
 
 
 
 
 
 
 
427
  }
428
- if( preg_match('/\d{4}-\d{2}-\d{2}/', $this->start_date) && preg_match('/\d{4}-\d{2}-\d{2}/', $this->end_date) ){
429
- if( strtotime($this->start_date . $this->start_time) > strtotime($this->end_date . $this->end_time) ){
430
- $this->errors[] = __('Events cannot start after they end.','dbem');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
431
  }
432
  }else{
433
- $this->errors[] = __('Dates must have correct formatting. Please use the date picker provided.','dbem');
 
 
 
 
434
  }
435
- if( !$this->location->validate() ){
436
- $this->errors = array_merge($this->errors, $this->location->errors);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
437
  }
438
- //TODO validate recurrence during event validate
439
- return apply_filters('em_event_validate', count($this->errors) == 0, $this );
 
 
 
 
440
  }
441
-
442
 
443
  /**
444
- * Returns an array with category id and name (in that order) of the EM_Event instance.
445
- * @return array
446
  */
447
- function get_category() {
448
- global $EM_Category;
449
- if( is_object($this->category) && get_class($this->category)=='EM_Category' && $this->category_id == $this->category->id ){
450
- return $this->category;
451
- }elseif( is_object($EM_Category) && $EM_Category->id == $this->category_id ){
452
- $this->category = $EM_Category;
453
- }else{
454
- $this->category = new EM_Category($this->category_id);
455
  }
456
- return $this->event;
457
- global $wpdb;
458
- $sql = "SELECT category_id, category_name FROM ".$wpdb->prefix.EM_EVENTS_TABLE." LEFT JOIN ".$wpdb->prefix.EM_CATEGORIES_TABLE." ON category_id=event_category_id WHERE event_id ='".$this->id."'";
459
- $category = $wpdb->get_row($sql, ARRAY_A);
460
- return apply_filters('em_event_get_category', $category, $this);
461
  }
462
 
463
  /**
464
- * Shortcut function for $this->get_bookings()->delete(), because using the EM_Bookings requires loading previous bookings, which isn't neceesary.
 
465
  */
466
- function delete_bookings(){
467
- global $wpdb;
468
- do_action('em_event_delete_bookings_pre', $this);
469
- $result = false;
470
- if( $this->can_manage(true) ){
471
- $result = $wpdb->query( $wpdb->prepare("DELETE FROM ".$wpdb->prefix.EM_BOOKINGS_TABLE." WHERE event_id=%d", $this->id) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
472
  }
473
- return apply_filters('em_event_delete_bookings', $result, $this);
474
  }
475
 
476
  /**
@@ -483,10 +830,42 @@ class EM_Event extends EM_Object{
483
  if( (!$this->bookings || $force_reload) ){
484
  $this->bookings = new EM_Bookings($this);
485
  }
 
 
 
486
  }
487
  return apply_filters('em_event_get_bookings', $this->bookings, $this);
488
  }
489
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
490
  /**
491
  * Will output a single event format of this event.
492
  * Equivalent of calling EM_Event::output( get_option ( 'dbem_single_event_format' ) )
@@ -497,17 +876,6 @@ class EM_Event extends EM_Object{
497
  $format = get_option ( 'dbem_single_event_format' );
498
  return apply_filters('em_event_output_single', $this->output($format, $target), $this, $target);
499
  }
500
-
501
- /**
502
- * Will output a event list item format of this event.
503
- * Equivalent of calling EM_Event::output( get_option ( 'dbem_event_list_item_format' ) )
504
- * @param string $target
505
- * @return string
506
- */
507
- function output_list($target='html'){
508
- $format = get_option ( 'dbem_event_list_item_format' );
509
- return apply_filters('em_event_output_list', $this->output($format, $target), $this, $target);
510
- }
511
 
512
  /**
513
  * Will output a event in the format passed in $format by replacing placeholders within the format.
@@ -515,130 +883,334 @@ class EM_Event extends EM_Object{
515
  * @param string $target
516
  * @return string
517
  */
518
- function output($format, $target="html") {
519
  $event_string = $format;
520
- preg_match_all("/#@?_?[A-Za-z0-9]+/", $format, $placeholders);
521
- foreach($placeholders[0] as $result) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
522
  $match = true;
523
  $replace = '';
 
524
  switch( $result ){
525
  //Event Details
526
  case '#_EVENTID':
527
  $replace = $this->id;
528
  break;
529
  case '#_NAME':
530
- $replace = $this->name;
531
  break;
532
  case '#_NOTES':
533
  case '#_EXCERPT':
534
  //SEE AT BOTTOM OF FILE FOR OLD TARGET FILTERS FROM 2.x
535
- $replace = $this->notes;
536
  if($result == "#_EXCERPT"){
537
- $matches = explode('<!--more', $this->notes);
538
  $replace = $matches[0];
539
  }
540
  break;
541
- //Times
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
542
  case '#_24HSTARTTIME':
543
  case '#_24HENDTIME':
544
- $time = ($result == '#_24HSTARTTIME') ? $this->start_time:$this->end_time;
545
  $replace = substr($time, 0,5);
546
  break;
547
  case '#_12HSTARTTIME':
548
  case '#_12HENDTIME':
549
- $time = ($result == '#_12HSTARTTIME') ? $this->start_time:$this->end_time;
550
  $replace = date('g:i A', strtotime($time));
551
  break;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
552
  //Links
553
  case '#_EVENTPAGEURL': //Depreciated
554
  case '#_LINKEDNAME': //Depreciated
555
  case '#_EVENTURL': //Just the URL
556
  case '#_EVENTLINK': //HTML Link
557
- $joiner = (stristr(EM_URI, "?")) ? "&amp;" : "?";
558
- $event_link = EM_URI.$joiner."event_id=".$this->id;
 
 
 
 
 
 
 
 
 
 
 
 
 
559
  if($result == '#_LINKEDNAME' || $result == '#_EVENTLINK'){
560
- $replace = "<a href='{$event_link}' title='{$this->name}'>{$this->name}</a>";
561
  }else{
562
  $replace = $event_link;
563
  }
564
  break;
 
565
  case '#_EDITEVENTLINK':
566
- if( $this->can_manage() ){
567
- //TODO user should have permission to edit the event
568
- $replace = "<a href='".get_bloginfo('wpurl')."/wp-admin/admin.php?page=events-manager-event&amp;event_id={$this->id}'>".__('Edit').' '.__('Event', 'dbem')."</a>";
 
 
 
 
 
 
569
  }
570
  break;
571
  //Bookings
572
- case '#_ADDBOOKINGFORM':
573
- case '#_REMOVEBOOKINGFORM':
574
  case '#_BOOKINGFORM':
575
- if ($this->rsvp && get_option('dbem_rsvp_enabled')){
576
- if($result == '#_BOOKINGFORM'){
577
- $replace = em_add_booking_form().em_delete_booking_form();
578
- }else{
579
- $replace = ($result == '#_ADDBOOKINGFORM') ? em_add_booking_form():em_delete_booking_form();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
580
  }
 
 
 
 
 
 
 
 
581
  }
582
  break;
583
  case '#_AVAILABLESEATS': //Depreciated
584
  case '#_AVAILABLESPACES':
585
- if ($this->rsvp && get_option('dbem_rsvp_enabled')) {
586
- $replace = $this->get_bookings()->get_available_seats();
587
  } else {
588
  $replace = "0";
589
  }
590
  break;
591
  case '#_BOOKEDSEATS': //Depreciated
592
  case '#_BOOKEDSPACES':
593
- if ($this->rsvp && get_option('dbem_rsvp_enabled')) {
594
- $replace = $this->get_bookings()->get_booked_seats();
 
 
 
 
 
 
 
595
  } else {
596
  $replace = "0";
597
  }
598
  break;
599
  case '#_SEATS': //Depreciated
600
  case '#_SPACES':
601
- $replace = $this->seats;
 
 
 
 
 
 
 
 
 
 
 
602
  break;
603
  //Contact Person
604
  case '#_CONTACTNAME':
605
  case '#_CONTACTPERSON': //Depreciated (your call, I think name is better)
606
- $replace = $this->contact->display_name;
607
  break;
608
  case '#_CONTACTUSERNAME':
609
- $replace = $this->contact->user_login;
610
  break;
611
  case '#_CONTACTEMAIL':
612
  case '#_CONTACTMAIL': //Depreciated
613
- $replace = $this->contact->user_email;
614
  break;
615
  case '#_CONTACTID':
616
- $replace = $this->contact->ID;
617
  break;
618
  case '#_CONTACTPHONE':
619
- $replace = ( $this->contact->phone != '') ? $this->contact->phone : __('N/A', 'dbem');
620
  break;
621
  case '#_CONTACTAVATAR':
622
- $replace = get_avatar( $this->contact->ID, $size = '50' );
 
 
 
 
 
 
 
 
 
623
  break;
624
  case '#_CONTACTPROFILELINK':
625
  case '#_CONTACTPROFILEURL':
626
  if( function_exists('bp_core_get_user_domain') ){
627
- $replace = bp_core_get_user_domain($this->contact->ID);
628
  if( $result == '#_CONTACTPROFILELINK' ){
629
- $replace = '<a href="'.$replace.'">'.__('Profile').'</a>';
630
  }
631
  }
632
  break;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
633
  default:
634
- $replace = $result;
635
  break;
636
  }
637
- $replace = apply_filters('em_event_output_placeholder', $replace, $this, $result, $target);
638
- $event_string = str_replace($result, $replace , $event_string );
639
  }
640
  //Time placeholders
641
- foreach($placeholders[0] as $result) {
642
  // matches all PHP START date and time placeholders
643
  if (preg_match('/^#[dDjlNSwzWFmMntLoYyaABgGhHisueIOPTZcrU]$/', $result)) {
644
  $replace = date_i18n(ltrim($result, "#"), $this->start);
@@ -652,141 +1224,280 @@ class EM_Event extends EM_Object{
652
  $event_string = str_replace($result, $replace, $event_string );
653
  }
654
  }
655
- //Time place holder that doesn't show if empty.
656
- //TODO add filter here too
657
- preg_match_all('/#@?_\{[A-Za-z0-9 -\/,\.\\\]+\}/', $format, $results);
658
- foreach($results[0] as $result) {
659
- if(substr($result, 0, 3 ) == "#@_"){
660
- $date = 'end_date';
661
- $offset = 4;
662
- }else{
663
- $date = 'start_date';
664
- $offset = 3;
665
- }
666
- if( $date == 'end_date' && $this->end_date == $this->start_date ){
667
- $replace = __( apply_filters('em_event_output_placeholder', '', $this, $result, $target) );
668
- }else{
669
- $replace = __( apply_filters('em_event_output_placeholder', mysql2date(substr($result, $offset, (strlen($result)-($offset+1)) ), $this->$date), $this, $result, $target) );
670
- }
671
- $event_string = str_replace($result,$replace,$event_string );
672
- }
673
- //This is for the custom attributes
674
- preg_match_all('/#_ATT\{.+?\}(\{(.+)\})?/', $format, $results);
675
- foreach($results[0] as $resultKey => $result) {
676
- //Strip string of placeholder and just leave the reference
677
- $attRef = substr( substr($result, 0, strpos($result, '}')), 6 );
678
- $attString = '';
679
- if( is_array($this->attributes) && array_key_exists($attRef, $this->attributes) ){
680
- $attString = $this->attributes[$attRef];
681
- }elseif( !empty($results[2][$resultKey]) ){
682
- //Check to see if we have a second set of braces;
683
- $attString = $results[2][$resultKey];
684
- }
685
- $attString = apply_filters('em_event_output_placeholder', $attString, $this, $result, $target);
686
- $event_string = str_replace($result, $attString ,$event_string );
687
  }
688
 
689
- //Now do dependent objects
690
- $event_string = $this->location->output($event_string, $target);
691
- $event_string = $this->category->output($event_string, $target);
692
- return apply_filters('em_event_output', $event_string, $this, $target);
693
- }
 
 
 
 
 
694
 
695
  /**********************************************************
696
  * RECURRENCE METHODS
697
  ***********************************************************/
698
 
699
  /**
700
- * Saves events and replaces old ones. Returns true if sucecssful or false if not.
701
  * @return boolean
702
  */
703
- function save_events() {
704
- if( $this->is_recurring() && $this->can_manage() ){
705
- do_action('em_event_save_events_pre', $this); //actions/filters only run if event is recurring
706
- global $wpdb;
707
- $event_saves = array();
708
- $matching_days = $this->get_recurrence_days(); //Get days where events recur
709
- $this->delete_events(); //Delete old events beforehand
710
- //Make template event (and we just change dates)
711
- $event = $this->to_array();
712
- unset($event['event_id']); //remove id and we have a event template to feed to wpdb insert
713
- $event['event_attributes'] = serialize($event['event_attributes']);
714
- foreach($event as $key => $value ){ //remove recurrence information
715
- if( substr($key, 0, 10) == 'recurrence' ){
716
- unset($event[$key]);
717
- }
718
- }
719
- $event['recurrence_id'] = $this->id;
720
- //Save event template with different dates
721
- foreach( $matching_days as $day ) {
722
- $event['event_start_date'] = date("Y-m-d", $day);
723
- $event['event_end_date'] = $event['event_start_date'];
724
- $event_saves[] = $wpdb->insert($wpdb->prefix.EM_EVENTS_TABLE, $event, $this->get_types($event));
725
- //TODO should be EM_DEBUG, and do we really need it?
726
- if( DEBUG ){ echo "Entering recurrence " . date("D d M Y", $day)."<br/>"; }
727
- }
728
- return apply_filters('em_event_save_events', !in_array(false, $event_saves), $this);
729
- }
730
- return apply_filters('em_event_save_events', false, $this);;
731
  }
732
 
733
  /**
734
- * Removes all reoccurring events.
735
- * @param $recurrence_id
736
- * @return null
737
  */
738
- function delete_events(){
739
- global $wpdb;
740
- do_action('em_event_delete_events_pre', $this);
741
- //So we don't do something we'll regret later, we could just supply the get directly into the delete, but this is safer
742
- $result = false;
743
- if( $this->can_manage(true) ){
744
- $EM_Events = EM_Events::get( array('recurrence_id'=>$this->id) );
745
- $event_ids = array();
746
- foreach($EM_Events as $EM_Event){
747
- if($EM_Event->recurrence_id == $this->id){
748
- $event_ids[] = $EM_Event->id; //ONLY ADD if id's match - hard coded
749
- }
750
- }
751
- $result = EM_Events::delete( $event_ids );
752
  }
753
- return apply_filters('delete_events', $result, $this);
 
 
 
 
 
 
 
754
  }
755
 
756
  /**
757
- * Returns true if this event is a recurring event, meaning that it's not an individual event,
758
- * but an event that defines many events that recur over a span of time.
759
- * For checking if a specific event is part of a greater set of recurring events, use is_recurrence()
760
  * @return boolean
761
  */
762
- function is_recurring(){
763
- return ( $this->recurrence );
764
- }
 
 
 
 
 
 
 
 
 
 
 
 
765
  /**
766
- * Will return true if this individual event is part of a set of events that recur
767
- * For checking if this is the "master recurring event", see is_recurring()
768
  * @return boolean
769
  */
770
- function is_recurrence(){
771
- return ( $this->id > 0 && $this->recurrence_id > 0 );
 
 
 
 
 
 
 
 
 
772
  }
 
773
  /**
774
- * Returns if this is an individual event and is not recurring or a recurrence
775
  * @return boolean
776
  */
777
- function is_individual(){
778
- return ( !$this->is_recurring() && !$this->is_recurrence() );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
779
  }
780
 
781
  /**
782
- * Can the user manage this event?
 
 
783
  */
784
- function can_manage( $error_msg = false ){
785
- $can_manage = ( get_option('dbem_permissions_events') || $this->author == get_current_user_id() || empty($this->id) || em_verify_admin() );
786
- if($error_msg && !$can_manage){
787
- $this->errors[] = __('You do not have permission to manage this event.','dbem');
 
 
 
 
 
 
 
 
 
 
788
  }
789
- return apply_filters('em_event_can_manage', $can_manage, $this);
790
  }
791
 
792
  /**
@@ -794,104 +1505,109 @@ class EM_Event extends EM_Object{
794
  * @param array $recurrence
795
  * @return array
796
  */
797
- function get_recurrence_days(){
798
- if( $this->is_recurring() ){
799
-
800
- $start_date = strtotime($this->start_date);
801
- $end_date = strtotime($this->end_date);
802
-
803
- $weekdays = explode(",", $this->byday); //what days of the week (or if monthly, one value at index 0)
804
-
805
- $matching_days = array();
806
- $aDay = 86400; // a day in seconds
807
- $aWeek = $aDay * 7;
808
 
809
- //TODO can this be optimized?
810
- switch ( $this->freq ){
811
- case 'daily':
812
- //If daily, it's simple. Get start date, add interval timestamps to that and create matching day for each interval until end date.
813
- $current_date = $start_date;
814
- while( $current_date <= $end_date ){
815
- $matching_days[] = $current_date;
816
- $current_date = $current_date + ($aDay * $this->interval);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
817
  }
818
- break;
819
- case 'weekly':
820
- //sort out week one, get starting days and then days that match time span of event (i.e. remove past events in week 1)
821
- $start_of_week = get_option('start_of_week'); //Start of week depends on wordpress
822
- //first, get the start of this week as timestamp
823
- $event_start_day = date('w', $start_date);
824
- $offset = 0;
825
- if( $event_start_day > $start_of_week ){
826
- $offset = $event_start_day - $start_of_week; //x days backwards
827
- }elseif( $event_start_day < $start_of_week ){
828
- $offset = $start_of_week;
829
- }
830
- $start_week_date = $start_date - ( ($event_start_day - $start_of_week) * $aDay );
831
- //then get the timestamps of weekdays during this first week, regardless if within event range
832
- $start_weekday_dates = array(); //Days in week 1 where there would events, regardless of event date range
833
- for($i = 0; $i < 7; $i++){
834
- $weekday_date = $start_week_date+($aDay*$i); //the date of the weekday we're currently checking
835
- $weekday_day = date('w',$weekday_date); //the day of the week we're checking, taking into account wp start of week setting
836
- if( in_array( $weekday_day, $weekdays) ){
837
- $start_weekday_dates[] = $weekday_date; //it's in our starting week day, so add it
838
- }
839
- }
840
- //for each day of eventful days in week 1, add 7 days * weekly intervals
841
- foreach ($start_weekday_dates as $weekday_date){
842
- //Loop weeks by interval until we reach or surpass end date
843
- while($weekday_date <= $end_date){
844
- if( $weekday_date >= $start_date && $weekday_date <= $end_date ){
845
- $matching_days[] = $weekday_date;
846
- }
847
- $weekday_date = $weekday_date + ($aWeek * $this->interval);
848
  }
849
- }//done!
850
- break;
851
- case 'monthly':
852
- //loop months starting this month by intervals
853
- $current_arr = getdate($start_date);
854
- $end_arr = getdate($end_date);
855
- $end_month_date = strtotime( date('Y-m-t', $end_date) ); //End date on last day of month
856
- $current_date = strtotime( date('Y-m-1', $start_date) ); //Start date on first day of month
857
- while( $current_date <= $end_month_date ){
858
- $last_day_of_month = date('t', $current_date);
859
- //Now find which day we're talking about
860
- $current_week_day = date('w',$current_date);
861
- $matching_month_days = array();
862
- //Loop through days of this years month and save matching days to temp array
863
- for($day = 1; $day <= $last_day_of_month; $day++){
864
- if($current_week_day == $this->byday){
865
- $matching_month_days[] = $day;
866
- }
867
- $current_week_day = ($current_week_day < 6) ? $current_week_day+1 : 0;
868
- }
869
- //Now grab from the array the x day of the month
870
- $matching_day = ($this->byweekno > 0) ? $matching_month_days[$this->byweekno-1] : array_pop($matching_month_days);
871
- $matching_date = strtotime(date('Y-m',$current_date).'-'.$matching_day);
872
- if($matching_date >= $start_date && $matching_date <= $end_date){
873
- $matching_days[] = $matching_date;
874
- }
875
- //add the number of days in this month to make start of next month
876
- $current_arr['mon'] += $this->interval;
877
- if($current_arr['mon'] > 12){
878
- //FIXME this won't work if interval is more than 12
879
- $current_arr['mon'] = $current_arr['mon'] - 12;
880
- $current_arr['year']++;
881
  }
882
- $current_date = strtotime("{$current_arr['year']}-{$current_arr['mon']}-1");
883
  }
884
- break;
885
- }
886
- sort($matching_days);
887
- //TODO delete this after testing
888
- /*Delete*/
889
- $test_dates = array();
890
- foreach($matching_days as $matching_day){
891
- $test_dates[] = date('d/m/Y', $matching_day);
892
- }
893
- /*end delete*/
894
- return $matching_days;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
895
  }
896
  }
897
 
@@ -899,74 +1615,58 @@ class EM_Event extends EM_Object{
899
  * Returns a string representation of this recurrence. Will return false if not a recurrence
900
  * @return string
901
  */
902
- function get_recurrence_description() {
903
- //FIXME Recurrence description not working for recurrence
904
- global $EM_Recurrences;
905
- if( $this->is_individual() ) return false;
906
- $recurrence = $EM_Recurrences[$this->recurrence_id]->to_array();
907
- $weekdays_name = array(__('Sunday'),__('Monday'),__('Tuesday'),__('Wednesday'),__('Thursday'),__('Friday'),__('Saturday'));
908
  $monthweek_name = array('1' => __('the first %s of the month', 'dbem'),'2' => __('the second %s of the month', 'dbem'), '3' => __('the third %s of the month', 'dbem'), '4' => __('the fourth %s of the month', 'dbem'), '-1' => __('the last %s of the month', 'dbem'));
909
- $output = sprintf (__('From %1$s to %2$s', 'dbem'), $recurrence['event_start_date'], $recurrence['event_end_date']).", ";
910
- if ($recurrence['recurrence_freq'] == 'daily') {
911
  $freq_desc =__('everyday', 'dbem');
912
- if ($recurrence['recurrence_interval'] > 1 ) {
913
- $freq_desc = sprintf (__("every %s days", 'dbem'), $recurrence['recurrence_interval']);
914
  }
915
- }
916
- if ($recurrence['recurrence_freq'] == 'weekly') {
917
- $weekday_array = explode(",", $recurrence['recurrence_byday']);
918
  $natural_days = array();
919
  foreach($weekday_array as $day){
920
  array_push($natural_days, $weekdays_name[$day]);
921
  }
922
  $output .= implode(" and ", $natural_days);
923
  $freq_desc = ", " . __("every week", 'dbem');
924
- if ($recurrence['recurrence_interval'] > 1 ) {
925
- $freq_desc = ", ".sprintf (__("every %s weeks", 'dbem'), $recurrence['recurrence_interval']);
926
  }
927
 
928
- }
929
- if ($recurrence['recurrence_freq'] == 'monthly') {
930
- $weekday_array = explode(",", $recurrence['recurrence_byday']);
931
  $natural_days = array();
932
  foreach($weekday_array as $day){
933
  array_push($natural_days, $weekdays_name[$day]);
934
  }
935
- $freq_desc = sprintf (($monthweek_name[$recurrence['recurrence_byweekno']]), implode(" and ", $natural_days));
936
- if ($recurrence['recurrence_interval'] > 1 ) {
937
- $freq_desc .= ", ".sprintf (__("every %s months",'dbem'), $recurrence['recurrence_interval']);
938
  }
939
-
 
940
  }
941
  $output .= $freq_desc;
942
  return $output;
943
- }
944
 
945
  /**********************************************************
946
  * UTILITIES
947
  ***********************************************************/
948
-
949
  /**
950
- * Returns this object in the form of an array, useful for saving directly into the wp_dbem_events table.
951
- * @param boolean $location
952
- * @param boolean $for_database
953
- * @return array
954
  */
955
- function to_array($location = false, $for_database = false){
956
- $event = array();
957
- //Core Event Data
958
- foreach ( $this->fields as $key => $val ) {
959
- //TODO does it matter if it's for db or not... shouldn't it just not include blanks?
960
- if( !$for_database || $for_database && $this->$val['name'] ){
961
- $event[$key] = $this->$val['name'];
962
- }
963
- }
964
- //Location Data
965
- if($location && is_object($this->location)){
966
- $location = $this->location->to_array();
967
- $event = array_merge($event, $location);
968
  }
969
- return $event;
970
  }
971
  }
972
 
@@ -983,12 +1683,14 @@ function em_event_output_placeholder($result,$event,$placeholder,$target='html')
983
  if( ($placeholder == "#_EXCERPT" || $placeholder == "#_LOCATIONEXCERPT") && $target == 'html' ){
984
  $result = apply_filters('dbem_notes_excerpt', $result);
985
  }elseif( $placeholder == '#_CONTACTEMAIL' && $target == 'html' ){
986
- $result = em_ascii_encode($event->contact->user_email);
987
  }elseif( $placeholder == "#_NOTES" || $placeholder == "#_EXCERPT" || $placeholder == "#_LOCATIONEXCERPT" ){
988
  if($target == 'html'){
989
  $result = apply_filters('dbem_notes', $result);
990
  }elseif($target == 'map'){
991
  $result = apply_filters('dbem_notes_map', $result);
 
 
992
  }else{
993
  $result = apply_filters('dbem_notes_rss', $result);
994
  $result = apply_filters('the_content_rss', $result);
@@ -996,6 +1698,8 @@ function em_event_output_placeholder($result,$event,$placeholder,$target='html')
996
  }elseif( in_array($placeholder, array("#_NAME",'#_ADDRESS','#_LOCATION','#_TOWN')) ){
997
  if ($target == "html"){
998
  $result = apply_filters('dbem_general', $result);
 
 
999
  }else{
1000
  $result = apply_filters('dbem_general_rss', $result);
1001
  }
1
  <?php
2
+ /**
3
+ * Get an event in a db friendly way, by checking globals and passed variables to avoid extra class instantiations
4
+ * @param mixed $id
5
+ * @param mixed $search_by
6
+ * @return EM_Event
7
+ */
8
+ function em_get_event($id = false, $search_by = 'event_id') {
9
+ global $EM_Event;
10
+ //check if it's not already global so we don't instantiate again
11
+ if( is_object($EM_Event) && get_class($EM_Event) == 'EM_Event' ){
12
+ if( $search_by == 'event_id' && $EM_Event->event_id == $id ){
13
+ return $EM_Event;
14
+ }elseif( $search_by == 'post_id' && $EM_Event->post_id == $id ){
15
+ return $EM_Event;
16
+ }elseif( is_object($id) && $EM_Event->post_id == $id->ID ){
17
+ return $EM_Event;
18
+ }
19
+ }
20
+ if( is_object($id) && get_class($id) == 'EM_Event' ){
21
+ return $id;
22
+ }else{
23
+ return new EM_Event($id,$search_by);
24
+ }
25
+ }
26
  /**
27
  * Event Object. This holds all the info pertaining to an event, including location and recurrence info.
28
  * An event object can be one of three "types" a recurring event, recurrence of a recurring event, or a single event.
35
  //TODO Integrate recurrences into events table
36
  //FIXME If you create a super long recurrence timespan, there could be thousands of events... need an upper limit here.
37
  class EM_Event extends EM_Object{
38
+ /* Field Names */
39
+ var $event_id;
40
+ var $event_slug;
41
+ var $event_owner;
42
+ var $event_name;
43
+ var $event_start_time;
44
+ var $event_end_time;
45
+ var $event_all_day;
46
+ var $event_start_date;
47
+ var $event_end_date;
48
+ var $post_content;
49
+ var $event_rsvp;
50
+ //var $spaces;
51
+ var $location_id;
52
+ var $recurrence_id;
53
+ var $event_status;
54
+ var $event_date_created;
55
+ var $event_date_modified;
56
+ var $blog_id;
57
+ var $group_id;
58
  /**
59
+ * Populated with the non-hidden event post custom fields (i.e. not starting with _)
60
+ * @var array
61
+ */
62
+ var $event_attributes = array();
63
+ /* Recurring Specific Values */
64
+ var $recurrence;
65
+ var $recurrence_interval;
66
+ var $recurrence_freq;
67
+ var $recurrence_byday;
68
+ var $recurrence_days;
69
+ var $recurrence_byweekno;
70
+ /**
71
+ * Previously used to give this object shorter property names for db values (each key has a name) but this is now depreciated, use the db field names as properties. This propertey provides extra info about the db fields.
72
  * @var array
73
  */
74
  var $fields = array(
75
  'event_id' => array( 'name'=>'id', 'type'=>'%d' ),
76
+ 'post_id' => array( 'name'=>'post_id', 'type'=>'%d' ),
77
+ 'event_slug' => array( 'name'=>'slug', 'type'=>'%s', 'null'=>true ),
78
+ 'event_owner' => array( 'name'=>'owner', 'type'=>'%d', 'null'=>true ),
79
+ 'event_name' => array( 'name'=>'name', 'type'=>'%s', 'null'=>true ),
80
+ 'event_start_time' => array( 'name'=>'start_time', 'type'=>'%s', 'null'=>true ),
81
+ 'event_end_time' => array( 'name'=>'end_time', 'type'=>'%s', 'null'=>true ),
82
+ 'event_all_day' => array( 'name'=>'all_day', 'type'=>'%d', 'null'=>true ),
83
+ 'event_start_date' => array( 'name'=>'start_date', 'type'=>'%s', 'null'=>true ),
84
+ 'event_end_date' => array( 'name'=>'end_date', 'type'=>'%s', 'null'=>true ),
85
+ 'post_content' => array( 'name'=>'notes', 'type'=>'%s', 'null'=>true ),
86
+ 'event_rsvp' => array( 'name'=>'rsvp', 'type'=>'%d', 'null'=>true ), //has a default, so can be null/excluded
87
+ //'event_spaces' => array( 'name'=>'spaces', 'type'=>'%d' ),
88
+ 'location_id' => array( 'name'=>'location_id', 'type'=>'%d', 'null'=>true ),
89
+ 'recurrence_id' => array( 'name'=>'recurrence_id', 'type'=>'%d', 'null'=>true ),
90
+ 'event_status' => array( 'name'=>'status', 'type'=>'%d', 'null'=>true ),
91
+ 'event_private' => array( 'name'=>'status', 'type'=>'%d', 'null'=>true ),
92
+ 'event_date_created' => array( 'name'=>'date_created', 'type'=>'%s', 'null'=>true ),
93
+ 'event_date_modified' => array( 'name'=>'date_modified', 'type'=>'%s', 'null'=>true ),
94
+ 'event_attributes' => array( 'name'=>'attributes', 'type'=>'%s', 'null'=>true ),
95
+ 'blog_id' => array( 'name'=>'blog_id', 'type'=>'%d', 'null'=>true ),
96
+ 'group_id' => array( 'name'=>'group_id', 'type'=>'%d', 'null'=>true ),
97
+ 'recurrence' => array( 'name'=>'recurrence', 'type'=>'%d', 'null'=>true ), //every x day(s)/week(s)/month(s)
98
+ 'recurrence_interval' => array( 'name'=>'interval', 'type'=>'%d', 'null'=>true ), //every x day(s)/week(s)/month(s)
99
+ 'recurrence_freq' => array( 'name'=>'freq', 'type'=>'%s', 'null'=>true ), //daily,weekly,monthly?
100
+ 'recurrence_days' => array( 'name'=>'days', 'type'=>'%d', 'null'=>true ), //daily,weekly,monthly?
101
+ 'recurrence_byday' => array( 'name'=>'byday', 'type'=>'%s', 'null'=>true ), //if weekly or monthly, what days of the week?
102
+ 'recurrence_byweekno' => array( 'name'=>'byweekno', 'type'=>'%d', 'null'=>true ), //if monthly which week (-1 is last)
103
  );
104
+ var $post_fields = array('event_slug','event_owner','event_name','event_attributes','post_id','post_content'); //fields that won't be taken from the em_events table anymore
105
+ var $recurrence_fields = array('recurrence_interval', 'recurrence_freq', 'recurrence_days', 'recurrence_byday', 'recurrence_byweekno');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
106
 
107
+ var $image_url = '';
108
  /**
109
  * Timestamp of start date/time
110
  * @var int
154
  * @var string
155
  */
156
  var $feedback_message;
157
+ /**
158
+ * Any warnings about an event (e.g. bad data, recurrence, etc.)
159
+ * @var string
160
+ */
161
+ var $warnings;
162
  /**
163
  * Array of dbem_event field names required to create an event
164
  * @var array
165
  */
166
  var $required_fields = array('event_name', 'event_start_date');
167
+ var $mime_types = array(1 => 'gif', 2 => 'jpg', 3 => 'png');
168
+ /**
169
+ * previous status of event when instantiated
170
+ * @access protected
171
+ * @var mixed
172
+ */
173
+ var $previous_status = 0;
174
 
175
  /**
176
  * Initialize an event. You can provide event data in an associative array (using database table field names), an id number, or false (default) to create empty event.
177
  * @param mixed $event_data
178
+ * @param mixed $search_by default is post_id, otherwise it can be by event_id as well.
179
  * @return null
180
  */
181
+ function __construct($id = false, $search_by = 'event_id') {
182
+ global $wpdb;
183
+ if( is_array($id) ){
184
+ //deal with the old array style, but we can't supply arrays anymore
185
+ $id = (!empty($id['event_id'])) ? $id['event_id'] : $id['post_id'];
186
+ $search_by = (!empty($id['event_id'])) ? 'event_id':'post_id';
187
+ }
188
+ $is_post = !empty($id->ID) && ($id->post_type == EM_POST_TYPE_EVENT || $id->post_type == 'event-recurring');
189
+ if( is_numeric($id) || $is_post ){ //only load info if $id is a number
190
+ if($search_by == 'event_id' && !$is_post ){
191
+ //search by event_id, get post_id and blog_id (if in ms mode) and load the post
192
+ $results = $wpdb->get_row($wpdb->prepare("SELECT post_id, blog_id FROM ".EM_EVENTS_TABLE." WHERE event_id=%d",$id), ARRAY_A);
193
+ if( is_multisite() && is_numeric($results['blog_id']) ){
194
+ $event_post = get_blog_post($results['blog_id'], $results['post_id']);
195
+ $search_by = $results['blog_id'];
196
+ }else{
197
+ $event_post = get_post($results['post_id']);
 
 
 
 
 
 
 
 
 
 
 
 
 
198
  }
199
+ }else{
200
+ if(!$is_post){
201
+ if( is_numeric($search_by) && is_multisite() ){
202
+ //we've been given a blog_id, so we're searching for a post id
203
+ $event_post = get_blog_post($search_by, $id);
204
+ }else{
205
+ //search for the post id only
206
+ $event_post = get_post($id);
207
+ }
208
+ }else{
209
+ $event_post = $id;
 
 
 
 
210
  }
211
  }
212
+ $this->load_postdata($event_post, $search_by);
213
+ }
214
+ $this->recurrence = $this->is_recurring() ? 1:0;
215
+ //if(defined('trashtest')){ print_r($this); die("got here");}
216
+ //Do it here so things appear in the po file.
217
+ $this->status_array = array(
218
+ 0 => __('Pending','dbem'),
219
+ 1 => __('Approved','dbem')
220
+ );
221
+ do_action('em_event', $this, $id, $search_by);
222
+ }
223
+
224
+ function load_postdata($event_post, $search_by = false){
225
+ if( is_object($event_post) ){
226
+ if( $event_post->post_status != 'auto-draft' ){
227
+ if( is_numeric($search_by) && is_multisite() ){
228
+ // if in multisite mode, switch blogs quickly to get the right post meta.
229
+ switch_to_blog($search_by);
230
+ $event_meta = get_post_custom($event_post->ID);
231
+ restore_current_blog();
232
+ $this->blog_id = $search_by;
233
+ }else{
234
+ $event_meta = get_post_custom($event_post->ID);
235
+ }
236
+ //Get custom fields and post meta
237
+ foreach($event_meta as $event_meta_key => $event_meta_val){
238
+ if($event_meta_key[0] != '_'){
239
+ $this->event_attributes[$event_meta_key] = ( count($event_meta_val) > 1 ) ? $event_meta_val:$event_meta_val[0];
240
+ }else{
241
+ foreach($this->fields as $field_name => $field_info){
242
+ if( $event_meta_key == '_'.$field_name && $event_meta_key != '_event_attributes'){
243
+ $this->$field_name = $event_meta_val[0];
244
+ }
245
+ }
246
+ }
247
+ }
248
+ //Start/End times should be available as timestamp
249
+ $this->start = strtotime($this->event_start_date." ".$this->event_start_time);
250
+ $this->end = strtotime($this->event_end_date." ".$this->event_end_time);
251
+ //quick compatability fix in case _event_id isn't loaded or somehow got erased in post meta
252
+ if( empty($this->event_id) && !$this->is_recurring() ){
253
+ global $wpdb;
254
+ $event_array = $wpdb->get_row('SELECT * FROM '.EM_EVENTS_TABLE. ' WHERE post_id='.$event_post->ID, ARRAY_A);
255
+ if( !empty($event_array['event_id']) ){
256
+ foreach($event_array as $key => $value){
257
+ if( !empty($value) && empty($this->$key) ){
258
+ update_post_meta($event_post->ID, '_'.$key, $value);
259
+ $this->$key = $value;
260
+ }
261
+ }
262
+ }
263
+ }
264
  }
265
+ //load post data - regardless
266
+ $this->post_id = $event_post->ID;
267
+ $this->event_name = $event_post->post_title;
268
+ $this->event_owner = $event_post->post_author;
269
+ $this->post_content = $event_post->post_content;
270
+ $this->event_slug = $event_post->post_name;
271
+ $this->event_modified = $event_post->post_modified;
272
+ foreach( $event_post as $key => $value ){ //merge post object into this object
273
+ $this->$key = $value;
274
  }
275
+ $this->previous_status = $this->event_status; //so we know about updates
276
+ $this->recurrence = $this->is_recurring() ? 1:0;
277
+ $this->get_status();
278
+ $this->compat_keys();
279
  }
280
  }
281
 
282
  /**
283
+ * Retrieve event information via POST (only used in situations where posts aren't submitted via WP)
284
  * @return boolean
285
  */
286
+ function get_post($validate = true){
287
+ global $allowedposttags;
288
+ //we need to get the post/event name and content.... that's it.
289
+ $this->post_content = !empty($_POST['content']) ? wp_kses($_POST['content'], $allowedposttags):'';
290
+ $this->event_name = !empty($_POST['event_name']) ? wp_kses($_POST['event_name'], array()):'';
291
+ $this->post_type = ($this->is_recurring() || !empty($_POST['recurring'])) ? 'event-recurring':EM_POST_TYPE_EVENT;
292
+ //don't forget categories!
293
+ $this->get_categories()->get_post();
294
+ $this->get_post_meta(false);
295
+ $result = $validate ? $this->validate():true; //validate both post and meta, otherwise return true
296
+ return apply_filters('em_event_get_post', $result, $this);
297
+ }
298
+
299
+ /**
300
+ * Retrieve event post meta information via POST, which should be always be called when saving the event custom post via WP.
301
+ * @param boolean $validate whether or not to run validation, default is true
302
+ * @return boolean
303
+ */
304
+ function get_post_meta($validate = true){
305
+ //Grab POST data
306
+ $this->event_start_date = ( !empty($_POST['event_start_date']) ) ? $_POST['event_start_date'] : '';
307
+ $this->event_end_date = ( !empty($_POST['event_end_date']) ) ? $_POST['event_end_date'] : $this->event_start_date;
308
+ //check if this is recurring or not
309
+ if( $_REQUEST['recurring'] ){
310
+ $this->recurrence = 1;
311
+ $this->post_type = 'event-recurring';
312
+ }
313
+ //Get Location info
314
+ if( get_option('dbem_disable_locations',false) || (!empty($_POST['no_location']) && !get_option('dbem_require_location',true)) || (empty($_POST['location_id']) && !get_option('dbem_require_location',true) && get_option('dbem_use_select_for_locations')) ){
315
+ $this->location_id = 0;
316
+ }elseif( !empty($_POST['location_id']) && is_numeric($_POST['location_id']) ){
317
+ $this->location_id = $_POST['location_id'];
318
  }else{
319
+ //we're adding a new location, so create an empty location and populate
320
+ $this->location_id = null;
321
+ $this->get_location()->get_post(false);
322
+ }
323
+ //Sort out time
324
+ $this->event_all_day = ( !empty($_POST['event_all_day']) ) ? 1 : 0;
325
+ if( !$this->event_all_day ){
326
+ $match = array();
327
+ foreach( array('event_start_time','event_end_time') as $timeName ){
328
+ if( !empty($_POST[$timeName]) && preg_match ( '/^([01]\d|2[0-3]):([0-5]\d) ?(AM|PM)?$/', $_POST[$timeName], $match ) ){
329
+ if( !empty($match[3]) && $match[3] == 'PM' && $match[1] != 12 ){
330
+ $match[1] = 12+$match[1];
331
+ }elseif( !empty($match[3]) && $match[3] == 'AM' && $match[1] == 12 ){
332
+ $match[1] = '00';
333
+ }
334
+ $this->$timeName = $match[1].":".$match[2].":00";
335
+ }else{
336
+ $this->$timeName = ($timeName == 'event_start_time') ? "00:00:00":$this->event_start_time;
337
+ }
338
+ }
339
  }else{
340
+ $this->event_start_time = $this->event_end_time = '00:00:00';
341
  }
342
  //Start/End times should be available as timestamp
343
+ $this->start = strtotime($this->event_start_date." ".$this->event_start_time);
344
+ $this->end = strtotime($this->event_end_date." ".$this->event_end_time);
345
+ //Bookings
346
+ if( !empty($_REQUEST['event_rsvp']) && $_REQUEST['event_rsvp'] ){
347
+ $this->get_bookings()->get_tickets()->get_post();
348
+ $this->event_rsvp = 1;
349
+ }else{
350
+ $this->event_rsvp = 0;
351
+ }
352
+ //Sort out event attributes - note that custom post meta now also gets inserted here automatically (and is overwritten by these attributes)
353
+ if(get_option('dbem_attributes_enabled')){
354
+ global $allowedtags;
355
+ if( !is_array($this->event_attributes) ){ $this->event_attributes = array(); }
356
+ $event_available_attributes = em_get_attributes();
357
+ if( !empty($_POST['em_attributes']) && is_array($_POST['em_attributes']) ){
358
+ foreach($_POST['em_attributes'] as $att_key => $att_value ){
359
+ if( (in_array($att_key, $event_available_attributes['names']) || array_key_exists($att_key, $this->event_attributes) ) && trim($att_value) != '' ){
360
+ $att_vals = count($event_available_attributes['values'][$att_key]);
361
+ if( $att_vals == 0 || ($att_vals > 0 && in_array($att_value, $event_available_attributes['values'][$att_key])) ){
362
+ $this->event_attributes[$att_key] = stripslashes($att_value);
363
+ }elseif($att_vals > 0){
364
+ $this->event_attributes[$att_key] = stripslashes(wp_kses($event_available_attributes['values'][$att_key][0], $allowedtags));
365
+ }
366
+ }
367
+ }
368
+ }
369
+ }
370
+ //Set Blog ID
371
+ if( is_multisite() ){
372
+ $this->blog_id = get_current_blog_id();
373
+ }
374
+ //group id
375
+ $this->group_id = (!empty($_POST['group_id']) && is_numeric($_POST['group_id'])) ? $_POST['group_id']:$this->group_id;
376
  //Recurrence data
377
+ if( $this->is_recurring() ){
378
+ $this->recurrence = 1; //just in case
379
+ $this->recurrence_freq = ( !empty($_REQUEST['recurrence_freq']) && in_array($_REQUEST['recurrence_freq'], array('daily','weekly','monthly')) ) ? $_REQUEST['recurrence_freq']:'daily';
380
+ if( !empty($_REQUEST['recurrence_bydays']) && $this->recurrence_freq == 'weekly' && self::array_is_numeric($_REQUEST['recurrence_bydays']) ){
381
+ $this->recurrence_byday = implode( ",", $_REQUEST['recurrence_bydays'] );
382
+ }elseif( !empty($_REQUEST['recurrence_byday']) && $this->recurrence_freq == 'monthly' ){
383
+ $this->recurrence_byday = $_REQUEST['recurrence_byday'];
 
384
  }
385
+ $this->recurrence_interval = ( !empty($_REQUEST['recurrence_interval']) && is_numeric($_REQUEST['recurrence_interval']) ) ? $_REQUEST['recurrence_interval']:1;
386
+ $this->recurrence_byweekno = ( !empty($_REQUEST['recurrence_byweekno']) ) ? $_REQUEST['recurrence_byweekno']:'';
387
+ $this->recurrence_days = ( !empty($_REQUEST['recurrence_days']) && is_numeric($_REQUEST['recurrence_days']) ) ? $_REQUEST['recurrence_days']:1;
388
  }
389
+ //categories in MS GLobal
390
+ if(EM_MS_GLOBAL && !is_main_site()){
391
+ $this->get_categories()->get_post(); //it'll know what to do
392
+ }
393
+ $result = $validate ? $this->validate_meta():true;
394
+ $this->compat_keys(); //compatability
395
+ return apply_filters('em_event_get_post', $result, $this);
396
+ }
397
+
398
+ function validate(){
399
+ $validate_post = true;
400
+ if( empty($this->event_name) ){
401
+ $validate_post = false;
402
+ $this->add_error( __('Event name').__(" is required.", "dbem") );
403
+ }
404
+ $validate_meta = $this->validate_meta();
405
+ return apply_filters('em_event_validate', $validate_post && $validate_meta, $this );
406
+ }
407
+ function validate_meta(){
408
+ $missing_fields = Array ();
409
+ foreach ( array('event_start_date') as $field ) {
410
+ if ( $this->$field == "") {
411
+ $missing_fields[$field] = $field;
412
+ }
413
+ }
414
+ if( preg_match('/\d{4}-\d{2}-\d{2}/', $this->event_start_date) && preg_match('/\d{4}-\d{2}-\d{2}/', $this->event_end_date) ){
415
+ if( strtotime($this->event_start_date . $this->event_start_time) > strtotime($this->event_end_date . $this->event_end_time) ){
416
+ $this->add_error(__('Events cannot start after they end.','dbem'));
417
+ }
418
+ }else{
419
+ if( !empty($missing_fields['event_start_date']) ) { unset($missing_fields['event_start_date']); }
420
+ if( !empty($missing_fields['event_end_date']) ) { unset($missing_fields['event_end_date']); }
421
+ $this->add_error(__('Dates must have correct formatting. Please use the date picker provided.','dbem'));
422
+ }
423
+ if( $this->event_rsvp && !$this->get_bookings()->get_tickets()->validate() ){
424
+ $this->add_error($this->get_bookings()->get_tickets()->get_errors());
425
+ }
426
+ if( !get_option('dbem_disable_locations',false) && empty($this->location_id) ){ //location ids don't need validating as we're not saving a location
427
+ if( get_option('dbem_require_location',true) || $this->location_id !== 0 ){
428
+ if( !$this->get_location()->validate() ){
429
+ $this->add_error($this->get_location()->get_errors());
430
+ }
431
+ }
432
+ }
433
+ if ( count($missing_fields) > 0){
434
+ // TODO Create friendly equivelant names for missing fields notice in validation
435
+ $this->add_error( __( 'Missing fields: ', 'dbem') . implode ( ", ", $missing_fields ) . ". " );
436
+ }
437
+ if ( $this->is_recurring() && ($this->event_end_date == "" || $this->event_end_date == $this->event_start_date) ){
438
+ $this->add_error( __( 'Since the event is repeated, you must specify an event end date greater than the start date.', 'dbem' ));
439
  }
440
+ return apply_filters('em_event_validate_meta', count($this->errors) == 0, $this );
441
  }
442
 
443
  /**
444
  * Will save the current instance into the database, along with location information if a new one was created and return true if successful, false if not.
445
+ * Will automatically detect whether it's a new or existing event.
446
  * @return boolean
447
  */
448
  function save(){
449
+ global $wpdb, $current_user, $blog_id;
450
+ if( !$this->can_manage('edit_events', 'edit_others_events') && !( get_option('dbem_events_anonymous_submissions') && empty($this->event_id)) ){
451
+ //unless events can be submitted by an anonymous user (and this is a new event), user must have permissions.
452
  return apply_filters('em_event_save', false, $this);
453
  }
454
+ remove_action('save_post',array('EM_Event_Post_Admin','save_post'),10,1); //disable the default save post action, we'll do it manually this way
455
  do_action('em_event_save_pre', $this);
456
+ $post_array = array();
457
+ //Deal with updates to an event
458
+ if( !empty($this->post_id) ){
459
+ //get the full array of post data so we don't overwrite anything.
460
+ if( !empty($this->blog_id) && is_multisite() ){
461
+ $post_array = (array) get_blog_post($this->blog_id, $this->post_id);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
462
  }else{
463
+ $post_array = (array) get_post($this->post_id);
 
 
 
 
 
 
464
  }
 
465
  }
466
+ //Overwrite new post info
467
+ $post_array['post_type'] = ($this->recurrence && get_option('dbem_recurrence_enabled')) ? 'event-recurring':EM_POST_TYPE_EVENT;
468
+ $post_array['post_title'] = $this->event_name;
469
+ $post_array['post_content'] = $this->post_content;
470
+ //decide on post status
471
+ if( count($this->errors) == 0 ){
472
+ $post_array['post_status'] = ( $this->can_manage('publish_events','publish_events') ) ? 'publish':'pending';
473
+ }else{
474
+ $post_array['post_status'] = 'draft';
475
+ }
476
+ //anonymous submission only
477
+ if( !is_user_logged_in() && get_option('dbem_events_anonymous_submissions') && empty($this->event_id) ){
478
+ $post_array['post_author'] = get_option('dbem_events_anonymous_user');
479
+ if( !is_numeric($post_array['post_author']) ) $post_array['post_author'] = 0;
480
+ }
481
+ //Save post and continue with meta
482
+ $post_id = wp_insert_post($post_array);
483
+ $post_save = false;
484
+ $meta_save = false;
485
+ if( !is_wp_error($post_id) && !empty($post_id) ){
486
+ $post_save = true;
487
+ //refresh this event with wp post info we'll put into the db
488
+ $post_data = get_post($post_id);
489
+ $this->post_id = $post_id;
490
+ $this->event_slug = $post_data->post_name;
491
+ $this->event_owner = $post_data->post_author;
492
+ $this->post_status = $post_data->post_status;
493
+ $this->get_status();
494
+ //Categories? note that categories will soft-fail, so no errors
495
+ $this->get_categories()->save();
496
+ //now save the meta
497
+ $meta_save = $this->save_meta();
498
+ //save the image
499
+ $this->image_upload();
500
+ $image_save = (count($this->errors) == 0); //whilst it might not be an image save that fails, we can know something went wrong
501
+ }
502
+ $result = $meta_save && $post_save && $image_save;
503
+ $previous_status = $this->previous_status;
504
+ if($result) $this->load_postdata($post_data, $blog_id); //reload post info
505
+ $this->previous_status = $previous_status;
506
+ return apply_filters('em_event_save', $result, $this);
507
  }
508
 
509
+ function save_meta(){
 
 
 
 
 
510
  global $wpdb;
511
+ if( ( get_option('dbem_events_anonymous_submissions') && empty($this->event_id)) || $this->can_manage('edit_events', 'edit_others_events') ){
512
+ do_action('em_event_save_meta_pre', $this);
513
+ //first save location
514
+ if( empty($this->location_id) && !($this->location_id === 0 && !get_option('dbem_require_location',true)) ){
515
+ if( get_site_option('dbem_ms_mainblog_locations') ){ $this->ms_global_switch(); }
516
+ if( !$this->get_location()->save() ){ //soft fail
517
+ global $EM_Notices;
518
+ $this->get_location()->set_status(null);
519
+ $EM_Notices->add_error( sprintf(__('There were some errors saving your location, and it will not be displayed on the website listings, to correct this you must <a href="%s">edit your location</a> directly.'),$this->get_location()->output('#_LOCATIONEDITURL')), true);
520
+ }
521
+ if( get_site_option('dbem_ms_mainblog_locations') ){ $this->ms_global_switch_back(); }
522
+ if( !empty($this->location->location_id) ){ //only case we don't use get_location(), since it will fail as location has an id, whereas location_id isn't set in this object
523
+ $this->location_id = $this->location->location_id;
524
+ }
525
  }
526
+ //Update Post Meta
527
+ foreach($this->fields as $key => $field_info){
528
+ if( !in_array($key, $this->post_fields) && $key != 'event_attributes' ){
529
+ update_post_meta($this->post_id, '_'.$key, $this->$key);
530
+ }elseif($key == 'event_attributes'){
531
+ //attributes get saved as individual keys
532
+ foreach($this->event_attributes as $event_attribute_key => $event_attribute){
533
+ update_post_meta($this->post_id, $event_attribute_key, $event_attribute);
534
+ }
535
+ }
536
+ }
537
+ update_post_meta($this->post_id, '_start_ts', strtotime($this->event_start_date));
538
+ update_post_meta($this->post_id, '_end_ts', strtotime($this->event_end_date));
539
+
540
+ $result = count($this->errors) == 0;
541
+ $this->get_status();
542
+ $this->event_status = ($result) ? $this->event_status:null; //set status at this point, it's either the current status, or if validation fails, null
543
+ //Save to em_event table
544
+ $event_array = $this->to_array(true);
545
+ unset($event_array['event_id']);
546
+ if( $this->post_status == 'private' ) $event_array['event_private'] = 1;
547
+ $event_array['event_attributes'] = serialize($this->event_attributes); //might as well
548
+ if( empty($this->event_id) ){
549
+ $this->previous_status = 0; //for sure this was previously status 0
550
+ $this->event_date_created = current_time('mysql');
551
+ if ( !$wpdb->insert(EM_EVENTS_TABLE, $event_array) ){
552
+ $this->add_error( sprintf(__('Something went wrong saving your %s to the index table. Please inform a site administrator about this.','dbem'),__('event','dbem')));
553
+ }else{
554
+ //success, so link the event with the post via an event id meta value for easy retrieval
555
+ $this->event_id = $wpdb->insert_id;
556
+ update_post_meta($this->post_id, '_event_id', $this->event_id);
557
+ $this->feedback_message = sprintf(__('Successfully saved %s','dbem'),__('Event','dbem'));
558
+ }
559
+ }else{
560
+ $this->previous_status = $this->get_previous_status();
561
+ $this->event_date_modified = current_time('mysql');
562
+ if ( $wpdb->update(EM_EVENTS_TABLE, $event_array, array('event_id'=>$this->event_id) ) === false ){
563
+ $this->add_error( sprintf(__('Something went wrong updating your %s to the index table. Please inform a site administrator about this.','dbem'),__('event','dbem')));
564
+ }else{
565
+ $this->feedback_message = sprintf(__('Successfully saved %s','dbem'),__('Event','dbem'));
566
+ }
567
+ }
568
+ //Add/Delete Tickets
569
+ if($this->event_rsvp == 0){
570
+ $this->get_bookings()->delete();
571
+ }else{
572
+ if( !$this->get_bookings()->get_tickets()->save() ){
573
+ $this->add_error( $this->get_bookings()->get_tickets()->get_errors() );
574
+ }
575
+ }
576
+ $result = count($this->errors) == 0;
577
+ //If we're saving event categories in MS Global mode, we'll add them here, saving by term id (cat ids are gone now)
578
+ if( EM_MS_GLOBAL && !is_main_site() ){
579
+ $this->get_categories()->save(); //it'll know what to do
580
+ }elseif( EM_MS_GLOBAL ){
581
+ $this->get_categories()->save_index(); //just save to index, we assume cats are saved in $this->save();
582
+ }
583
+ //build recurrences if needed
584
+ if( $this->is_recurring() && $result && $this->is_published() ){ //only save events if recurring event validates and is published
585
+ if( !$this->save_events() ){ //only save if post is 'published'
586
+ $this->add_error(__ ( 'Something went wrong with the recurrence update...', 'dbem' ). __ ( 'There was a problem saving the recurring events.', 'dbem' ));
587
+ }
588
  }
589
  }
590
+ return apply_filters('em_event_save_meta', count($this->errors) == 0, $this);
591
  }
592
 
593
  /**
597
  function duplicate(){
598
  global $wpdb, $EZSQL_ERROR;
599
  //First, duplicate.
600
+ if( $this->can_manage('edit_events','edit_others_events') ){
601
+ $EM_Event = clone $this;
602
+ $EM_Event->event_id = null;
603
+ //Duplicate Post
604
+ $fields = $wpdb->get_col("DESCRIBE ".$wpdb->posts);
605
+ unset($fields[0]);
606
+ $fields = implode(',',$fields);
607
+ $sql = "INSERT INTO {$wpdb->posts} ($fields) SELECT $fields FROM {$wpdb->posts} WHERE ID={$this->post_id}";
608
+ $result = $wpdb->query($sql);
609
+ $EM_Event->post_id = $EM_Event->ID = $wpdb->insert_id;
610
+ //Duplicate Event Table index and tickets
611
+ if( $EM_Event->save_meta() ){
612
+ //duplicate tickets
613
+ $EM_Tickets = $this->get_bookings()->get_tickets();
614
+ foreach($EM_Tickets->tickets as $EM_Ticket){
615
+ $EM_Ticket->ticket_id = '';
616
+ $EM_Ticket->event_id = $EM_Event->event_id;
617
+ $EM_Ticket->save();
618
+ }
619
+ $EM_Event->get_bookings(true); //refresh booking tickets
620
+ $EM_Event->feedback_message = sprintf(__("%s successfully duplicated.", 'dbem'), __('Event','dbem'));
621
  return apply_filters('em_event_duplicate', $EM_Event, $this);
622
  }
623
  }
625
  return apply_filters('em_event_duplicate', false, $this);;
626
  }
627
 
 
628
  /**
629
+ * Delete whole event, including bookings, tickets, etc.
630
  * @return boolean
631
  */
632
+ function delete($force_delete = true){ //atm wp seems to force cp deletions anyway
633
+ global $wpdb;
634
+ if( $this->can_manage('delete_events', 'delete_others_events') ){
635
+ remove_action('before_delete_post',array('EM_Event_Post_Admin','before_delete_post'),10,1); //since we're deleting directly, remove post actions
636
+ do_action('em_event_delete_pre', $this);
637
+ $result = wp_delete_post($this->post_id,$force_delete);
638
+ if( $force_delete ){
639
+ $result_meta = $this->delete_meta();
640
  }
641
+ }else{
642
+ $result = $result_meta = false;
643
  }
644
+ //print_r($result); echo "|"; print_r($result_meta); die('DELETING');
645
+ return apply_filters('em_event_delete', $result !== false && $result_meta, $this);
646
+ }
647
+
648
+ function delete_meta(){
649
+ global $wpdb;
650
+ $result = false;
651
+ if( $this->can_manage('delete_events', 'delete_others_events') ){
652
+ do_action('em_event_delete_meta_event_pre', $this);
653
+ $result = $wpdb->query ( $wpdb->prepare("DELETE FROM ". EM_EVENTS_TABLE ." WHERE event_id=%d", $this->event_id) );
654
+ if( $result !== false ){
655
+ $this->delete_bookings();
656
+ $this->delete_tickets();
657
+ //Delete the recurrences then this recurrence event
658
+ if( $this->is_recurring() ){
659
+ $result = $this->delete_events(); //was true at this point, so false if fails
660
+ }
661
+ //Delete categories from meta if in MS global mode
662
+ if( EM_MS_GLOBAL ){
663
+ $wpdb->query('DELETE FROM '.EM_CATEGORIES_TABLE.' WHERE object_id='.$this->event_id." AND meta_key='event-category'");
664
+ }
665
+ }
666
+ }
667
+ return apply_filters('em_event_delete_meta', $result !== false, $this);
668
+ }
669
+
670
+ /**
671
+ * Shortcut function for $this->get_bookings()->delete(), because using the EM_Bookings requires loading previous bookings, which isn't neceesary.
672
+ */
673
+ function delete_bookings(){
674
+ global $wpdb;
675
+ do_action('em_event_delete_bookings_pre', $this);
676
+ $result = false;
677
+ if( $this->can_manage('manage_bookings','manage_others_bookings') ){
678
+ $result_bt = $wpdb->query( $wpdb->prepare("DELETE FROM ".EM_TICKETS_BOOKINGS_TABLE." WHERE booking_id IN (SELECT booking_id FROM ".EM_BOOKINGS_TABLE." WHERE event_id=%d)", $this->id) );
679
+ $result = $wpdb->query( $wpdb->prepare("DELETE FROM ".EM_BOOKINGS_TABLE." WHERE event_id=%d", $this->id) );
680
  }
681
+ return apply_filters('em_event_delete_bookings', $result !== false && $result_bt !== false, $this);
682
+ }
683
+
684
+ /**
685
+ * Shortcut function for $this->get_bookings()->delete(), because using the EM_Bookings requires loading previous bookings, which isn't neceesary.
686
+ */
687
+ function delete_tickets(){
688
+ global $wpdb;
689
+ do_action('em_event_delete_tickets_pre', $this);
690
+ $result = false;
691
+ if( $this->can_manage('manage_bookings','manage_others_bookings') ){
692
+ $result_bt = $wpdb->query( $wpdb->prepare("DELETE FROM ".EM_TICKETS_BOOKINGS_TABLE." WHERE ticket_id IN (SELECT ticket_id FROM ".EM_TICKETS_TABLE." WHERE event_id=%d)", $this->id) );
693
+ $result = $wpdb->query( $wpdb->prepare("DELETE FROM ".EM_TICKETS_TABLE." WHERE event_id=%d", $this->id) );
694
  }
695
+ return apply_filters('em_event_delete_tickets', $result, $this);
696
+ }
697
+
698
+ /**
699
+ * Publish Events
700
+ * @return bool
701
+ */
702
+ function send_approval_notification(){
703
+ if( (!$this->is_recurring() && !user_can($this->event_owner, 'publish_events')) || ($this->is_recurring() && !user_can($this->event_owner, 'publish_recurring_events')) ){
704
+ //only send email to users that can't publish events themselves and that were previously unpublished
705
+ if( !$this->previous_status && $this->is_published() ){
706
+ //email
707
+ if( $this->event_owner == "" ) return true;
708
+ $subject = $this->output(get_option('dbem_event_approved_email_subject'), 'email');
709
+ $body = $this->output(get_option('dbem_event_approved_email_body'), 'email');
710
+
711
+ //Send to the person booking
712
+ if( !$this->email_send( $subject, $body, $this->get_contact()->user_email) ){
713
+ return false;
714
+ }
715
+ return true;
716
+ }
717
+ }
718
+ return false;
719
+ }
720
+
721
+ /**
722
+ * Change the status of the event. This will save to the Database too.
723
+ * @param int $status
724
+ * @param boolean $set_post_status
725
+ * @return string
726
+ */
727
+ function set_status($status, $set_post_status = false){
728
+ global $wpdb;
729
+ if($status === null){
730
+ $set_status='NULL';
731
+ if($set_post_status){
732
+ //if the post is trash, don't untrash it!
733
+ $wpdb->update( $wpdb->posts, array( 'post_status' => 'draft' ), array( 'ID' => $this->post_id ) );
734
+ $this->post_status = 'draft';
735
  }
736
  }else{
737
+ $set_status = $status ? 1:0;
738
+ if($set_post_status){
739
+ $this->post_status = $post_status = $set_status ? 'publish':'pending';
740
+ $wpdb->update( $wpdb->posts, array( 'post_status' => $post_status ), array( 'ID' => $this->post_id ) );
741
+ }
742
  }
743
+ $this->previous_status = $this->get_previous_status();
744
+ $result = $wpdb->query("UPDATE ".EM_EVENTS_TABLE." SET event_status=$set_status WHERE event_id=".$this->event_id);
745
+ $this->get_status(); //reload status
746
+ return apply_filters('em_event_set_status', $result !== false, $status, $this);
747
+ }
748
+
749
+ function is_published(){
750
+ return apply_filters('em_event_is_published', ($this->post_status == 'publish' || $this->post_status == 'private'), $this);
751
+ }
752
+
753
+ function get_status($db = false){
754
+ switch( $this->post_status ){
755
+ case 'private':
756
+ $this->event_private = 1;
757
+ $this->event_status = $status = 1;
758
+ break;
759
+ case 'publish':
760
+ $this->event_private = 0;
761
+ $this->event_status = $status = 1;
762
+ break;
763
+ case 'pending':
764
+ $this->event_private = 0;
765
+ $this->event_status = $status = 0;
766
+ break;
767
+ default: //draft or unknown
768
+ $this->event_private = 0;
769
+ $status = $db ? 'NULL':null;
770
+ $this->event_status = null;
771
+ break;
772
  }
773
+ return $status;
774
+ }
775
+
776
+ function get_previous_status(){
777
+ global $wpdb;
778
+ return $wpdb->get_var('SELECT event_status FROM '.EM_EVENTS_TABLE.' WHERE event_id='.$this->event_id); //get status from db, not post_status, as posts get saved quickly
779
  }
 
780
 
781
  /**
782
+ * Returns an EM_Categories object of the EM_Event instance.
783
+ * @return EM_Categories
784
  */
785
+ function get_categories() {
786
+ if( empty($this->categories) ){
787
+ $this->categories = new EM_Categories($this);
788
+ }elseif(empty($this->categories->event_id)){
789
+ $this->categories->event_id = $this->event_id;
790
+ $this->categories->post_id = $this->post_id;
 
 
791
  }
792
+ return apply_filters('em_event_get_categories', $this->categories, $this);
 
 
 
 
793
  }
794
 
795
  /**
796
+ * Returns the location object this event belongs to.
797
+ * @return EM_Location
798
  */
799
+ function get_location() {
800
+ global $EM_Location;
801
+ if( is_object($EM_Location) && $EM_Location->location_id == $this->location_id ){
802
+ $this->location = $EM_Location;
803
+ }else{
804
+ if( !is_object($this->location) || $this->location->location_id != $this->location_id ){
805
+ $this->location = em_get_location($this->location_id);
806
+ }
807
+ }
808
+ return $this->location;
809
+ }
810
+
811
+ /**
812
+ * Returns the location object this event belongs to.
813
+ * @return EM_Person
814
+ */
815
+ function get_contact(){
816
+ if( !is_object($this->contact) ){
817
+ $this->contact = new EM_Person($this->event_owner);
818
+ }else{
819
+ return $this->contact;
820
  }
 
821
  }
822
 
823
  /**
830
  if( (!$this->bookings || $force_reload) ){
831
  $this->bookings = new EM_Bookings($this);
832
  }
833
+ $this->bookings->event_id = $this->event_id; //always refresh event_id
834
+ }else{
835
+ return new EM_Bookings();
836
  }
837
  return apply_filters('em_event_get_bookings', $this->bookings, $this);
838
  }
839
 
840
+ /**
841
+ * Get the tickets related to this event.
842
+ * @param boolean $force_reload
843
+ * @return EM_Tickets
844
+ */
845
+ function get_tickets( $force_reload = false ){
846
+ return $this->get_bookings($force_reload)->get_tickets();
847
+ }
848
+
849
+ function is_free(){
850
+ $free = true;
851
+ if( isset($this->free) ) return $this->free;
852
+ foreach($this->get_tickets() as $EM_Ticket){
853
+ if( $EM_Ticket->price > 0 ){
854
+ $free = false;
855
+ }
856
+ }
857
+ return apply_filters('em_event_is_free',$free,$this);
858
+ }
859
+
860
+ /**
861
+ * Gets number of spaces in this event, dependent on ticket spaces or hard limit, whichever is smaller.
862
+ * @param boolean $force_refresh
863
+ * @return int
864
+ */
865
+ function get_spaces($force_refresh=false){
866
+ return $this->get_bookings()->get_spaces($force_refresh);
867
+ }
868
+
869
  /**
870
  * Will output a single event format of this event.
871
  * Equivalent of calling EM_Event::output( get_option ( 'dbem_single_event_format' ) )
876
  $format = get_option ( 'dbem_single_event_format' );
877
  return apply_filters('em_event_output_single', $this->output($format, $target), $this, $target);
878
  }
 
 
 
 
 
 
 
 
 
 
 
879
 
880
  /**
881
  * Will output a event in the format passed in $format by replacing placeholders within the format.
883
  * @param string $target
884
  * @return string
885
  */
886
+ function output($format, $target="html") {
887
  $event_string = $format;
888
+ //Time place holder that doesn't show if empty.
889
+ //TODO add filter here too
890
+ preg_match_all('/#@?_\{[A-Za-z0-9 -\/,\.\\\]+\}/', $format, $results);
891
+ foreach($results[0] as $result) {
892
+ if(substr($result, 0, 3 ) == "#@_"){
893
+ $date = 'end_date';
894
+ $offset = 4;
895
+ }else{
896
+ $date = 'start_date';
897
+ $offset = 3;
898
+ }
899
+ if( $date == 'end_date' && $this->event_end_date == $this->event_start_date ){
900
+ $replace = __( apply_filters('em_event_output_placeholder', '', $this, $result, $target) );
901
+ }else{
902
+ $replace = __( apply_filters('em_event_output_placeholder', mysql2date(substr($result, $offset, (strlen($result)-($offset+1)) ), $this->$date), $this, $result, $target) );
903
+ }
904
+ $event_string = str_replace($result,$replace,$event_string );
905
+ }
906
+ //This is for the custom attributes
907
+ preg_match_all('/#_ATT\{([^}]+)\}(\{([^}]+)\})?/', $format, $results);
908
+ foreach($results[0] as $resultKey => $result) {
909
+ //Strip string of placeholder and just leave the reference
910
+ $attRef = substr( substr($result, 0, strpos($result, '}')), 6 );
911
+ $attString = '';
912
+ if( is_array($this->event_attributes) && array_key_exists($attRef, $this->event_attributes) ){
913
+ $attString = $this->event_attributes[$attRef];
914
+ }elseif( !empty($results[3][$resultKey]) ){
915
+ //Check to see if we have a second set of braces;
916
+ $attString = $results[3][$resultKey];
917
+ }
918
+ $attString = apply_filters('em_event_output_placeholder', $attString, $this, $result, $target);
919
+ $event_string = str_replace($result, $attString ,$event_string );
920
+ }
921
+ //First let's do some conditional placeholder removals
922
+ preg_match_all('/\{([a-zA-Z0-9_]+)\}([^{]+)\{\/\1\}/', $event_string, $conditionals);
923
+ if( count($conditionals[0]) > 0 ){
924
+ //Check if the language we want exists, if not we take the first language there
925
+ foreach($conditionals[1] as $key => $condition){
926
+ $replacement = $conditionals[0][$key];
927
+ if ($condition == 'has_bookings') {
928
+ //check if there's a booking, if not, remove this section of code.
929
+ if($this->event_rsvp && get_option('dbem_rsvp_enabled')){
930
+ $replacement = substr($conditionals[0][$key], 14, strlen($conditionals[0][$key])-29); //29 = (15+14)
931
+ }else{
932
+ $replacement = '';
933
+ }
934
+ }
935
+ if ($condition == 'no_bookings') {
936
+ //check if there's a booking, if not, remove this section of code.
937
+ if(!$this->event_rsvp && get_option('dbem_rsvp_enabled')){
938
+ $replacement = substr($conditionals[0][$key], 13, strlen($conditionals[0][$key])-28); //28 = (13+14)
939
+ }else{
940
+ $replacement = '';
941
+ }
942
+ }
943
+ if ($condition == 'no_location'){
944
+ //does this event have a valid location?
945
+ if( empty($this->location_id) || !$this->get_location()->location_status ){
946
+ $replacement = substr($conditionals[0][$key], 13, strlen($conditionals[0][$key])-28); //28 = (13+14)
947
+ }else{
948
+ $replacement = '';
949
+ }
950
+ }
951
+ if ($condition == 'has_location'){
952
+ //does this event have a valid location?
953
+ if( !empty($this->location_id) && $this->get_location()->location_status ){
954
+ $replacement = substr($conditionals[0][$key], 14, strlen($conditionals[0][$key])-29); //28 = (13+14)
955
+ }else{
956
+ $replacement = '';
957
+ }
958
+ }
959
+ $event_string = str_replace($conditionals[0][$key], apply_filters('em_event_output_condition', $replacement, $condition, $conditionals[0][$key], $this), $event_string);
960
+ }
961
+ }
962
+ //Now let's check out the placeholders.
963
+ preg_match_all("/(#@?_?[A-Za-z0-9]+)({([a-zA-Z0-9,]+)})?/", $format, $placeholders);
964
+ foreach($placeholders[1] as $key => $result) {
965
  $match = true;
966
  $replace = '';
967
+ $full_result = $placeholders[0][$key];
968
  switch( $result ){
969
  //Event Details
970
  case '#_EVENTID':
971
  $replace = $this->id;
972
  break;
973
  case '#_NAME':
974
+ $replace = $this->event_name;
975
  break;
976
  case '#_NOTES':
977
  case '#_EXCERPT':
978
  //SEE AT BOTTOM OF FILE FOR OLD TARGET FILTERS FROM 2.x
979
+ $replace = $this->post_content;
980
  if($result == "#_EXCERPT"){
981
+ $matches = explode('<!--more', $this->post_content);
982
  $replace = $matches[0];
983
  }
984
  break;
985
+ case '#_EVENTIMAGEURL':
986
+ case '#_EVENTIMAGE':
987
+ if($this->get_image_url() != ''){
988
+ if($result == '#_EVENTIMAGEURL'){
989
+ $replace = $this->image_url;
990
+ }else{
991
+ if( empty($placeholders[3][$key]) ){
992
+ $replace = "<img src='".$this->image_url."' alt='".esc_attr($this->event_name)."'/>";
993
+ }else{
994
+ $image_size = explode(',', $placeholders[3][$key]);
995
+ if( $this->array_is_numeric($image_size) && count($image_size) > 1 ){
996
+ $replace = "<img src='".em_get_thumbnail_url($this->image_url, $image_size[0], $image_size[1])."' alt='".esc_attr($this->event_name)."'/>";
997
+ }else{
998
+ $replace = "<img src='".$this->image_url."' alt='".esc_attr($this->event_name)."'/>";
999
+ }
1000
+ }
1001
+ }
1002
+ }
1003
+ break;
1004
+ //Times & Dates
1005
  case '#_24HSTARTTIME':
1006
  case '#_24HENDTIME':
1007
+ $time = ($result == '#_24HSTARTTIME') ? $this->event_start_time:$this->event_end_time;
1008
  $replace = substr($time, 0,5);
1009
  break;
1010
  case '#_12HSTARTTIME':
1011
  case '#_12HENDTIME':
1012
+ $time = ($result == '#_12HSTARTTIME') ? $this->event_start_time:$this->event_end_time;
1013
  $replace = date('g:i A', strtotime($time));
1014
  break;
1015
+ case '#_EVENTTIMES':
1016
+ //get format of time to show
1017
+ if( !$this->event_all_day ){
1018
+ $time_format = ( get_option('dbem_time_format') ) ? get_option('dbem_time_format'):get_option('time_format');
1019
+ if($this->event_start_time != $this->event_end_time ){
1020
+ $replace = date($time_format, $this->start). get_option('dbem_times_seperator') . date($time_format, $this->end);
1021
+ }else{
1022
+ $replace = date($time_format, $this->start);
1023
+ }
1024
+ }else{
1025
+ $replace = get_option('dbem_event_all_day_message');
1026
+ }
1027
+ break;
1028
+ case '#_EVENTDATES':
1029
+ //get format of time to show
1030
+ $date_format = ( get_option('dbem_date_format') ) ? get_option('dbem_date_format'):get_option('date_format');
1031
+ if( $this->event_start_date != $this->event_end_date){
1032
+ $replace = date($date_format, $this->start). get_option('dbem_dates_seperator') . date($date_format, $this->end);
1033
+ }else{
1034
+ $replace = date($date_format, $this->start);
1035
+ }
1036
+ break;
1037
  //Links
1038
  case '#_EVENTPAGEURL': //Depreciated
1039
  case '#_LINKEDNAME': //Depreciated
1040
  case '#_EVENTURL': //Just the URL
1041
  case '#_EVENTLINK': //HTML Link
1042
+ if( EM_MS_GLOBAL ){
1043
+ if( get_site_option('dbem_ms_global_events_links') && !empty($this->blog_id) && is_main_site() && $this->blog_id != get_current_blog_id() ){
1044
+ //linking directly to the blog
1045
+ $event_link = get_blog_permalink( $this->blog_id, $this->post_id);
1046
+ }elseif( !empty($this->blog_id) && is_main_site() && $this->blog_id != get_current_blog_id() ){
1047
+ if( get_option('dbem_events_page') ){
1048
+ $event_link = trailingslashit(get_permalink(get_option('dbem_events_page')).get_site_option('dbem_ms_events_slug',EM_EVENT_SLUG).'/'.$this->event_slug.'-'.$this->event_id);
1049
+ }else{
1050
+ $event_link = trailingslashit(home_url()).EM_POST_TYPE_EVENT_SLUG.'/'.get_site_option('dbem_ms_events_slug',EM_EVENT_SLUG).'/'.$this->event_slug.'-'.$this->event_id;
1051
+ }
1052
+ }
1053
+ }
1054
+ if( empty($event_link) ){
1055
+ $event_link = get_post_permalink($this->post_id);
1056
+ }
1057
  if($result == '#_LINKEDNAME' || $result == '#_EVENTLINK'){
1058
+ $replace = '<a href="'.$event_link.'" title="'.esc_attr($this->event_name).'">'.esc_attr($this->event_name).'</a>';
1059
  }else{
1060
  $replace = $event_link;
1061
  }
1062
  break;
1063
+ case '#_EDITEVENTURL':
1064
  case '#_EDITEVENTLINK':
1065
+ if( $this->can_manage('edit_events','edit_others_events') ){
1066
+ if( is_multisite() && get_site_option('dbem_ms_global_events') && get_site_option('dbem_ms_global_events_links') && !empty($this->blog_id) && is_main_site() && $this->blog_id != get_current_blog_id() ){
1067
+ $replace = get_site_url($this->blog_id, "/wp-admin/post.php?post={$this->post_id}&action=edit");
1068
+ }else{
1069
+ $replace = esc_url(admin_url()."post.php?post={$this->post_id}&action=edit");
1070
+ }
1071
+ if( $result == '#_EDITEVENTLINK'){
1072
+ $replace = '<a href="'.$replace.'">'.esc_html(__('Edit', 'dbem').' '.__('Event', 'dbem')).'</a>';
1073
+ }
1074
  }
1075
  break;
1076
  //Bookings
1077
+ case '#_ADDBOOKINGFORM': //Depreciated
1078
+ case '#_REMOVEBOOKINGFORM': //Depreciated
1079
  case '#_BOOKINGFORM':
1080
+ if( get_option('dbem_rsvp_enabled')){
1081
+ ob_start();
1082
+ $template = em_locate_template('placeholders/bookingform.php', true, array('EM_Event'=>$this));
1083
+ if( !defined('EM_BOOKING_JS_LOADED') ){
1084
+ //this kicks off the Javascript required by booking forms. This is fired once for all booking forms on a page load and appears at the bottom of the page
1085
+ //your theme must call the wp_footer() function for this to work (as required by many other plugins too)
1086
+ function em_booking_js_footer(){
1087
+ ?>
1088
+ <script type="text/javascript">
1089
+ jQuery(document).ready( function($){
1090
+ <?php
1091
+ //we call the segmented JS files and include them here
1092
+ include(WP_PLUGIN_DIR.'/events-manager/includes/js/bookingsform.js');
1093
+ do_action('em_gateway_js');
1094
+ ?>
1095
+ });
1096
+ </script>
1097
+ <?php
1098
+ }
1099
+ add_action('wp_footer','em_booking_js_footer');
1100
+ define('EM_BOOKING_JS_LOADED',true);
1101
  }
1102
+ $replace = ob_get_clean();
1103
+ }
1104
+ break;
1105
+ case '#_BOOKINGBUTTON':
1106
+ if( get_option('dbem_rsvp_enabled')){
1107
+ ob_start();
1108
+ $template = em_locate_template('placeholders/bookingbutton.php', true, array('EM_Event'=>$this));
1109
+ $replace = ob_get_clean();
1110
  }
1111
  break;
1112
  case '#_AVAILABLESEATS': //Depreciated
1113
  case '#_AVAILABLESPACES':
1114
+ if ($this->event_rsvp && get_option('dbem_rsvp_enabled')) {
1115
+ $replace = $this->get_bookings()->get_available_spaces();
1116
  } else {
1117
  $replace = "0";
1118
  }
1119
  break;
1120
  case '#_BOOKEDSEATS': //Depreciated
1121
  case '#_BOOKEDSPACES':
1122
+ if ($this->event_rsvp && get_option('dbem_rsvp_enabled')) {
1123
+ $replace = $this->get_bookings()->get_booked_spaces();
1124
+ } else {
1125
+ $replace = "0";
1126
+ }
1127
+ break;
1128
+ case '#_PENDINGSPACES':
1129
+ if ($this->event_rsvp && get_option('dbem_rsvp_enabled')) {
1130
+ $replace = $this->get_bookings()->get_pending_spaces();
1131
  } else {
1132
  $replace = "0";
1133
  }
1134
  break;
1135
  case '#_SEATS': //Depreciated
1136
  case '#_SPACES':
1137
+ $replace = $this->get_spaces();
1138
+ break;
1139
+ case '#_BOOKINGSURL':
1140
+ case '#_BOOKINGSLINK':
1141
+ if( $this->can_manage('manage_bookings','manage_others_bookings') ){
1142
+ $bookings_link = esc_url(EM_ADMIN_URL ."&amp;page=events-manager-bookings&amp;event_id=".$this->id);
1143
+ if($result == '#_BOOKINGSLINK'){
1144
+ $replace = '<a href="'.$bookings_link.'" title="'.esc_attr($bookings_link).'">'.esc_html($this->event_name).'</a>';
1145
+ }else{
1146
+ $replace = $bookings_link;
1147
+ }
1148
+ }
1149
  break;
1150
  //Contact Person
1151
  case '#_CONTACTNAME':
1152
  case '#_CONTACTPERSON': //Depreciated (your call, I think name is better)
1153
+ $replace = $this->get_contact()->display_name;
1154
  break;
1155
  case '#_CONTACTUSERNAME':
1156
+ $replace = $this->get_contact()->user_login;
1157
  break;
1158
  case '#_CONTACTEMAIL':
1159
  case '#_CONTACTMAIL': //Depreciated
1160
+ $replace = $this->get_contact()->user_email;
1161
  break;
1162
  case '#_CONTACTID':
1163
+ $replace = $this->get_contact()->ID;
1164
  break;
1165
  case '#_CONTACTPHONE':
1166
+ $replace = ( $this->get_contact()->phone != '') ? $this->get_contact()->phone : __('N/A', 'dbem');
1167
  break;
1168
  case '#_CONTACTAVATAR':
1169
+ $replace = get_avatar( $this->get_contact()->ID, $size = '50' );
1170
+ break;
1171
+ case '#_CONTACTPROFILELINK':
1172
+ case '#_CONTACTPROFILEURL':
1173
+ if( function_exists('bp_core_get_user_domain') ){
1174
+ $replace = bp_core_get_user_domain($this->get_contact()->ID);
1175
+ if( $result == '#_CONTACTPROFILELINK' ){
1176
+ $replace = '<a href="'.esc_url($replace).'">'.__('Profile', 'dbem').'</a>';
1177
+ }
1178
+ }
1179
  break;
1180
  case '#_CONTACTPROFILELINK':
1181
  case '#_CONTACTPROFILEURL':
1182
  if( function_exists('bp_core_get_user_domain') ){
1183
+ $replace = bp_core_get_user_domain($this->get_contact()->ID);
1184
  if( $result == '#_CONTACTPROFILELINK' ){
1185
+ $replace = '<a href="'.esc_url($replace).'">'.__('Profile', 'dbem').'</a>';
1186
  }
1187
  }
1188
  break;
1189
+ case '#_ATTENDEES':
1190
+ ob_start();
1191
+ $template = em_locate_template('placeholders/attendees.php', true, array('EM_Event'=>$this));
1192
+ $replace = ob_get_clean();
1193
+ break;
1194
+ case '#_CATEGORIES':
1195
+ case '#_EVENTCATEGORIES':
1196
+ ob_start();
1197
+ $template = em_locate_template('placeholders/categories.php', true, array('EM_Event'=>$this));
1198
+ $replace = ob_get_clean();
1199
+ break;
1200
+ case '#_EVENTTAGS':
1201
+ ob_start();
1202
+ $template = em_locate_template('placeholders/eventtags.php', true, array('EM_Event'=>$this));
1203
+ $replace = ob_get_clean();
1204
+ break;
1205
  default:
1206
+ $replace = $full_result;
1207
  break;
1208
  }
1209
+ $replace = apply_filters('em_event_output_placeholder', $replace, $this, $full_result, $target );
1210
+ $event_string = str_replace($full_result, $replace , $event_string );
1211
  }
1212
  //Time placeholders
1213
+ foreach($placeholders[1] as $result) {
1214
  // matches all PHP START date and time placeholders
1215
  if (preg_match('/^#[dDjlNSwzWFmMntLoYyaABgGhHisueIOPTZcrU]$/', $result)) {
1216
  $replace = date_i18n(ltrim($result, "#"), $this->start);
1224
  $event_string = str_replace($result, $replace, $event_string );
1225
  }
1226
  }
1227
+ //Now do dependent objects
1228
+ if( !empty($this->location_id) && $this->get_location()->location_status ){
1229
+ $event_string = $this->get_location()->output($event_string, $target);
1230
+ }else{
1231
+ $EM_Location = new EM_Location();
1232
+ $event_string = $EM_Location->output($event_string, $target);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1233
  }
1234
 
1235
+ //for backwards compat and easy use, take over the individual category placeholders with the frirst cat in th elist.
1236
+ $EM_Categories = $this->get_categories();
1237
+ if( count($EM_Categories->categories) > 0 ){
1238
+ $EM_Category = $EM_Categories->categories[0];
1239
+ }
1240
+ if( empty($EM_Category) ) $EM_Category = new EM_Category();
1241
+ $event_string = $EM_Category->output($event_string, $target);
1242
+
1243
+ return apply_filters('em_event_output', $event_string, $this, $format, $target);
1244
+ }
1245
 
1246
  /**********************************************************
1247
  * RECURRENCE METHODS
1248
  ***********************************************************/
1249
 
1250
  /**
1251
+ * Depreciated, returns false as EM_Event is now only a single event. Use EM_Event_Recurrence
1252
  * @return boolean
1253
  */
1254
+ function is_recurring(){
1255
+ return $this->post_type == 'event-recurring' && get_option('dbem_recurrence_enabled');
1256
+ }
1257
+ /**
1258
+ * Will return true if this individual event is part of a set of events that recur
1259
+ * @return boolean
1260
+ */
1261
+ function is_recurrence(){
1262
+ return ( $this->id > 0 && $this->recurrence_id > 0 && get_option('dbem_recurrence_enabled') );
1263
+ }
1264
+ /**
1265
+ * Returns if this is an individual event and is not a recurrence
1266
+ * @return boolean
1267
+ */
1268
+ function is_individual(){
1269
+ return ( !$this->is_recurring() && !$this->is_recurrence() );
 
 
 
 
 
 
 
 
 
 
 
 
1270
  }
1271
 
1272
  /**
1273
+ * Gets the event recurrence template, which is an EM_Event_Recurrence object (based off an event-recurring post)
1274
+ * @return EM_Event_Recurrence
 
1275
  */
1276
+ function get_event_recurrence(){
1277
+ if(!$this->is_recurring()){
1278
+ return new EM_Event($this->recurrence_id); //remember, recurrence_id is a post!
1279
+ }else{
1280
+ return $this;
 
 
 
 
 
 
 
 
 
1281
  }
1282
+ }
1283
+
1284
+ function get_detach_url(){
1285
+ return admin_url().'admin.php?event_id='.$this->event_id.'&amp;action=event_detach&amp;_wpnonce='.wp_create_nonce('event_detach_'.get_current_user_id().'_'.$this->event_id);
1286
+ }
1287
+
1288
+ function get_attach_url($recurrence_id){
1289
+ return admin_url().'admin.php?undo_id='.$recurrence_id.'&amp;event_id='.$this->event_id.'&amp;action=event_attach&amp;_wpnonce='.wp_create_nonce('event_attach_'.get_current_user_id().'_'.$this->event_id);
1290
  }
1291
 
1292
  /**
1293
+ * Returns if this is an individual event and is not recurring or a recurrence
 
 
1294
  * @return boolean
1295
  */
1296
+ function detach(){
1297
+ global $wpdb;
1298
+ if( $this->is_recurrence() && !$this->is_recurring() && $this->can_manage('edit_recurring_events','edit_others_recurring_events') ){
1299
+ //remove recurrence id from post meta and index table
1300
+ $url = $this->get_attach_url($this->recurrence_id);
1301
+ $wpdb->update(EM_EVENTS_TABLE, array('recurrence_id'=>0), array('event_id' => $this->event_id));
1302
+ update_post_meta($this->post_id, '_recurrence_id', 0);
1303
+ $this->feedback_message = __('Event detached.','dbem') . ' <a href="'.$url.'">'.__('Undo','dbem').'</a>';
1304
+ $this->recurrence_id = 0;
1305
+ return true;
1306
+ }
1307
+ $this->add_error(__('Event could not be detached.','dbem'));
1308
+ return false;
1309
+ }
1310
+
1311
  /**
1312
+ * Returns if this is an individual event and is not recurring or a recurrence
 
1313
  * @return boolean
1314
  */
1315
+ function attach($recurrence_id){
1316
+ global $wpdb;
1317
+ if( !$this->is_recurrence() && !$this->is_recurring() && is_numeric($recurrence_id) && $this->can_manage('edit_recurring_events','edit_others_recurring_events') ){
1318
+ //add recurrence id to post meta and index table
1319
+ $wpdb->update(EM_EVENTS_TABLE, array('recurrence_id'=>$recurrence_id), array('event_id' => $this->event_id));
1320
+ update_post_meta($this->post_id, '_recurrence_id', $recurrence_id);
1321
+ $this->feedback_message = __('Event re-attached to recurrence.','dbem');
1322
+ return true;
1323
+ }
1324
+ $this->add_error(__('Event could not be attached.','dbem'));
1325
+ return false;
1326
  }
1327
+
1328
  /**
1329
+ * Saves events and replaces old ones. Returns true if sucecssful or false if not.
1330
  * @return boolean
1331
  */
1332
+ function save_events() {
1333
+ global $wpdb;
1334
+ if( $this->can_manage('edit_events','edit_others_events') && $this->is_published() ){
1335
+ do_action('em_event_save_events_pre', $this); //actions/filters only run if event is recurring
1336
+ //Make template event index, post, and meta (and we just change event dates)
1337
+ $event = $this->to_array(true); //event template - for index
1338
+ $event['event_attributes'] = serialize($event['event_attributes']);
1339
+ $post_fields = $wpdb->get_row('SELECT * FROM '.$wpdb->posts.' WHERE ID='.$this->post_id, ARRAY_A); //post to copy
1340
+ $post_name = $post_fields['post_name']; //save post slug since we'll be using this
1341
+ $post_fields['post_type'] = 'event'; //make sure we'll save events, not recurrence templates
1342
+ $meta_fields_map = $wpdb->get_results('SELECT meta_key,meta_value FROM '.$wpdb->postmeta.' WHERE post_id='.$this->post_id, ARRAY_A);
1343
+ $meta_fields = array();
1344
+ //convert meta_fields into a cleaner array
1345
+ foreach($meta_fields_map as $meta_data){
1346
+ $meta_fields[$meta_data['meta_key']] = $meta_data['meta_value'];
1347
+ }
1348
+ //remove id and we have a event template to feed to wpdb insert
1349
+ unset($event['event_id']);
1350
+ unset($post_fields['ID']);
1351
+ //remove recurrence meta info we won't need in events
1352
+ foreach( array_keys($this->recurrence_fields) as $recurrence_field){
1353
+ unset($event[$recurrence_field]);
1354
+ unset($meta_fields['_'.$recurrence_field]);
1355
+ }
1356
+ $event['event_date_created'] = current_time('mysql'); //since the recurrences are recreated
1357
+ unset($event['event_date_modified']);
1358
+ //Set the recurrence ID
1359
+ $event['recurrence_id'] = $meta_fields['_recurrence_id'] = $this->event_id;
1360
+ $event['recurrence'] = $meta_fields['_recurrence'] = 0;
1361
+ //Let's start saving!
1362
+ $this->delete_events(); //Delete old events beforehand, this will change soon
1363
+ $event_saves = array();
1364
+ $event_ids = array();
1365
+ $post_ids = array();
1366
+ $matching_days = $this->get_recurrence_days(); //Get days where events recur
1367
+ /*
1368
+ echo 'tickets';
1369
+ echo "<pre>"; print_r($this->recurrence_tickets); echo "</pre>";
1370
+ echo '$meta_fields';
1371
+ echo "<pre>"; print_r($meta_fields); echo "</pre>";
1372
+ echo '$post_fields';
1373
+ echo "<pre>"; print_r($post_fields); echo "</pre>";
1374
+ echo '$event';
1375
+ echo "<pre>"; print_r($event); echo "</pre>";
1376
+ echo '$matching_days';
1377
+ echo "<pre>"; print_r($matching_days); echo "</pre>";
1378
+ die('i got here and we have '.count($this->errors).' errors');
1379
+ */
1380
+ if( count($matching_days) > 0 ){
1381
+ //first save event post data
1382
+ foreach( $matching_days as $day ) {
1383
+ //rewrite post fields if needed
1384
+ $post_fields['post_name'] = $event['event_slug'] = $meta_fields['_event_slug'] = $post_name.'-'.date("Y-m-d", $day);
1385
+ //adjust certain meta information
1386
+ $event['event_start_date'] = $meta_fields['_event_start_date'] = date("Y-m-d", $day);
1387
+ $meta_fields['_start_ts'] = $day;
1388
+ if($this->recurrence_days > 1){
1389
+ $meta_fields['_end_ts'] = $day + ($this->recurrence_days * 60*60*24);
1390
+ $event['event_end_date'] = $meta_fields['_event_end_date'] = date("Y-m-d", $meta_fields['_end_ts']);
1391
+ }else{
1392
+ $meta_fields['_end_ts'] = $day;
1393
+ $event['event_end_date'] = $meta_fields['_event_end_date'] = $event['event_start_date'];
1394
+ }
1395
+ //create the event
1396
+ if( $wpdb->insert($wpdb->posts, $post_fields ) ){
1397
+ $event['post_id'] = $meta_fields['_post_id'] = $post_id = $post_ids[] = $wpdb->insert_id; //post id saved into event and also as a var for later user
1398
+ // Set GUID and event slug as per wp_insert_post
1399
+ $wpdb->update( $wpdb->posts, array( 'guid' => get_permalink( $post_id ) ), array('ID'=>$post_id) );
1400
+ //insert into events index table
1401
+ $event_saves[] = $wpdb->insert(EM_EVENTS_TABLE, $event);
1402
+ $event_ids[] = $event_id = $wpdb->insert_id;
1403
+ //create the meta inserts for each event
1404
+ $meta_fields['_event_id'] = $event_id;
1405
+ foreach($meta_fields as $meta_key => $meta_val){
1406
+ $meta_inserts[] = $wpdb->prepare("(%d, '%s', '%s')", array($post_id, $meta_key, $meta_val));
1407
+ }
1408
+ }else{
1409
+ $event_saves[] = false;
1410
+ }
1411
+ //if( EM_DEBUG ){ echo "Entering recurrence " . date("D d M Y", $day)."<br/>"; }
1412
+ }
1413
+ //insert the metas in one go, faster than one by one
1414
+ if( count($meta_inserts) > 0 ){
1415
+ $result = $wpdb->query("INSERT INTO ".$wpdb->postmeta." (post_id,meta_key,meta_value) VALUES ".implode(',',$meta_inserts));
1416
+ if($result === false){
1417
+ $this->add_error('There was a problem adding custom fields to your recurring events.','dbem');
1418
+ }
1419
+ }
1420
+ //copy the event tags and categories
1421
+ $categories = get_the_terms( $this->post_id, EM_TAXONOMY_CATEGORY );
1422
+ $cat_slugs = array();
1423
+ if( is_array($categories) ){
1424
+ foreach($categories as $category){
1425
+ if( !empty($category->slug) ) $cat_slugs[] = $category->slug; //save of category will soft-fail if slug is empty
1426
+ }
1427
+ }
1428
+ $cat_slugs_count = count($cat_slugs);
1429
+ $tags = get_the_terms( $this->post_id, EM_TAXONOMY_TAG);
1430
+ $tax_slugs = array();
1431
+ if( is_array($tags) ){
1432
+ foreach($tags as $tag){
1433
+ if( !empty($tag->slug) ) $tax_slugs[] = $tag->slug; //save of category will soft-fail if slug is empty
1434
+ }
1435
+ }
1436
+ $tax_slugs_count = count($tax_slugs);
1437
+ foreach($post_ids as $post_id){
1438
+ if( $cat_slugs_count > 0 ){
1439
+ wp_set_object_terms($post_id, $cat_slugs, EM_TAXONOMY_CATEGORY);
1440
+ }
1441
+ if( $tax_slugs_count > 0 ){
1442
+ wp_set_object_terms($post_id, $tax_slugs, EM_TAXONOMY_TAG);
1443
+ }
1444
+ }
1445
+ //now, save booking info for each event
1446
+ if( $this->event_rsvp ){
1447
+ $meta_inserts = array();
1448
+ foreach($this->get_tickets() as $EM_Ticket){
1449
+ /* @var $EM_Ticket EM_Ticket */
1450
+ //get array, modify event id and insert
1451
+ $ticket = $EM_Ticket->to_array();
1452
+ unset($ticket['ticket_id']);
1453
+ //clean up ticket values
1454
+ foreach($ticket as $k => $v){
1455
+ if( empty($v) && $k != 'ticket_name' ){
1456
+ $ticket[$k] = 'NULL';
1457
+ }else{
1458
+ $ticket[$k] = "'$v'";
1459
+ }
1460
+ }
1461
+ foreach($event_ids as $event_id){
1462
+ $ticket['event_id'] = $event_id;
1463
+ $meta_inserts[] = "(".implode(",",$ticket).")";
1464
+ }
1465
+ }
1466
+ $keys = "(".implode(",",array_keys($ticket)).")";
1467
+ $values = implode(',',$meta_inserts);
1468
+ $sql = "INSERT INTO ".EM_TICKETS_TABLE." $keys VALUES $values";
1469
+ $result = $wpdb->query($sql);
1470
+ }
1471
+ }else{
1472
+ $this->add_error('You have not defined a date range long enough to create a recurrence.','dbem');
1473
+ $result = false;
1474
+ }
1475
+ return apply_filters('em_event_save_events', !in_array(false, $event_saves) && $result !== false, $this, $event_ids);
1476
+ }
1477
+ return apply_filters('em_event_save_events', false, $this, $event_ids);
1478
  }
1479
 
1480
  /**
1481
+ * Removes all reoccurring events.
1482
+ * @param $recurrence_id
1483
+ * @return null
1484
  */
1485
+ function delete_events(){
1486
+ global $wpdb;
1487
+ do_action('em_event_delete_events_pre', $this);
1488
+ //So we don't do something we'll regret later, we could just supply the get directly into the delete, but this is safer
1489
+ $result = false;
1490
+ if( $this->can_manage('delete_events', 'delete_others_events') ){
1491
+ //delete events from em_events table
1492
+ $events_array = EM_Events::get( array('recurrence_id'=>$this->event_id, 'scope'=>'all', 'status'=>false ) );
1493
+ foreach($events_array as $EM_Event){
1494
+ /* @var $EM_Event EM_Event */
1495
+ if($EM_Event->recurrence_id == $this->event_id){
1496
+ $EM_Event->delete(true);
1497
+ }
1498
+ }
1499
  }
1500
+ return apply_filters('delete_events', $result, $this, $events_array);
1501
  }
1502
 
1503
  /**
1505
  * @param array $recurrence
1506
  * @return array
1507
  */
1508
+ function get_recurrence_days(){
1509
+ $start_date = strtotime($this->event_start_date);
1510
+ $end_date = strtotime($this->event_end_date);
 
 
 
 
 
 
 
 
1511
 
1512
+ $weekdays = explode(",", $this->recurrence_byday); //what days of the week (or if monthly, one value at index 0)
1513
+
1514
+ $matching_days = array();
1515
+ $aDay = 86400; // a day in seconds
1516
+ $aWeek = $aDay * 7;
1517
+
1518
+ //TODO can this be optimized?
1519
+ switch ( $this->recurrence_freq ){
1520
+ case 'daily':
1521
+ //If daily, it's simple. Get start date, add interval timestamps to that and create matching day for each interval until end date.
1522
+ $current_date = $start_date;
1523
+ while( $current_date <= $end_date ){
1524
+ $matching_days[] = $current_date;
1525
+ $current_date = $current_date + ($aDay * $this->recurrence_interval);
1526
+ }
1527
+ break;
1528
+ case 'weekly':
1529
+ //sort out week one, get starting days and then days that match time span of event (i.e. remove past events in week 1)
1530
+ $start_of_week = get_option('start_of_week'); //Start of week depends on WordPress
1531
+ //first, get the start of this week as timestamp
1532
+ $event_start_day = date('w', $start_date);
1533
+ $offset = 0;
1534
+ if( $event_start_day > $start_of_week ){
1535
+ $offset = $event_start_day - $start_of_week; //x days backwards
1536
+ }elseif( $event_start_day < $start_of_week ){
1537
+ $offset = $start_of_week;
1538
+ }
1539
+ $start_week_date = $start_date - ( ($event_start_day - $start_of_week) * $aDay );
1540
+ //then get the timestamps of weekdays during this first week, regardless if within event range
1541
+ $start_weekday_dates = array(); //Days in week 1 where there would events, regardless of event date range
1542
+ for($i = 0; $i < 7; $i++){
1543
+ $weekday_date = $start_week_date+($aDay*$i); //the date of the weekday we're currently checking
1544
+ $weekday_day = date('w',$weekday_date); //the day of the week we're checking, taking into account wp start of week setting
1545
+ if( in_array( $weekday_day, $weekdays) ){
1546
+ $start_weekday_dates[] = $weekday_date; //it's in our starting week day, so add it
1547
  }
1548
+ }
1549
+ //for each day of eventful days in week 1, add 7 days * weekly intervals
1550
+ foreach ($start_weekday_dates as $weekday_date){
1551
+ //Loop weeks by interval until we reach or surpass end date
1552
+ while($weekday_date <= $end_date){
1553
+ if( $weekday_date >= $start_date && $weekday_date <= $end_date ){
1554
+ $matching_days[] = $weekday_date;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1555
  }
1556
+ $weekday_date = $weekday_date + ($aWeek * $this->recurrence_interval);
1557
+ }
1558
+ }//done!
1559
+ break;
1560
+ case 'monthly':
1561
+ //loop months starting this month by intervals
1562
+ $current_arr = getdate($start_date);
1563
+ $end_arr = getdate($end_date);
1564
+ $end_month_date = strtotime( date('Y-m-t', $end_date) ); //End date on last day of month
1565
+ $current_date = strtotime( date('Y-m-1', $start_date) ); //Start date on first day of month
1566
+ while( $current_date <= $end_month_date ){
1567
+ $last_day_of_month = date('t', $current_date);
1568
+ //Now find which day we're talking about
1569
+ $current_week_day = date('w',$current_date);
1570
+ $matching_month_days = array();
1571
+ //Loop through days of this years month and save matching days to temp array
1572
+ for($day = 1; $day <= $last_day_of_month; $day++){
1573
+ if($current_week_day == $this->recurrence_byday){
1574
+ $matching_month_days[] = $day;
 
 
 
 
 
 
 
 
 
 
 
 
 
1575
  }
1576
+ $current_week_day = ($current_week_day < 6) ? $current_week_day+1 : 0;
1577
  }
1578
+ //Now grab from the array the x day of the month
1579
+ $matching_day = ($this->recurrence_byweekno > 0) ? $matching_month_days[$this->recurrence_byweekno-1] : array_pop($matching_month_days);
1580
+ $matching_date = strtotime(date('Y-m',$current_date).'-'.$matching_day);
1581
+ if($matching_date >= $start_date && $matching_date <= $end_date){
1582
+ $matching_days[] = $matching_date;
1583
+ }
1584
+ //add the number of days in this month to make start of next month
1585
+ $current_arr['mon'] += $this->recurrence_interval;
1586
+ if($current_arr['mon'] > 12){
1587
+ //FIXME this won't work if interval is more than 12
1588
+ $current_arr['mon'] = $current_arr['mon'] - 12;
1589
+ $current_arr['year']++;
1590
+ }
1591
+ $current_date = strtotime("{$current_arr['year']}-{$current_arr['mon']}-1");
1592
+ }
1593
+ break;
1594
+ }
1595
+ sort($matching_days);
1596
+ return apply_filters('em_events_get_recurrence_days', $matching_days, $this);
1597
+ }
1598
+
1599
+ /**
1600
+ * If event is recurring, set recurrences to same status as template
1601
+ * @param $status
1602
+ */
1603
+ function set_status_events($status){
1604
+ //give sub events same status
1605
+ $events_array = EM_Events::get( array('recurrence_id'=>$this->post_id, 'scope'=>'all', 'status'=>false ) );
1606
+ foreach($events_array as $EM_Event){
1607
+ /* @var $EM_Event EM_Event */
1608
+ if($EM_Event->recurrence_id == $this->event_id){
1609
+ $EM_Event->set_status($status);
1610
+ }
1611
  }
1612
  }
1613
 
1615
  * Returns a string representation of this recurrence. Will return false if not a recurrence
1616
  * @return string
1617
  */
1618
+ function get_recurrence_description() {
1619
+ $EM_Event_Recurring = $this->get_event_recurrence();
1620
+ $recurrence = $this->to_array();
1621
+ $weekdays_name = array(__('Sunday', 'dbem'),__('Monday', 'dbem'),__('Tuesday', 'dbem'),__('Wednesday', 'dbem'),__('Thursday', 'dbem'),__('Friday', 'dbem'),__('Saturday', 'dbem'));
 
 
1622
  $monthweek_name = array('1' => __('the first %s of the month', 'dbem'),'2' => __('the second %s of the month', 'dbem'), '3' => __('the third %s of the month', 'dbem'), '4' => __('the fourth %s of the month', 'dbem'), '-1' => __('the last %s of the month', 'dbem'));
1623
+ $output = sprintf (__('From %1$s to %2$s', 'dbem'), $EM_Event_Recurring->event_start_date, $EM_Event_Recurring->event_end_date).", ";
1624
+ if ($EM_Event_Recurring->recurrence_freq == 'daily') {
1625
  $freq_desc =__('everyday', 'dbem');
1626
+ if ($EM_Event_Recurring->recurrence_interval > 1 ) {
1627
+ $freq_desc = sprintf (__("every %s days", 'dbem'), $EM_Event_Recurring->recurrence_interval);
1628
  }
1629
+ }elseif ($EM_Event_Recurring->recurrence_freq == 'weekly') {
1630
+ $weekday_array = explode(",", $EM_Event_Recurring->recurrence_byday);
 
1631
  $natural_days = array();
1632
  foreach($weekday_array as $day){
1633
  array_push($natural_days, $weekdays_name[$day]);
1634
  }
1635
  $output .= implode(" and ", $natural_days);
1636
  $freq_desc = ", " . __("every week", 'dbem');
1637
+ if ($EM_Event_Recurring->recurrence_interval > 1 ) {
1638
+ $freq_desc = ", ".sprintf (__("every %s weeks", 'dbem'), $EM_Event_Recurring->recurrence_interval);
1639
  }
1640
 
1641
+ }elseif ($EM_Event_Recurring->recurrence_freq == 'monthly') {
1642
+ $weekday_array = explode(",", $EM_Event_Recurring->recurrence_byday);
 
1643
  $natural_days = array();
1644
  foreach($weekday_array as $day){
1645
  array_push($natural_days, $weekdays_name[$day]);
1646
  }
1647
+ $freq_desc = sprintf (($monthweek_name[$EM_Event_Recurring->recurrence_byweekno]), implode(" and ", $natural_days));
1648
+ if ($EM_Event_Recurring->recurrence_interval > 1 ) {
1649
+ $freq_desc .= ", ".sprintf (__("every %s months",'dbem'), $EM_Event_Recurring->recurrence_interval);
1650
  }
1651
+ }else{
1652
+ $freq_desc = "[ERROR: corrupted database record]";
1653
  }
1654
  $output .= $freq_desc;
1655
  return $output;
1656
+ }
1657
 
1658
  /**********************************************************
1659
  * UTILITIES
1660
  ***********************************************************/
1661
+
1662
  /**
1663
+ * Can the user manage this?
 
 
 
1664
  */
1665
+ function can_manage( $owner_capability = false, $admin_capability = false, $user_to_check = false ){
1666
+ if( $this->id == '' && !is_user_logged_in() && get_option('dbem_events_anonymous_submissions') ){
1667
+ $user_to_check = get_option('dbem_events_anonymous_user');
 
 
 
 
 
 
 
 
 
 
1668
  }
1669
+ return apply_filters('em_event_can_manage', parent::can_manage($owner_capability, $admin_capability, $user_to_check), $this, $owner_capability, $admin_capability, $user_to_check);
1670
  }
1671
  }
1672
 
1683
  if( ($placeholder == "#_EXCERPT" || $placeholder == "#_LOCATIONEXCERPT") && $target == 'html' ){
1684
  $result = apply_filters('dbem_notes_excerpt', $result);
1685
  }elseif( $placeholder == '#_CONTACTEMAIL' && $target == 'html' ){
1686
+ $result = em_ascii_encode($event->get_contact()->user_email);
1687
  }elseif( $placeholder == "#_NOTES" || $placeholder == "#_EXCERPT" || $placeholder == "#_LOCATIONEXCERPT" ){
1688
  if($target == 'html'){
1689
  $result = apply_filters('dbem_notes', $result);
1690
  }elseif($target == 'map'){
1691
  $result = apply_filters('dbem_notes_map', $result);
1692
+ }elseif($target == 'ical'){
1693
+ $result = apply_filters('dbem_notes_ical', $result);
1694
  }else{
1695
  $result = apply_filters('dbem_notes_rss', $result);
1696
  $result = apply_filters('the_content_rss', $result);
1698
  }elseif( in_array($placeholder, array("#_NAME",'#_ADDRESS','#_LOCATION','#_TOWN')) ){
1699
  if ($target == "html"){
1700
  $result = apply_filters('dbem_general', $result);
1701
+ }elseif ($target == "ical"){
1702
+ $result = apply_filters('dbem_general_ical', $result);
1703
  }else{
1704
  $result = apply_filters('dbem_general_rss', $result);
1705
  }
classes/em-events.php CHANGED
@@ -1,9 +1,28 @@
1
  <?php
 
2
  /**
3
  * Use this class to query and manipulate sets of events. If dealing with more than one event, you probably want to use this class in some way.
4
  *
5
  */
6
- class EM_Events extends EM_Object {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
 
8
  /**
9
  * Returns an array of EM_Events that match the given specs in the argument, or returns a list of future evetnts in future
@@ -13,11 +32,10 @@ class EM_Events extends EM_Object {
13
  * @param array $args
14
  * @return EM_Event array()
15
  */
16
- function get( $args = array() ) {
17
- global $wpdb;
18
- $events_table = $wpdb->prefix . EM_EVENTS_TABLE;
19
- $locations_table = $wpdb->prefix . EM_LOCATIONS_TABLE;
20
- $categories_table = $wpdb->prefix . EM_CATEGORIES_TABLE;
21
 
22
  //Quick version, we can accept an array of IDs, which is easy to retrieve
23
  if( self::array_is_numeric($args) ){ //Array of numbers, assume they are event IDs to retreive
@@ -25,7 +43,6 @@ class EM_Events extends EM_Object {
25
  $sql = "
26
  SELECT * FROM $events_table
27
  LEFT JOIN $locations_table ON {$locations_table}.location_id={$events_table}.location_id
28
- LEFT JOIN $categories_table ON {$categories_table}.category_id={$events_table}.event_category_id
29
  WHERE event_id=".implode(" OR event_id=", $args)."
30
  ";
31
  $results = $wpdb->get_results(apply_filters('em_events_get_sql',$sql),ARRAY_A);
@@ -54,30 +71,47 @@ class EM_Events extends EM_Object {
54
  $orderby_sql = ( count($orderby) > 0 ) ? 'ORDER BY '. implode(', ', $orderby) : '';
55
 
56
  //Create the SQL statement and execute
 
 
 
 
 
 
 
57
  $sql = "
58
- SELECT * FROM $events_table
59
  LEFT JOIN $locations_table ON {$locations_table}.location_id={$events_table}.location_id
60
- LEFT JOIN $categories_table ON {$categories_table}.category_id={$events_table}.event_category_id
61
  $where
62
  $orderby_sql
63
  $limit $offset
64
  ";
65
-
 
 
 
 
66
  $results = $wpdb->get_results( apply_filters('em_events_get_sql',$sql, $args), ARRAY_A);
67
 
68
  //If we want results directly in an array, why not have a shortcut here?
69
  if( $args['array'] == true ){
70
- return $results;
71
  }
72
 
73
  //Make returned results EM_Event objects
74
  $results = (is_array($results)) ? $results:array();
75
  $events = array();
76
- foreach ( $results as $event ){
77
- $events[] = new EM_Event($event);
 
 
 
 
 
 
 
78
  }
79
 
80
- return apply_filters('em_events_get', $events);
81
  }
82
 
83
  /**
@@ -87,11 +121,15 @@ class EM_Events extends EM_Object {
87
  */
88
  function count_date($date){
89
  global $wpdb;
90
- $table_name = $wpdb->prefix . EM_EVENTS_TABLE;
91
  $sql = "SELECT COUNT(*) FROM $table_name WHERE (event_start_date like '$date') OR (event_start_date <= '$date' AND event_end_date >= '$date');";
92
  return apply_filters('em_events_count_date', $wpdb->get_var($sql));
93
  }
94
 
 
 
 
 
95
  /**
96
  * Will delete given an array of event_ids or EM_Event objects
97
  * @param unknown_type $id_array
@@ -99,30 +137,17 @@ class EM_Events extends EM_Object {
99
  function delete( $array ){
100
  global $wpdb;
101
  //Detect array type and generate SQL for event IDs
102
- $event_ids = array();
103
- if( @get_class(current($array)) == 'EM_Event' ){
104
- foreach($array as $EM_Event){
105
- $event_ids[] = $EM_Event->id;
106
- }
107
  }else{
108
- $event_ids = $array;
109
- }
110
- if(self::array_is_numeric($event_ids)){
111
- //First we have to check that they're all deletable by this user.
112
- if ( self::can_manage($event_ids) ) {
113
- apply_filters('em_events_delete_pre', $event_ids);
114
- $condition = implode(" OR event_id=", $event_ids);
115
- //Delete all the bookings
116
- $result_bookings = $wpdb->query("DELETE FROM ". $wpdb->prefix . EM_BOOKINGS_TABLE ." WHERE event_id=$condition;");
117
- //Now delete the events
118
- $result = $wpdb->query ( "DELETE FROM ". $wpdb->prefix . EM_EVENTS_TABLE ." WHERE event_id=$condition;" );
119
- return apply_filters('em_events_delete', true, $event_ids);
120
- }else{
121
- return apply_filters('em_events_delete', true, $event_ids);
122
- }
123
  }
124
  //TODO add better error feedback on events delete fails
125
- return apply_filters('em_events_delete', true, $event_ids);
126
  }
127
 
128
 
@@ -137,59 +162,58 @@ class EM_Events extends EM_Object {
137
  global $EM_Event;
138
  $EM_Event_old = $EM_Event; //When looping, we can replace EM_Event global with the current event in the loop
139
  //Can be either an array for the get search or an array of EM_Event objects
 
140
  if( is_object(current($args)) && get_class((current($args))) == 'EM_Event' ){
141
  $func_args = func_get_args();
142
  $events = $func_args[0];
143
- $args = apply_filters('em_events_output_args', self::get_default_search($func_args[1]), $events);
 
144
  $limit = ( !empty($args['limit']) && is_numeric($args['limit']) ) ? $args['limit']:false;
145
  $offset = ( !empty($args['offset']) && is_numeric($args['offset']) ) ? $args['offset']:0;
146
  $page = ( !empty($args['page']) && is_numeric($args['page']) ) ? $args['page']:1;
 
147
  }else{
148
  //Firstly, let's check for a limit/offset here, because if there is we need to remove it and manually do this
149
  $args = apply_filters('em_events_output_args', self::get_default_search($args) );
150
  $limit = ( !empty($args['limit']) && is_numeric($args['limit']) ) ? $args['limit']:false;
151
  $offset = ( !empty($args['offset']) && is_numeric($args['offset']) ) ? $args['offset']:0;
152
  $page = ( !empty($args['page']) && is_numeric($args['page']) ) ? $args['page']:1;
153
- $args['limit'] = false;
154
- $args['offset'] = false;
155
- $args['page'] = false;
 
 
156
  $events = self::get( $args );
157
  }
158
  //What format shall we output this to, or use default
159
  $format = ( empty($args['format']) ) ? get_option( 'dbem_event_list_item_format' ) : $args['format'] ;
160
 
161
  $output = "";
162
- $events_count = count($events);
163
  $events = apply_filters('em_events_output_events', $events);
164
-
165
  if ( $events_count > 0 ) {
166
- $event_count = 0;
167
- $events_shown = 0;
168
  foreach ( $events as $EM_Event ) {
169
- if( ($events_shown < $limit || empty($limit)) && ($event_count >= $offset || $offset === 0) ){
170
- $output .= $EM_Event->output($format);
171
- $events_shown++;
172
- }
173
- $event_count++;
174
  }
175
  //Add headers and footers to output
176
  if( $format == get_option ( 'dbem_event_list_item_format' ) ){
177
- $single_event_format_header = get_option ( 'dbem_event_list_item_format_header' );
178
- $single_event_format_header = ( $single_event_format_header != '' ) ? $single_event_format_header : "<ul class='dbem_events_list'>";
179
- $single_event_format_footer = get_option ( 'dbem_event_list_item_format_footer' );
180
- $single_event_format_footer = ( $single_event_format_footer != '' ) ? $single_event_format_footer : "</ul>";
181
- $output = $single_event_format_header . $output . $single_event_format_footer;
182
  }
 
183
  //Pagination (if needed/requested)
184
  if( !empty($args['pagination']) && !empty($limit) && $events_count > $limit ){
185
  //Show the pagination links (unless there's less than $limit events)
186
  $page_link_template = preg_replace('/(&|\?)page=\d+/i','',$_SERVER['REQUEST_URI']);
187
- $page_link_template = em_add_get_params($page_link_template, array('page'=>'%PAGE%'));
188
  $output .= apply_filters('em_events_output_pagination', em_paginate( $page_link_template, $events_count, $limit, $page), $page_link_template, $events_count, $limit, $page);
189
  }
190
  } else {
191
  $output = get_option ( 'dbem_no_events_message' );
192
- }
 
193
  //TODO check if reference is ok when restoring object, due to changes in php5 v 4
194
  $EM_Event = $EM_Event_old;
195
  $output = apply_filters('em_events_output', $output, $events, $args);
@@ -198,23 +222,70 @@ class EM_Events extends EM_Object {
198
 
199
  function can_manage($event_ids){
200
  global $wpdb;
201
- if( em_verify_admin() ){
202
  return apply_filters('em_events_can_manage', true, $event_ids);
203
  }
204
  if( EM_Object::array_is_numeric($event_ids) ){
205
  $condition = implode(" OR event_id=", $event_ids);
206
- //Delete all the bookings
207
- $results = $wpdb->query("SELECT event_author FROM ". $wpdb->prefix . EM_BOOKINGS_TABLE ." WHERE author_id != '". get_current_user_id() ."' event_id=$condition;");
208
- return apply_filters('em_events_can_manage', (count($results) > 0), $event_ids);
209
  }
210
  return apply_filters('em_events_can_manage', false, $event_ids);
211
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
212
 
213
  /* Overrides EM_Object method to apply a filter to result
214
  * @see wp-content/plugins/events-manager/classes/EM_Object#build_sql_conditions()
215
  */
216
  function build_sql_conditions( $args = array() ){
217
- return apply_filters( 'em_events_build_sql_conditions', parent::build_sql_conditions($args), $args );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
218
  }
219
 
220
  /* Overrides EM_Object method to apply a filter to result
@@ -234,21 +305,60 @@ class EM_Events extends EM_Object {
234
  $defaults = array(
235
  'orderby' => get_option('dbem_events_default_orderby'),
236
  'order' => get_option('dbem_events_default_order'),
237
- 'rsvp' => false //if set to true, only events with bookings enabled are returned
 
 
 
 
 
 
 
 
 
 
238
  );
 
 
 
 
 
 
 
 
239
  if( is_admin() ){
240
  //figure out default owning permissions
241
- switch( get_option('dbem_permissions_events') ){
242
- case 0:
243
- $defaults['owner'] = get_current_user_id();
244
- break;
245
- case 1:
246
- $defaults['owner'] = false;
247
- break;
248
  }
249
- $defaults['owner'] = ( em_verify_admin() ) ? false:$defaults['owner'];
250
  }
251
  return apply_filters('em_events_get_default_search', parent::get_default_search($defaults,$array), $array, $defaults);
252
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
253
  }
254
  ?>
1
  <?php
2
+ //TODO EM_Events is currently static, better we make this non-static so we can loop sets of events, and standardize with other objects.
3
  /**
4
  * Use this class to query and manipulate sets of events. If dealing with more than one event, you probably want to use this class in some way.
5
  *
6
  */
7
+ class EM_Events extends EM_Object implements Iterator {
8
+ /**
9
+ * Array of EM_Event objects
10
+ * @var array EM_Event
11
+ */
12
+ var $events = array();
13
+
14
+ function EM_Events( $args = array() ){
15
+ if( is_array($args) ){
16
+ if( is_object(current($args)) && get_class(current($args)) == 'EM_Event' ){
17
+ $this->events = $args;
18
+ }else{
19
+ $this->events = EM_Events::get($args);
20
+ }
21
+ }else{
22
+ $this->events = EM_Events::get();
23
+ }
24
+ do_action('em_events',$this);
25
+ }
26
 
27
  /**
28
  * Returns an array of EM_Events that match the given specs in the argument, or returns a list of future evetnts in future
32
  * @param array $args
33
  * @return EM_Event array()
34
  */
35
+ function get( $args = array(), $count=false ) {
36
+ global $wpdb;
37
+ $events_table = EM_EVENTS_TABLE;
38
+ $locations_table = EM_LOCATIONS_TABLE;
 
39
 
40
  //Quick version, we can accept an array of IDs, which is easy to retrieve
41
  if( self::array_is_numeric($args) ){ //Array of numbers, assume they are event IDs to retreive
43
  $sql = "
44
  SELECT * FROM $events_table
45
  LEFT JOIN $locations_table ON {$locations_table}.location_id={$events_table}.location_id
 
46
  WHERE event_id=".implode(" OR event_id=", $args)."
47
  ";
48
  $results = $wpdb->get_results(apply_filters('em_events_get_sql',$sql),ARRAY_A);
71
  $orderby_sql = ( count($orderby) > 0 ) ? 'ORDER BY '. implode(', ', $orderby) : '';
72
 
73
  //Create the SQL statement and execute
74
+
75
+ if( EM_MS_GLOBAL ){
76
+ $selectors = ( $count ) ? 'COUNT(*)':$events_table.'.post_id, '.$events_table.'.blog_id';
77
+ }else{
78
+ $selectors = ( $count ) ? 'COUNT(*)':$events_table.'.post_id';
79
+ }
80
+
81
  $sql = "
82
+ SELECT $selectors FROM $events_table
83
  LEFT JOIN $locations_table ON {$locations_table}.location_id={$events_table}.location_id
 
84
  $where
85
  $orderby_sql
86
  $limit $offset
87
  ";
88
+
89
+ //If we're only counting results, return the number of results
90
+ if( $count ){
91
+ return apply_filters('em_events_get_count', $wpdb->get_var($sql), $args);
92
+ }
93
  $results = $wpdb->get_results( apply_filters('em_events_get_sql',$sql, $args), ARRAY_A);
94
 
95
  //If we want results directly in an array, why not have a shortcut here?
96
  if( $args['array'] == true ){
97
+ return apply_filters('em_events_get_array',$results, $args);
98
  }
99
 
100
  //Make returned results EM_Event objects
101
  $results = (is_array($results)) ? $results:array();
102
  $events = array();
103
+
104
+ if( EM_MS_GLOBAL ){
105
+ foreach ( $results as $event ){
106
+ $events[] = em_get_event($event['post_id'], $event['blog_id']);
107
+ }
108
+ }else{
109
+ foreach ( $results as $event ){
110
+ $events[] = em_get_event($event['post_id'], 'post_id');
111
+ }
112
  }
113
 
114
+ return apply_filters('em_events_get', $events, $args);
115
  }
116
 
117
  /**
121
  */
122
  function count_date($date){
123
  global $wpdb;
124
+ $table_name = EM_EVENTS_TABLE;
125
  $sql = "SELECT COUNT(*) FROM $table_name WHERE (event_start_date like '$date') OR (event_start_date <= '$date' AND event_end_date >= '$date');";
126
  return apply_filters('em_events_count_date', $wpdb->get_var($sql));
127
  }
128
 
129
+ function count( $args = array() ){
130
+ return apply_filters('em_events_count', self::get($args, true), $args);
131
+ }
132
+
133
  /**
134
  * Will delete given an array of event_ids or EM_Event objects
135
  * @param unknown_type $id_array
137
  function delete( $array ){
138
  global $wpdb;
139
  //Detect array type and generate SQL for event IDs
140
+ $results = array();
141
+ if( @get_class(current($array)) != 'EM_Event' ){
142
+ $events = self::get($array);
 
 
143
  }else{
144
+ $events = $array;
145
+ }
146
+ foreach ($events as $EM_Event){
147
+ $results[] = $EM_Event->delete();
 
 
 
 
 
 
 
 
 
 
 
148
  }
149
  //TODO add better error feedback on events delete fails
150
+ return apply_filters('em_events_delete', in_array(false, $results), $event_ids);
151
  }
152
 
153
 
162
  global $EM_Event;
163
  $EM_Event_old = $EM_Event; //When looping, we can replace EM_Event global with the current event in the loop
164
  //Can be either an array for the get search or an array of EM_Event objects
165
+ $func_args = func_get_args();
166
  if( is_object(current($args)) && get_class((current($args))) == 'EM_Event' ){
167
  $func_args = func_get_args();
168
  $events = $func_args[0];
169
+ $args = (!empty($func_args[1]) && is_array($func_args[1])) ? $func_args[1] : array();
170
+ $args = apply_filters('em_events_output_args', self::get_default_search($args), $events);
171
  $limit = ( !empty($args['limit']) && is_numeric($args['limit']) ) ? $args['limit']:false;
172
  $offset = ( !empty($args['offset']) && is_numeric($args['offset']) ) ? $args['offset']:0;
173
  $page = ( !empty($args['page']) && is_numeric($args['page']) ) ? $args['page']:1;
174
+ $events_count = count($events);
175
  }else{
176
  //Firstly, let's check for a limit/offset here, because if there is we need to remove it and manually do this
177
  $args = apply_filters('em_events_output_args', self::get_default_search($args) );
178
  $limit = ( !empty($args['limit']) && is_numeric($args['limit']) ) ? $args['limit']:false;
179
  $offset = ( !empty($args['offset']) && is_numeric($args['offset']) ) ? $args['offset']:0;
180
  $page = ( !empty($args['page']) && is_numeric($args['page']) ) ? $args['page']:1;
181
+ $args_count = $args;
182
+ $args_count['limit'] = false;
183
+ $args_count['offset'] = false;
184
+ $args_count['page'] = false;
185
+ $events_count = self::count($args_count);
186
  $events = self::get( $args );
187
  }
188
  //What format shall we output this to, or use default
189
  $format = ( empty($args['format']) ) ? get_option( 'dbem_event_list_item_format' ) : $args['format'] ;
190
 
191
  $output = "";
 
192
  $events = apply_filters('em_events_output_events', $events);
 
193
  if ( $events_count > 0 ) {
 
 
194
  foreach ( $events as $EM_Event ) {
195
+ $output .= $EM_Event->output($format);
 
 
 
 
196
  }
197
  //Add headers and footers to output
198
  if( $format == get_option ( 'dbem_event_list_item_format' ) ){
199
+ $format_header = ( get_option( 'dbem_event_list_item_format_header') == '' ) ? '':get_option ( 'dbem_event_list_item_format_header' );
200
+ $format_footer = ( get_option ( 'dbem_event_list_item_format_footer' ) == '' ) ? '':get_option ( 'dbem_event_list_item_format_footer' );
201
+ }else{
202
+ $format_header = ( !empty($args['format_header']) ) ? $args['format_header']:'';
203
+ $format_footer = ( !empty($args['format_footer']) ) ? $args['format_footer']:'';
204
  }
205
+ $output = $format_header . $output . $format_footer;
206
  //Pagination (if needed/requested)
207
  if( !empty($args['pagination']) && !empty($limit) && $events_count > $limit ){
208
  //Show the pagination links (unless there's less than $limit events)
209
  $page_link_template = preg_replace('/(&|\?)page=\d+/i','',$_SERVER['REQUEST_URI']);
210
+ $page_link_template = em_add_get_params($page_link_template, array('page'=>'%PAGE%'), false); //don't html encode, so em_paginate does its thing;
211
  $output .= apply_filters('em_events_output_pagination', em_paginate( $page_link_template, $events_count, $limit, $page), $page_link_template, $events_count, $limit, $page);
212
  }
213
  } else {
214
  $output = get_option ( 'dbem_no_events_message' );
215
+ }
216
+
217
  //TODO check if reference is ok when restoring object, due to changes in php5 v 4
218
  $EM_Event = $EM_Event_old;
219
  $output = apply_filters('em_events_output', $output, $events, $args);
222
 
223
  function can_manage($event_ids){
224
  global $wpdb;
225
+ if( current_user_can('edit_others_events') ){
226
  return apply_filters('em_events_can_manage', true, $event_ids);
227
  }
228
  if( EM_Object::array_is_numeric($event_ids) ){
229
  $condition = implode(" OR event_id=", $event_ids);
230
+ //we try to find any of these events that don't belong to this user
231
+ $results = $wpdb->get_var("SELECT COUNT(*) FROM ". EM_EVENTS_TABLE ." WHERE event_owner != '". get_current_user_id() ."' event_id=$condition;");
232
+ return apply_filters('em_events_can_manage', ($results == 0), $event_ids);
233
  }
234
  return apply_filters('em_events_can_manage', false, $event_ids);
235
  }
236
+
237
+ function get_post_search($args = array()){
238
+ $accepted_searches = apply_filters('em_accepted_searches', array('scope','search','category','country','state','region','town'), $args);
239
+ foreach($_REQUEST as $post_key => $post_value){
240
+ if( in_array($post_key, $accepted_searches) && !empty($post_value) ){
241
+ if(is_array($post_value)){
242
+ $post_value = implode(',',$post_value);
243
+ }
244
+ if($post_value != ',' ){
245
+ $args[$post_key] = $post_value;
246
+ }
247
+ }
248
+ }
249
+ return apply_filters('em_events_get_post_search', $args);
250
+ }
251
 
252
  /* Overrides EM_Object method to apply a filter to result
253
  * @see wp-content/plugins/events-manager/classes/EM_Object#build_sql_conditions()
254
  */
255
  function build_sql_conditions( $args = array() ){
256
+ $conditions = parent::build_sql_conditions($args);
257
+ if( !empty($args['search']) ){
258
+ $like_search = array('event_name',EM_EVENTS_TABLE.'.post_content','location_name','location_address','location_town','location_postcode','location_state','location_country');
259
+ $conditions['search'] = "(".implode(" LIKE '%{$args['search']}%' OR ", $like_search). " LIKE '%{$args['search']}%')";
260
+ }
261
+ if( array_key_exists('status',$args) && is_numeric($args['status']) ){
262
+ $null = ($args['status'] == 0) ? ' OR `event_status` = 0':'';
263
+ $conditions['status'] = "(`event_status`={$args['status']}{$null} )";
264
+ }
265
+ //private events
266
+ if( !empty($args['private']) ){
267
+ $conditions['private'] = "(`event_private`=0)";
268
+ }elseif( !empty($args['private_only']) ){
269
+ $conditions['private_only'] = "(`event_private`=1)";
270
+ }
271
+ if( is_multisite() && array_key_exists('blog',$args) && is_numeric($args['blog']) ){
272
+ if( is_main_site($args['blog']) ){
273
+ $conditions['blog'] = "(".EM_EVENTS_TABLE.".blog_id={$args['blog']} OR ".EM_EVENTS_TABLE.".blog_id IS NULL)";
274
+ }else{
275
+ $conditions['blog'] = "(".EM_EVENTS_TABLE.".blog_id={$args['blog']})";
276
+ }
277
+ }
278
+ if( $args['bookings'] === 'user' && is_user_logged_in()){
279
+ //get bookings of user
280
+ $EM_Person = new EM_Person(get_current_user_id());
281
+ $booking_ids = $EM_Person->get_bookings(true);
282
+ if( count($booking_ids) > 0 ){
283
+ $conditions['bookings'] = "(event_id IN (SELECT event_id FROM ".EM_BOOKINGS_TABLE." WHERE booking_id IN (".implode(',',$booking_ids).")))";
284
+ }else{
285
+ $conditions['bookings'] = "(event_id = 0)";
286
+ }
287
+ }
288
+ return apply_filters( 'em_events_build_sql_conditions', $conditions, $args );
289
  }
290
 
291
  /* Overrides EM_Object method to apply a filter to result
305
  $defaults = array(
306
  'orderby' => get_option('dbem_events_default_orderby'),
307
  'order' => get_option('dbem_events_default_order'),
308
+ 'bookings' => false, //if set to true, only events with bookings enabled are returned
309
+ 'status' => 1, //approved events only
310
+ 'format_header' => '', //events can have custom html above the list
311
+ 'format_footer' => '', //events can have custom html below the list
312
+ 'town' => false,
313
+ 'state' => false,
314
+ 'country' => false,
315
+ 'region' => false,
316
+ 'blog' => get_current_blog_id(),
317
+ 'private' => !current_user_can('read_private_events'),
318
+ 'private_only' => false
319
  );
320
+ if(is_multisite()){
321
+ global $bp;
322
+ if( !is_main_site() && !array_key_exists('blog', $array) ){
323
+ $array['blog'] = get_current_blog_id();
324
+ }elseif( empty($array['blog']) && get_site_option('dbem_ms_global_events') ) {
325
+ $array['blog'] = false;
326
+ }
327
+ }
328
  if( is_admin() ){
329
  //figure out default owning permissions
330
+ $defaults['owner'] = !current_user_can('edit_others_events') ? get_current_user_id() : false;
331
+ if( !array_key_exists('status', $array) && current_user_can('edit_others_events') ){
332
+ $defaults['status'] = false; //by default, admins see pending and live events
 
 
 
 
333
  }
 
334
  }
335
  return apply_filters('em_events_get_default_search', parent::get_default_search($defaults,$array), $array, $defaults);
336
  }
337
+
338
+ //TODO Implement object and interators for handling groups of events.
339
+ public function rewind(){
340
+ reset($this->events);
341
+ }
342
+
343
+ public function current(){
344
+ $var = current($this->events);
345
+ return $var;
346
+ }
347
+
348
+ public function key(){
349
+ $var = key($this->events);
350
+ return $var;
351
+ }
352
+
353
+ public function next(){
354
+ $var = next($this->events);
355
+ return $var;
356
+ }
357
+
358
+ public function valid(){
359
+ $key = key($this->events);
360
+ $var = ($key !== NULL && $key !== FALSE);
361
+ return $var;
362
+ }
363
  }
364
  ?>
classes/em-location-post-admin.php ADDED
@@ -0,0 +1,123 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class EM_Location_Post_Admin{
3
+ function init(){
4
+ global $pagenow;
5
+ if($pagenow == 'post.php' || $pagenow == 'post-new.php' ){ //only needed if editing post
6
+ add_action('admin_head', array('EM_Location_Post_Admin','admin_head'));
7
+ }
8
+ //Meta Boxes
9
+ add_action('add_meta_boxes', array('EM_Location_Post_Admin','meta_boxes'));
10
+ //Save/Edit actions
11
+ add_action('save_post',array('EM_Location_Post_Admin','save_post'));
12
+ add_action('before_delete_post',array('EM_Location_Post_Admin','before_delete_post'),10,1);
13
+ add_action('trashed_post',array('EM_Location_Post_Admin','trashed_post'),10,1);
14
+ add_action('untrash_post',array('EM_Location_Post_Admin','untrash_post'),10,1);
15
+ add_action('untrashed_post',array('EM_Location_Post_Admin','untrashed_post'),10,1);
16
+ //Notices
17
+ add_action('admin_notices',array('EM_Location_Post_Admin','admin_notices'));
18
+ add_action('post_updated_messages',array('EM_Location_Post_Admin','admin_notices_filter'),1,1);
19
+ }
20
+
21
+ function admin_head(){
22
+ global $post, $EM_Location;
23
+ if( !empty($post) && $post->post_type == EM_POST_TYPE_LOCATION ){
24
+ $EM_Location = em_get_location($post);
25
+ }
26
+ }
27
+
28
+ function admin_notices(){
29
+ //When editing
30
+ global $post, $EM_Notices;
31
+ if( $post->post_type == EM_POST_TYPE_LOCATION){
32
+ }
33
+ }
34
+
35
+ function admin_notices_filter($messages){
36
+ //When editing
37
+ global $post, $EM_Notices;
38
+ if( $post->post_type == EM_POST_TYPE_LOCATION ){
39
+ if ( $EM_Notices->count_errors() > 0 ) {
40
+ unset($_GET['message']);
41
+ }
42
+ }
43
+ return $messages;
44
+ }
45
+
46
+ function save_post($post_id){
47
+ global $wpdb, $EM_Location, $EM_Notices;
48
+ $saving_status = !in_array(get_post_status($post_id), array('trash','auto-draft')) && !defined('DOING_AUTOSAVE');
49
+ $is_post_type = get_post_type($post_id) == EM_POST_TYPE_LOCATION;
50
+ if(!defined('UNTRASHING_'.$post_id) && $is_post_type && $saving_status){
51
+ if( wp_verify_nonce($_REQUEST['_emnonce'], 'edit_location')){
52
+ do_action('em_location_save_pre', $this);
53
+ $EM_Location = em_get_location($post_id, 'post_id');
54
+ $get_meta = $EM_Location->get_post_meta();
55
+ $save_meta = $EM_Location->save_meta();
56
+ //Handle Errors by making post draft
57
+ if( !$get_meta || !$save_meta ){
58
+ $EM_Location->set_status(null, true);
59
+ $EM_Notices->add_error( '<strong>'.sprintf(__('Your %s details are incorrect and cannot be published, please correct these errors first:','dbem'),__('location','dbem')).'</strong>', true); //Always seems to redirect, so we make it static
60
+ $EM_Notices->add_error($EM_Location->get_errors(), true); //Always seems to redirect, so we make it static
61
+ apply_filters('em_location_save', false , $this);
62
+ }else{
63
+ apply_filters('em_location_save', true , $this);
64
+ }
65
+ }else{
66
+ //do a quick and dirty update
67
+ do_action('em_location_save_pre', $this);
68
+ $EM_Location = new EM_Location($post_id, 'post_id');
69
+ $location_status = ($EM_Location->is_published()) ? 1:0;
70
+ $wpdb->query("UPDATE ".EM_LOCATIONS_TABLE." SET location_name='{$EM_Location->location_name}', location_slug='{$EM_Location->location_slug}', location_private='{$EM_Location->location_private}',location_status={$location_status} WHERE location_id='{$EM_Location->location_id}'");
71
+ apply_filters('em_location_save', true , $this);
72
+ }
73
+ }
74
+ }
75
+
76
+ function before_delete_post($post_id){
77
+ if(get_post_type($post_id) == EM_POST_TYPE_LOCATION){
78
+ $EM_Location = em_get_location($post_id,'post_id');
79
+ $EM_Location->delete_meta();
80
+ }
81
+ }
82
+
83
+ function trashed_post($post_id){
84
+ if(get_post_type($post_id) == EM_POST_TYPE_LOCATION){
85
+ global $EM_Notices;
86
+ $EM_Location = em_get_location($post_id,'post_id');
87
+ $EM_Location->set_status(null);
88
+ $EM_Notices->remove_all(); //no validation/notices needed
89
+ }
90
+ }
91
+
92
+ function untrash_post($post_id){
93
+ if(get_post_type($post_id) == EM_POST_TYPE_LOCATION){
94
+ //set a constant so we know this event doesn't need 'saving'
95
+ if(!defined('UNTRASHING_'.$post_id)) define('UNTRASHING_'.$post_id, true);
96
+ }
97
+ }
98
+
99
+ function untrashed_post($post_id){
100
+ if(get_post_type($post_id) == EM_POST_TYPE_LOCATION){
101
+ global $EM_Notices;
102
+ $EM_Location = em_get_location($post_id,'post_id');
103
+ $EM_Location->set_status(1);
104
+ $EM_Notices->remove_all(); //no validation/notices needed
105
+ }
106
+ }
107
+
108
+ function meta_boxes(){
109
+ add_meta_box('em-location-where', __('Where','dbem'), array('EM_Location_Post_Admin','meta_box_where'),EM_POST_TYPE_LOCATION, 'normal','high');
110
+ //add_meta_box('em-location-metadump', __('EM_Location Meta Dump','dbem'), array('EM_Location_Post_Admin','meta_box_metadump'),EM_POST_TYPE_LOCATION, 'normal','high');
111
+ }
112
+
113
+ function meta_box_metadump(){
114
+ global $post,$EM_Location;
115
+ echo "<pre>"; print_r(get_post_custom($post->ID)); echo "</pre>";
116
+ echo "<pre>"; print_r($EM_Location); echo "</pre>";
117
+ }
118
+ function meta_box_where(){
119
+ ?><input type="hidden" name="_emnonce" value="<?php echo wp_create_nonce('edit_location'); ?>" /><?php
120
+ em_locate_template('forms/location/where.php',true);
121
+ }
122
+ }
123
+ add_action('admin_init',array('EM_Location_Post_Admin','init'));
classes/em-location-post.php ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class EM_Location_Post {
3
+ function init(){
4
+ //Front Side Modifiers
5
+ if( !is_admin() ){
6
+ //override single page with formats?
7
+ add_filter('the_content', array('EM_Location_Post','the_content'));
8
+ //display as page template?
9
+ if( get_option('dbem_cp_locations_template_page') ){
10
+ add_filter('single_template',array('EM_Location_Post','single_template'));
11
+ }
12
+ }
13
+ add_action('parse_query', array('EM_Location_Post','parse_query'));
14
+ }
15
+
16
+ /**
17
+ * Overrides the default post format of a location and can display a location as a page, which uses the page.php template.
18
+ * @param string $template
19
+ * @return string
20
+ */
21
+ function single_template($template){
22
+ global $post;
23
+ if( $post->post_type == EM_POST_TYPE_LOCATION ){
24
+ $template = locate_template(array('page.php','index.php'),false);
25
+ }
26
+ return $template;
27
+ }
28
+
29
+ function the_content( $content ){
30
+ global $post;
31
+ if( $post->post_type == EM_POST_TYPE_LOCATION ){
32
+ if( is_archive() || is_search() ){
33
+ if( get_option('dbem_cp_locations_archive_formats') ){
34
+ $EM_Location = em_get_location($post);
35
+ $content = $EM_Location->output(get_option('dbem_location_list_item_format'));
36
+ }
37
+ }else{
38
+ if( get_option('dbem_cp_locations_formats') && !post_password_required() ){
39
+ $EM_Location = em_get_location($post);
40
+ $content = $EM_Location->output_single();
41
+ }
42
+ }
43
+ }
44
+ return $content;
45
+ }
46
+
47
+ function parse_query( ){
48
+ global $wp_query;
49
+ if( $wp_query->query_vars['post_type'] == EM_POST_TYPE_LOCATION ){
50
+ if( is_admin() ){
51
+ $wp_query->query_vars['orderby'] = (!empty($_REQUEST['orderby'])) ? $_REQUEST['orderby']:'title';
52
+ $wp_query->query_vars['order'] = (!empty($_REQUEST['order'])) ? $_REQUEST['order']:'ASC';
53
+ }else{
54
+ if( empty($wp_query->query_vars['location']) ) {
55
+ if( get_option('dbem_locations_default_archive_orderby') == 'title'){
56
+ $wp_query->query_vars['orderby'] = 'title';
57
+ }else{
58
+ $wp_query->query_vars['orderby'] = 'meta_value_num';
59
+ $wp_query->query_vars['meta_key'] = get_option('dbem_locations_default_archive_orderby','_location_country');
60
+ }
61
+ $wp_query->query_vars['order'] = get_option('dbem_locations_default_archive_orderby','ASC');
62
+ }
63
+ }
64
+ }
65
+ }
66
+ }
67
+ EM_Location_Post::init();
classes/em-location-posts-admin.php ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class EM_Location_Posts_Admin{
3
+ function init(){
4
+ global $pagenow;
5
+ if($pagenow == 'edit.php' && !empty($_REQUEST['post_type']) && $_REQUEST['post_type'] == EM_POST_TYPE_LOCATION ){ //only needed if editing post
6
+ add_action('admin_head', array('EM_Location_Posts_Admin','admin_head'));
7
+ }
8
+ add_filter('manage_edit-location_columns' , array('EM_Location_Posts_Admin','columns_add'));
9
+ add_filter('manage_posts_custom_column' , array('EM_Location_Posts_Admin','columns_output'),10,1 );
10
+ }
11
+
12
+ function admin_head(){
13
+ //quick hacks to make event admin table make more sense for events
14
+ ?>
15
+ <script type="text/javascript">
16
+ jQuery(document).ready( function($){
17
+ $('.inline-edit-date').prev().css('display','none').next().css('display','none').next().css('display','none');
18
+ });
19
+ </script>
20
+ <style>
21
+ table.fixed{ table-layout:auto !important; }
22
+ .tablenav select[name="m"] { display:none; }
23
+ </style>
24
+ <?php
25
+ }
26
+
27
+ function admin_menu(){
28
+ global $menu, $submenu;
29
+ // Add a submenu to the custom top-level menu:
30
+ $plugin_pages = array();
31
+ $plugin_pages[] = add_submenu_page('edit.php?post_type='.EM_POST_TYPE_EVENT, __('Locations', 'dbem'), __('Locations', 'dbem'), 'edit_locations', 'events-manager-locations', "edit.php?post_type=event");
32
+ $plugin_pages = apply_filters('em_create_locationss_submenu',$plugin_pages);
33
+ }
34
+
35
+ function columns_add($columns) {
36
+ unset($columns['author']);
37
+ unset($columns['date']);
38
+ unset($columns['comments']);
39
+ return array_merge($columns, array(
40
+ 'address' => __('Address','dbem'),
41
+ 'town' => __('Town','dbem'),
42
+ 'state' => __('State','dbem'),
43
+ 'country' => __('Country','dbem')
44
+ ));
45
+ }
46
+
47
+ function columns_output( $column ) {
48
+ global $post;
49
+ if( $post->post_type == EM_POST_TYPE_LOCATION ){
50
+ $post = em_get_location($post);
51
+ switch ( $column ) {
52
+ case 'address':
53
+ echo $post->location_address;
54
+ break;
55
+ case 'town':
56
+ echo $post->location_town;
57
+ break;
58
+ case 'state':
59
+ echo $post->location_state;
60
+ break;
61
+ case 'country':
62
+ echo $post->location_country;
63
+ break;
64
+ }
65
+ }
66
+ }
67
+ }
68
+ EM_Location_Posts_Admin::init();
classes/em-location.php CHANGED
@@ -1,159 +1,409 @@
1
  <?php
 
 
 
 
 
 
 
 
 
 
 
 
 
2
  /**
3
  * Object that holds location info and related functions
4
  * @author marcus
5
  */
6
  class EM_Location extends EM_Object {
7
  //DB Fields
8
- var $id = '';
9
- var $name = '';
10
- var $address = '';
11
- var $town = '';
12
- var $latitude = '';
13
- var $longitude = '';
14
- var $description = '';
15
- var $image_url = '';
16
- var $owner = '';
 
 
 
 
 
 
 
17
  //Other Vars
18
  var $fields = array(
19
- 'location_id' => array('name'=>'id','type'=>'%d'),
20
- 'location_name' => array('name'=>'name','type'=>'%s'),
21
- 'location_address' => array('name'=>'address','type'=>'%s'),
22
- 'location_town' => array('name'=>'town','type'=>'%s'),
23
- //Not Used - 'location_province' => array('name'=>'province','type'=>'%s'),
24
- 'location_latitude' => array('name'=>'latitude','type'=>'%f'),
25
- 'location_longitude' => array('name'=>'longitude','type'=>'%f'),
26
- 'location_description' => array('name'=>'description','type'=>'%s'),
27
- 'location_owner' => array('name'=>'owner','type'=>'%d')
 
 
 
 
 
 
 
28
  );
29
- var $required_fields;
 
 
 
30
  var $feedback_message = "";
31
  var $mime_types = array(1 => 'gif', 2 => 'jpg', 3 => 'png');
32
  var $errors = array();
 
 
 
 
 
 
33
 
34
  /**
35
  * Gets data from POST (default), supplied array, or from the database if an ID is supplied
36
  * @param $location_data
 
37
  * @return null
38
  */
39
- function EM_Location( $location_data = 0 ) {
 
40
  //Initialize
41
- $this->required_fields = array("name" => __('The location name', 'dbem'), "address" => __('The location address', 'dbem'), "town" => __('The location town', 'dbem'));
42
- if( $location_data != 0 ){
43
- //Load location data
44
- if( is_array($location_data) && isset($location_data['location_name']) ){
45
- $location = $location_data;
46
- }elseif( $location_data > 0 ){
47
- //Retreiving from the database
48
- global $wpdb;
49
- $sql = "SELECT * FROM ". $wpdb->prefix.EM_LOCATIONS_TABLE ." WHERE location_id ='{$location_data}'";
50
- $location = $wpdb->get_row($sql, ARRAY_A);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
51
  }
52
- //If gmap is turned off, values may not be returned and set, so we set it here
53
- if(empty($location['location_latitude'])) {
54
- $location['location_latitude'] = 0;
55
- $location['location_longitude'] = 0;
 
 
 
 
56
  }
57
- //Save into the object
58
- $this->to_object($location, true);
59
- $this->get_image_url();
60
- }
61
  }
62
 
63
- function get_post(){
64
- //We are getting the values via POST or GET
 
 
 
 
65
  do_action('em_location_get_post_pre', $this);
66
- $location = array();
67
- $location['location_id'] = ( !empty($_POST['location_id']) ) ? $_POST['location_id']:'';
68
- $location['location_name'] = ( !empty($_POST['location_name']) ) ? stripslashes($_POST['location_name']):'';
69
- $location['location_address'] = ( !empty($_POST['location_address']) ) ? stripslashes($_POST['location_address']):'';
70
- $location['location_town'] = ( !empty($_POST['location_town']) ) ? stripslashes($_POST['location_town']):'';
71
- $location['location_latitude'] = ( !empty($_POST['location_latitude']) ) ? $_POST['location_latitude']:'';
72
- $location['location_longitude'] = ( !empty($_POST['location_longitude']) ) ? $_POST['location_longitude']:'';
73
- $location['location_description'] = ( !empty($_POST['content']) ) ? stripslashes($_POST['content']):'';
74
- $this->to_object( apply_filters('em_location_get_post', $location, $this) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
75
  }
76
 
77
  function save(){
78
- global $wpdb, $current_user;
79
- get_currentuserinfo();
 
 
 
 
80
  do_action('em_location_save_pre', $this);
81
- $table = $wpdb->prefix.EM_LOCATIONS_TABLE;
82
- $data = $this->to_array();
83
- unset($data['location_id']);
84
- unset($data['location_image_url']);
85
- if($this->id != ''){
86
- $where = array( 'location_id' => $this->id );
87
- $wpdb->update($table, $data, $where, $this->get_types($data));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
88
  }else{
89
- $this->owner = $current_user->ID; //Record creator of event
90
- $data['location_owner'] = $this->owner;
91
- $wpdb->insert($table, $data, $this->get_types($data));
92
- $this->id = $wpdb->insert_id;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
93
  }
94
- $image_upload = $this->image_upload();
95
- return apply_filters('em_location_save', ( $this->id > 0 && $image_upload ), $this, $image_upload);
96
  }
97
 
98
- function delete(){
99
- global $wpdb;
100
- do_action('em_location_delete_pre', $this);
101
- $table_name = $wpdb->prefix.EM_LOCATIONS_TABLE;
102
- $sql = "DELETE FROM $table_name WHERE location_id = '{$this->id}';";
103
- $result = $wpdb->query($sql);
104
- $result = $this->image_delete() && $result;
105
- return apply_filters('em_location_delete', $result, $this);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
106
  }
107
 
108
- function get_image_url(){
109
- if($this->image_url == ''){
110
- foreach($this->mime_types as $type) {
111
- $file_path = "/".EM_IMAGE_UPLOAD_DIR."/location-{$this->id}.$type";
112
- if( file_exists( ABSPATH . $file_path) ) {
113
- $result = get_bloginfo('wpurl').$file_path;
114
- $this->image_url = $result;
115
- }
116
  }
117
  }
118
- return apply_filters('em_location_get_image_url', $this->image_url, $this);
119
  }
120
 
121
- function image_delete() {
122
- $file_name= ABSPATH.EM_IMAGE_UPLOAD_DIR."/location-".$this->id;
123
  $result = false;
124
- foreach($this->mime_types as $type) {
125
- if (file_exists($file_name.".".$type))
126
- $result = unlink($file_name.".".$type);
127
  }
128
- return apply_filters('em_location_image_delete', $result, $this);
129
  }
130
 
131
- function image_upload(){
132
- //TODO better image upload error handling
133
- do_action('em_location_image_upload_pre', $this);
134
- $result = true;
135
- if ( !empty($_FILES['location_image']['size']) ) {
136
- if( !file_exists(ABSPATH.EM_IMAGE_UPLOAD_DIR) ){
137
- mkdir(ABSPATH.EM_IMAGE_UPLOAD_DIR, 0777);
138
- }
139
- $this->image_delete();
140
- list($width, $height, $type, $attr) = getimagesize($_FILES['location_image']['tmp_name']);
141
- $image_path = ABSPATH.EM_IMAGE_UPLOAD_DIR."/location-".$this->id.".".$this->mime_types[$type];
142
- if (!move_uploaded_file($_FILES['location_image']['tmp_name'], $image_path)){
143
- $this->errors = __('The image could not be loaded','dbem');
144
- $result = false;
145
- }else{
146
- $result = true;
 
 
 
 
 
 
 
 
147
  }
148
  }
149
- return apply_filters('em_location_image_upload', $result, $this);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
150
  }
151
 
152
  function load_similar($criteria){
153
  global $wpdb;
154
  if( !empty($criteria['location_name']) && !empty($criteria['location_name']) && !empty($criteria['location_name']) ){
155
- $locations_table = $wpdb->prefix.EM_LOCATIONS_TABLE;
156
- $prepared_sql = $wpdb->prepare("SELECT * FROM $locations_table WHERE location_name = %s AND location_address = %s AND location_town = %s", stripcslashes($criteria['location_name']), stripcslashes($criteria['location_address']), stripcslashes($criteria['location_town']) );
157
  //$wpdb->show_errors(true);
158
  $location = $wpdb->get_row($prepared_sql, ARRAY_A);
159
  if( is_array($location) ){
@@ -163,93 +413,141 @@ class EM_Location extends EM_Object {
163
  }
164
  return apply_filters('em_location_load_similar', false, $this);
165
  }
166
-
167
- /**
168
- * Validates the location. Should be run during any form submission or saving operation.
169
- * @return boolean
170
- */
171
- function validate(){
172
- foreach ( $this->required_fields as $field => $description) {
173
- if ( $this->$field == "" ) {
174
- $this->errors[] = $description.__(" is missing!", "dbem");
175
- }
176
- }
177
- if ( !empty($_FILES['location_image']) && $_FILES['location_image']['size'] > 0 ) {
178
- if (is_uploaded_file($_FILES['location_image']['tmp_name'])) {
179
- $mime_types = array(1 => 'gif', 2 => 'jpg', 3 => 'png');
180
- $maximum_size = get_option('dbem_image_max_size');
181
- if ($_FILES['location_image']['size'] > $maximum_size){
182
- $this->errors[] = __('The image file is too big! Maximum size:', 'dbem')." $maximum_size";
183
- }
184
- list($width, $height, $type, $attr) = getimagesize($_FILES['location_image']['tmp_name']);
185
- $maximum_width = get_option('dbem_image_max_width');
186
- $maximum_height = get_option('dbem_image_max_height');
187
- if (($width > $maximum_width) || ($height > $maximum_height)) {
188
- $this->errors[] = __('The image is too big! Maximum size allowed:')." $maximum_width x $maximum_height";
189
- }
190
- if (($type!=1) && ($type!=2) && ($type!=3)){
191
- $this->errors[] = __('The image is in a wrong format!');
192
- }
193
- }
194
- }
195
- return apply_filters('em_location_validate', ( count($this->errors) == 0 ), $this);
196
- }
197
 
198
  function has_events(){
199
  global $wpdb;
200
- $events_table = $wpdb->prefix.EM_EVENTS_TABLE;
201
- $sql = "SELECT count(event_id) as events_no FROM $events_table WHERE location_id = {$this->id}";
202
  $affected_events = $wpdb->get_row($sql);
203
  return apply_filters('em_location_has_events', (count($affected_events) > 0), $this);
204
  }
205
 
206
- function can_manage(){
207
- return ( get_option('dbem_permissions_locations') == 2 || $this->owner == get_current_user_id() || empty($this->id) || em_verify_admin() );
208
- }
209
-
210
- function can_use(){
211
- switch( get_option('dbem_permissions_locations') ){
212
- case 0:
213
- return $this->owner == get_current_user_id();
214
- case 1:
215
- return em_verify_admin($this->owner);
216
- case 2:
217
- return true;
218
  }
 
219
  }
220
 
221
  function output_single($target = 'html'){
222
  $format = get_option ( 'dbem_single_location_format' );
223
- return apply_filters('em_location_output_single', $this->output($format, $target), $this, $target);
224
  }
225
 
226
  function output($format, $target="html") {
227
- $location_string = $format;
228
- preg_match_all("/#_[A-Za-z]+/", $format, $placeholders);
229
- foreach($placeholders[0] as $result) {
 
 
 
 
 
 
 
230
  $match = true;
231
  $replace = '';
 
232
  switch( $result ){
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
233
  case '#_MAP': //Depreciated
234
  case '#_LOCATIONMAP':
235
- $replace = EM_Map::get_single( array('location' => $this) );
 
 
236
  break;
237
  case '#_DESCRIPTION': //Depreciated
238
  case '#_EXCERPT': //Depreciated
239
  case '#_LOCATIONNOTES':
240
  case '#_LOCATIONEXCERPT':
241
- $replace = $this->description;
242
  if($result == "#_EXCERPT" || $result == "#_LOCATIONEXCERPT"){
243
- $matches = explode('<!--more', $this->description);
244
  $replace = $matches[0];
245
  }
246
  break;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
247
  case '#_LOCATIONURL':
248
  case '#_LOCATIONLINK':
249
  case '#_LOCATIONPAGEURL': //Depreciated
250
- $joiner = (stristr(EM_URI, "?")) ? "&amp;" : "?";
251
- $link = EM_URI.$joiner."location_id=".$this->id;
252
- $replace = ($result == '#_LOCATIONURL' || $result == '#_LOCATIONPAGEURL') ? $link : '<a href="'.$link.'">'.$this->name.'</a>';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
253
  break;
254
  case '#_PASTEVENTS': //Depreciated
255
  case '#_LOCATIONPASTEVENTS':
@@ -257,10 +555,15 @@ class EM_Location extends EM_Object {
257
  case '#_LOCATIONNEXTEVENTS':
258
  case '#_ALLEVENTS': //Depreciated
259
  case '#_LOCATIONALLEVENTS':
260
- if ($result == '#_PASTEVENTS' || $result == '#_LOCATIONPASTEVENTS'){ $scope = 'past'; }
261
- elseif ( $result == '#_NEXTEVENTS' || $result == '#_LOCATIONNEXTEVENTS' ){ $scope = 'future'; }
 
 
 
 
 
262
  else{ $scope = 'all'; }
263
- $events = EM_Events::get( array('location'=>$this->id, 'scope'=>$scope) );
264
  if ( count($events) > 0 ){
265
  foreach($events as $event){
266
  $replace .= $event->output(get_option('dbem_location_event_list_item_format'));
@@ -269,39 +572,31 @@ class EM_Location extends EM_Object {
269
  $replace = get_option('dbem_location_no_events_message');
270
  }
271
  break;
272
- case '#_IMAGE': //Depreciated
273
- case '#_LOCATIONIMAGE':
274
- if($this->image_url != ''){
275
- $replace = "<img src='".$this->image_url."' alt='".$this->name."'/>";
276
- }
277
- break;
278
- case '#_NAME': //Depreciated
279
- case '#_LOCATIONNAME':
280
- $replace = $this->name;
281
- break;
282
- case '#_ADDRESS': //Depreciated
283
- case '#_LOCATIONADDRESS':
284
- $replace = $this->address;
285
- break;
286
- case '#_TOWN': //Depreciated
287
- case '#_LOCATIONTOWN':
288
- $replace = $this->town;
289
- break;
290
- case '#_LOCATIONID':
291
- $replace = $this->id;
292
- break;
293
  default:
294
  $match = false;
295
  break;
296
  }
297
  if($match){ //if true, we've got a placeholder that needs replacing
298
- //TODO FILTER - placeholder filter
299
- $replace = apply_filters('em_location_output_placeholder', $replace, $this, $result, $target); //USE WITH CAUTION! THIS MIGHT GET RENAMED
300
- $location_string = str_replace($result, $replace , $location_string );
 
 
 
 
301
  }
302
  }
303
  $name_filter = ($target == "html") ? 'dbem_general':'dbem_general_rss'; //TODO remove dbem_ filters
304
- $location_string = str_replace('#_LOCATION', apply_filters($name_filter, $this->name) , $location_string ); //Depreciated
305
  return apply_filters('em_location_output', $location_string, $this, $format, $target);
306
  }
 
 
 
 
 
 
 
 
 
307
  }
1
  <?php
2
+ /**
3
+ * gets a location
4
+ * @param mixed $id
5
+ * @param mixed $search_by
6
+ * @return EM_Location
7
+ */
8
+ function em_get_location($id = false, $search_by = 'location_id') {
9
+ if( is_object($id) && get_class($id) == 'EM_Location' ){
10
+ return $id;
11
+ }else{
12
+ return new EM_Location($id,$search_by);
13
+ }
14
+ }
15
  /**
16
  * Object that holds location info and related functions
17
  * @author marcus
18
  */
19
  class EM_Location extends EM_Object {
20
  //DB Fields
21
+ var $location_id = '';
22
+ var $post_id = '';
23
+ var $blog_id = '';
24
+ var $location_slug = '';
25
+ var $location_name = '';
26
+ var $location_address = '';
27
+ var $location_town = '';
28
+ var $location_state = '';
29
+ var $location_postcode = '';
30
+ var $location_region = '';
31
+ var $location_country = '';
32
+ var $location_latitude = 0;
33
+ var $location_longitude = 0;
34
+ var $post_content = '';
35
+ var $location_owner = '';
36
+ var $location_status = 0;
37
  //Other Vars
38
  var $fields = array(
39
+ 'location_id' => array('name'=>'id','type'=>'%d'),
40
+ 'post_id' => array('name'=>'post_id','type'=>'%d'),
41
+ 'blog_id' => array('name'=>'blog_id','type'=>'%d'),
42
+ 'location_slug' => array('name'=>'slug','type'=>'%s', 'null'=>true),
43
+ 'location_name' => array('name'=>'name','type'=>'%s', 'null'=>true),
44
+ 'location_address' => array('name'=>'address','type'=>'%s','null'=>true),
45
+ 'location_town' => array('name'=>'town','type'=>'%s','null'=>true),
46
+ 'location_state' => array('name'=>'state','type'=>'%s','null'=>true),
47
+ 'location_postcode' => array('name'=>'postcode','type'=>'%s','null'=>true),
48
+ 'location_region' => array('name'=>'region','type'=>'%s','null'=>true),
49
+ 'location_country' => array('name'=>'country','type'=>'%s','null'=>true),
50
+ 'location_latitude' => array('name'=>'latitude','type'=>'%f','null'=>true),
51
+ 'location_longitude' => array('name'=>'longitude','type'=>'%f','null'=>true),
52
+ 'post_content' => array('name'=>'description','type'=>'%s', 'null'=>true),
53
+ 'location_owner' => array('name'=>'owner','type'=>'%d', 'null'=>true),
54
+ 'location_status' => array('name'=>'status','type'=>'%d', 'null'=>true)
55
  );
56
+ var $post_fields = array('post_id','location_slug','location_name','post_content','location_owner');
57
+ var $attributes = array();
58
+ var $image_url = '';
59
+ var $required_fields = array();
60
  var $feedback_message = "";
61
  var $mime_types = array(1 => 'gif', 2 => 'jpg', 3 => 'png');
62
  var $errors = array();
63
+ /**
64
+ * previous status of location
65
+ * @access protected
66
+ * @var mixed
67
+ */
68
+ var $previous_status = 0;
69
 
70
  /**
71
  * Gets data from POST (default), supplied array, or from the database if an ID is supplied
72
  * @param $location_data
73
+ * @param $search_by can be set to post_id or a number for a blog id if in ms mode with global tables, default is location_id
74
  * @return null
75
  */
76
+ function __construct($id = false, $search_by = 'location_id' ) {
77
+ global $wpdb;
78
  //Initialize
79
+ $this->required_fields = array("location_address" => __('The location address', 'dbem'), "location_town" => __('The location town', 'dbem'), "location_country" => __('The country', 'dbem'));
80
+ //Get the post_id/location_id
81
+ $is_post = !empty($id->ID) && $id->post_type == EM_POST_TYPE_LOCATION;
82
+ if( $is_post || absint($id) > 0 ){ //only load info if $id is a number
83
+ if($search_by == 'location_id' && !$is_post){
84
+ //search by location_id, get post_id and blog_id (if in ms mode) and load the post
85
+ $results = $wpdb->get_row($wpdb->prepare("SELECT post_id, blog_id FROM ".EM_LOCATIONS_TABLE." WHERE location_id=%d",$id), ARRAY_A);
86
+ if( !empty($results['post_id']) ){
87
+ if( is_multisite() && is_numeric($results['blog_id']) ){
88
+ $location_post = get_blog_post($results['blog_id'], $results['post_id']);
89
+ $search_by = $results['blog_id'];
90
+ }else{
91
+ $location_post = get_post($results['post_id']);
92
+ }
93
+ }
94
+ }else{
95
+ if(!$is_post){
96
+ if( is_numeric($search_by) && is_multisite() ){
97
+ //we've been given a blog_id, so we're searching for a post id
98
+ $location_post = get_blog_post($search_by, $id);
99
+ }else{
100
+ //search for the post id only
101
+ $location_post = get_post($id);
102
+ }
103
+ }else{
104
+ $location_post = $id;
105
+ }
106
+ }
107
+ $this->load_postdata($location_post, $search_by);
108
+ }
109
+ $this->compat_keys();
110
+ do_action('em_location', $this, $id, $search_by);
111
+ }
112
+
113
+ function load_postdata($location_post, $search_by = false){
114
+ if( is_object($location_post) ){
115
+ if( $location_post->post_status != 'auto-draft' ){
116
+ if( is_numeric($search_by) && is_multisite() ){
117
+ // if in multisite mode, switch blogs quickly to get the right post meta.
118
+ switch_to_blog($search_by);
119
+ $location_meta = get_post_custom($location_post->ID);
120
+ restore_current_blog();
121
+ $this->blog_id = $search_by;
122
+ }else{
123
+ $location_meta = get_post_custom($location_post->ID);
124
+ }
125
+ //Get custom fields
126
+ foreach($location_meta as $location_meta_key => $location_meta_val){
127
+ $found = false;
128
+ foreach($this->fields as $field_name => $field_info){
129
+ if( $location_meta_key == '_'.$field_name){
130
+ $this->$field_name = $location_meta_val[0];
131
+ $found = true;
132
+ }
133
+ }
134
+ if(!$found && $location_meta_key[0] != '_'){
135
+ $this->attributes[$location_meta_key] = ( count($location_meta_val) > 1 ) ? $location_meta_val:$location_meta_val[0];
136
+ }
137
+ }
138
  }
139
+ //load post data - regardless
140
+ $this->post_id = $location_post->ID;
141
+ $this->location_name = $location_post->post_title;
142
+ $this->location_slug = $location_post->post_name;
143
+ $this->location_owner = $location_post->post_author;
144
+ $this->post_content = $location_post->post_content;
145
+ foreach( $location_post as $key => $value ){ //merge the post data into location object
146
+ $this->$key = $value;
147
  }
148
+ $this->previous_status = $this->event_status; //so we know about updates
149
+ $this->get_status();
150
+ }
 
151
  }
152
 
153
+ /**
154
+ * Retrieve event information via POST (used in situations where posts aren't submitted via WP)
155
+ * @param boolean $validate whether or not to run validation, default is true
156
+ * @return boolean
157
+ */
158
+ function get_post($validate = true){
159
  do_action('em_location_get_post_pre', $this);
160
+ $this->location_name = ( !empty($_POST['location_name']) ) ? wp_kses($_POST['location_name'], array()):'';
161
+ $this->post_content = ( !empty($_POST['content']) ) ? wp_kses($_POST['content'], array()):'';
162
+ $this->get_post_meta(false);
163
+ $result = $validate ? $this->validate():true; //validate both post and meta, otherwise return true
164
+ $this->compat_keys();
165
+ return apply_filters('em_location_get_post', $result, $this);
166
+ }
167
+ /**
168
+ * Retrieve event post meta information via POST, which should be always be called when saving the event custom post via WP.
169
+ * @param boolean $validate whether or not to run validation, default is true
170
+ * @return mixed
171
+ */
172
+ function get_post_meta($validate = true){
173
+ //We are getting the values via POST or GET
174
+ do_action('em_location_get_post_meta_pre', $this);
175
+ $this->location_address = ( !empty($_POST['location_address']) ) ? wp_kses($_POST['location_address'], array()):'';
176
+ $this->location_town = ( !empty($_POST['location_town']) ) ? wp_kses($_POST['location_town'], array()):'';
177
+ $this->location_state = ( !empty($_POST['location_state']) ) ? wp_kses($_POST['location_state'], array()):'';
178
+ $this->location_postcode = ( !empty($_POST['location_postcode']) ) ? wp_kses($_POST['location_postcode'], array()):'';
179
+ $this->location_region = ( !empty($_POST['location_region']) ) ? wp_kses($_POST['location_region'], array()):'';
180
+ $this->location_country = ( !empty($_POST['location_country']) ) ? wp_kses($_POST['location_country'], array()):'';
181
+ $this->location_latitude = ( !empty($_POST['location_latitude']) && is_numeric($_POST['location_latitude']) ) ? $_POST['location_latitude']:'';
182
+ $this->location_longitude = ( !empty($_POST['location_longitude']) && is_numeric($_POST['location_longitude']) ) ? $_POST['location_longitude']:'';
183
+ //Set Blog ID
184
+ if( is_multisite() && empty($this->blog_id) ){
185
+ $this->blog_id = get_current_blog_id();
186
+ }
187
+ $result = $validate ? $this->validate_meta():true; //post returns null
188
+ return apply_filters('em_location_get_post_meta',$result,$this);
189
+ }
190
+
191
+ function validate(){
192
+ $validate_post = true;
193
+ if( empty($this->location_name) ){
194
+ $validate_post = false;
195
+ $this->add_error( __('Location name').__(" is required.", "dbem") );
196
+ }
197
+ $validate_meta = $this->validate_meta();
198
+ return apply_filters('em_location_validate', $validate_post && $validate_meta, $this );
199
+ }
200
+
201
+ /**
202
+ * Validates the location. Should be run during any form submission or saving operation.
203
+ * @return boolean
204
+ */
205
+ function validate_meta(){
206
+ //check required fields
207
+ foreach ( $this->required_fields as $field => $description) {
208
+ if( $field == 'location_country' && !array_key_exists($this->location_country, em_get_countries()) ){
209
+ //country specific checking
210
+ $this->add_error( $this->required_fields['location_country'].__(" is required.", "dbem") );
211
+ }elseif ( $this->$field == "" ) {
212
+ $this->add_error( $description.__(" is required.", "dbem") );
213
+ }
214
+ }
215
+ return apply_filters('em_location_validate_meta', ( count($this->errors) == 0 ), $this);
216
  }
217
 
218
  function save(){
219
+ global $wpdb, $current_user, $blog_id;
220
+ //TODO shuffle filters into right place
221
+ if( !$this->can_manage('edit_locations', 'edit_others_locations') && !( get_option('dbem_events_anonymous_submissions') && empty($this->location_id)) ){
222
+ return apply_filters('em_location_save', false, $this);
223
+ }
224
+ remove_action('save_post',array('EM_Location_Post_Admin','save_post'),10,1); //disable the default save post action, we'll do it manually this way
225
  do_action('em_location_save_pre', $this);
226
+ $post_array = array();
227
+ //Deal with updates to a location
228
+ if( !empty($this->post_id) ){
229
+ //get the full array of post data so we don't overwrite anything.
230
+ if( !empty($this->blog_id) && is_multisite() ){
231
+ $post_array = (array) get_blog_post($this->blog_id, $this->post_id);
232
+ }else{
233
+ $post_array = (array) get_post($this->post_id);
234
+ }
235
+ }
236
+ //Overwrite new post info
237
+ $post_array['post_type'] = EM_POST_TYPE_LOCATION;
238
+ $post_array['post_title'] = $this->location_name;
239
+ $post_array['post_content'] = $this->post_content;
240
+ //decide on post status
241
+ if( count($this->errors) == 0 ){
242
+ if( EM_MS_GLOBAL && !is_main_site() && get_site_option('dbem_ms_mainblog_locations') ){
243
+ //if in global ms mode and user is a valid role to publish on their blog, then we will publish the location on the main blog
244
+ restore_current_blog();
245
+ $switch_back = true;
246
+ }
247
+ $post_array['post_status'] = ( current_user_can('publish_locations') ) ? 'publish':'pending';
248
+ if(!empty($switch_back) && get_site_option('dbem_ms_mainblog_locations') ) EM_Object::ms_global_switch(); //switch 'back' to main blog
249
  }else{
250
+ $post_array['post_status'] = 'draft';
251
+ }
252
+ //Anonymous submission
253
+ if( !is_user_logged_in() && get_option('dbem_events_anonymous_submissions') && empty($this->location_id) ){
254
+ $post_array['post_author'] = get_option('dbem_events_anonymous_user');
255
+ if( !is_numeric($post_array['post_author']) ) $post_array['post_author'] = 0;
256
+ }
257
+ //Save post and continue with meta
258
+ $post_id = wp_insert_post($post_array);
259
+ $post_save = false;
260
+ $meta_save = false;
261
+ if( !is_wp_error($post_id) && !empty($post_id) ){
262
+ $post_save = true;
263
+ //refresh this event with wp post
264
+ $post_data = get_post($post_id);
265
+ $this->post_id = $post_id;
266
+ $this->location_slug = $post_data->post_name;
267
+ $this->location_owner = $post_data->post_author;
268
+ $this->post_status = $post_data->post_status;
269
+ $this->get_status();
270
+ //now save the meta
271
+ $meta_save = $this->save_meta();
272
+ //save the image
273
+ $this->image_upload();
274
+ $image_save = (count($this->errors) == 0);
275
+ }elseif(is_wp_error($post_id)){
276
+ //location not saved, add an error
277
+ $this->add_error($post_id->get_error_message());
278
  }
279
+ return apply_filters('em_location_save', $post_save && $meta_save && $image_save, $this);
 
280
  }
281
 
282
+ function save_meta(){
283
+ //echo "<pre>"; print_r($this); echo "</pre>"; die();
284
+ global $wpdb, $current_user;
285
+ if( $this->can_manage('edit_locations','edit_others_locations') || ( get_option('dbem_events_anonymous_submissions') && empty($this->location_id)) ){
286
+ do_action('em_location_save_meta_pre', $this);
287
+ $data = $this->to_array();
288
+ //Update Post Meta
289
+ foreach( array_keys($this->fields) as $key ){
290
+ if( !in_array($key, $this->post_fields) ){
291
+ update_post_meta($this->post_id, '_'.$key, $this->$key);
292
+ }
293
+ }
294
+ $this->get_status();
295
+ $this->location_status = (count($this->errors) == 0) ? $this->location_status:null; //set status at this point, it's either the current status, or if validation fails, null
296
+ //Save to em_locations table
297
+ $location_array = $this->to_array(true);
298
+ if( $this->post_status == 'private' ) $location_array['location_private'] = 1;
299
+ unset($location_array['location_id']);
300
+ if( empty($this->location_id) ){
301
+ $this->previous_status = 0; //for sure this was previously status 0
302
+ if ( !$wpdb->insert(EM_LOCATIONS_TABLE, $location_array) ){
303
+ $this->add_error( sprintf(__('Something went wrong saving your %s to the index table. Please inform a site administrator about this.','dbem'),__('location','dbem')));
304
+ }else{
305
+ //success, so link the event with the post via an event id meta value for easy retrieval
306
+ $this->location_id = $wpdb->insert_id;
307
+ update_post_meta($this->post_id, '_location_id', $this->location_id);
308
+ $this->feedback_message = sprintf(__('Successfully saved %s','dbem'),__('Location','dbem'));
309
+ }
310
+ }else{
311
+ $this->previous_status = $wpdb->get_var('SELECT location_status FROM '.EM_LOCATIONS_TABLE.' WHERE location_id='.$this->location_id); //get status from db, not post_status
312
+ if ( $wpdb->update(EM_LOCATIONS_TABLE, $location_array, array('location_id'=>$this->location_id)) === false ){
313
+ $this->add_error( sprintf(__('Something went wrong updating your %s to the index table. Please inform a site administrator about this.','dbem'),__('location','dbem')));
314
+ }else{
315
+ $this->feedback_message = sprintf(__('Successfully saved %s','dbem'),__('Location','dbem'));
316
+ }
317
+ }
318
+ }else{
319
+ $this->add_error( sprintf(__('You do not have permission to create/edit %s.','dbem'), __('locations','dbem')) );
320
+ }
321
+ return apply_filters('em_location_save_meta', count($this->errors) == 0, $this);
322
  }
323
 
324
+ function delete($force_delete = true){ //atm wp seems to force cp deletions anyway
325
+ global $wpdb;
326
+ $result = false;
327
+ if( $this->can_manage('delete_locations','delete_others_locations') ){
328
+ do_action('em_location_delete_pre', $this);
329
+ $result = wp_delete_post($this->post_id,$force_delete); //the post class will take care of the meta
330
+ if( $force_delete ){
331
+ $result_meta = $this->delete_meta();
332
  }
333
  }
334
+ return apply_filters('em_location_delete', $result !== false && $result_meta, $this);
335
  }
336
 
337
+ function delete_meta(){
338
+ global $wpdb;
339
  $result = false;
340
+ if( $this->can_manage('delete_locations','delete_others_locations') ){
341
+ do_action('em_location_delete_meta_pre', $this);
342
+ $result = $wpdb->query ( $wpdb->prepare("DELETE FROM ". EM_LOCATIONS_TABLE ." WHERE location_id=%d", $this->location_id) );
343
  }
344
+ return apply_filters('em_location_delete_meta', $result !== false, $this);
345
  }
346
 
347
+ function is_published(){
348
+ return apply_filters('em_location_is_published', ($this->post_status == 'publish' || $this->post_status == 'private'), $this);
349
+ }
350
+
351
+ /**
352
+ * Change the status of the location. This will save to the Database too.
353
+ * @param int $status
354
+ * @param boolean $set_post_status
355
+ * @return string
356
+ */
357
+ function set_status($status, $set_post_status = false){
358
+ global $wpdb;
359
+ if($status === null){
360
+ $set_status='NULL';
361
+ if($set_post_status){
362
+ //if the post is trash, don't untrash it!
363
+ $wpdb->update( $wpdb->posts, array( 'post_status' => 'draft' ), array( 'ID' => $this->post_id ) );
364
+ $this->post_status = 'draft';
365
+ }
366
+ }else{
367
+ $set_status = $status ? 1:0;
368
+ if($set_post_status){
369
+ $this->post_status = $post_status = $set_status ? 'publish':'pending';
370
+ $wpdb->update( $wpdb->posts, array( 'post_status' => $post_status ), array( 'ID' => $this->post_id ) );
371
  }
372
  }
373
+ $this->previous_status = $wpdb->get_var('SELECT location_status FROM '.EM_LOCATIONS_TABLE.' WHERE location_id='.$this->location_id); //get status from db, not post_status, as posts get saved quickly
374
+ $result = $wpdb->query("UPDATE ".EM_LOCATIONS_TABLE." SET location_status=$set_status WHERE location_id=".$this->location_id);
375
+ $this->get_status();
376
+ return apply_filters('em_location_set_status', $result !== false, $status, $this);
377
+ }
378
+
379
+ function get_status($db = false){
380
+ switch( $this->post_status ){
381
+ case 'private':
382
+ $this->location_private = 1;
383
+ $this->location_status = $status = 1;
384
+ break;
385
+ case 'publish':
386
+ $this->location_private = 0;
387
+ $this->location_status = $status = 1;
388
+ break;
389
+ case 'pending':
390
+ $this->location_private = 0;
391
+ $this->location_status = $status = 0;
392
+ break;
393
+ default: //draft or unknown
394
+ $this->location_private = 0;
395
+ $status = $db ? 'NULL':null;
396
+ $this->location_status = null;
397
+ break;
398
+ }
399
+ return $status;
400
  }
401
 
402
  function load_similar($criteria){
403
  global $wpdb;
404
  if( !empty($criteria['location_name']) && !empty($criteria['location_name']) && !empty($criteria['location_name']) ){
405
+ $locations_table = EM_LOCATIONS_TABLE;
406
+ $prepared_sql = $wpdb->prepare("SELECT * FROM $locations_table WHERE location_name = %s AND location_address = %s AND location_town = %s AND location_state = %s AND location_postcode = %s AND location_country = %s", stripcslashes($criteria['location_name']), stripcslashes($criteria['location_address']), stripcslashes($criteria['location_town']), stripcslashes($criteria['location_state']), stripcslashes($criteria['location_postcode']), stripcslashes($criteria['location_country']) );
407
  //$wpdb->show_errors(true);
408
  $location = $wpdb->get_row($prepared_sql, ARRAY_A);
409
  if( is_array($location) ){
413
  }
414
  return apply_filters('em_location_load_similar', false, $this);
415
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
416
 
417
  function has_events(){
418
  global $wpdb;
419
+ $events_table = EM_EVENTS_TABLE;
420
+ $sql = "SELECT count(event_id) as events_no FROM $events_table WHERE location_id = {$this->location_id}";
421
  $affected_events = $wpdb->get_row($sql);
422
  return apply_filters('em_location_has_events', (count($affected_events) > 0), $this);
423
  }
424
 
425
+ /**
426
+ * Can the user manage this location?
427
+ */
428
+ function can_manage( $owner_capability = false, $admin_capability = false ){
429
+ if( $owner_capability == 'edit_locations' && $this->location_id == '' && !is_user_logged_in() && get_option('dbem_events_anonymous_submissions') ){
430
+ return apply_filters('em_event_can_manage',true);
 
 
 
 
 
 
431
  }
432
+ return apply_filters('em_location_can_manage', parent::can_manage($owner_capability, $admin_capability), $this);
433
  }
434
 
435
  function output_single($target = 'html'){
436
  $format = get_option ( 'dbem_single_location_format' );
437
+ return apply_filters('em_location_output_single', $this->output($format, $target), $this, $target);
438
  }
439
 
440
  function output($format, $target="html") {
441
+ preg_match_all('/\{([a-zA-Z0-9_]+)\}([^{]+)\{\/[a-zA-Z0-9_]+\}/', $format, $conditionals);
442
+ if( count($conditionals[0]) > 0 ){
443
+ //Check if the language we want exists, if not we take the first language there
444
+ foreach($conditionals[1] as $key => $condition){
445
+ $format = str_replace($conditionals[0][$key], apply_filters('em_location_output_condition', '', $conditionals[0][$key], $condition, $this), $format);
446
+ }
447
+ }
448
+ $location_string = $format;
449
+ preg_match_all("/(#@?_?[A-Za-z0-9]+)({([a-zA-Z0-9,]+)})?/", $format, $placeholders);
450
+ foreach($placeholders[1] as $key => $result) {
451
  $match = true;
452
  $replace = '';
453
+ $full_result = $placeholders[0][$key];
454
  switch( $result ){
455
+ case '#_LOCATIONID':
456
+ $replace = $this->location_id;
457
+ break;
458
+ case '#_NAME': //Depreciated
459
+ case '#_LOCATIONNAME':
460
+ $replace = $this->location_name;
461
+ break;
462
+ case '#_ADDRESS': //Depreciated
463
+ case '#_LOCATIONADDRESS':
464
+ $replace = $this->location_address;
465
+ break;
466
+ case '#_TOWN': //Depreciated
467
+ case '#_LOCATIONTOWN':
468
+ $replace = $this->location_town;
469
+ break;
470
+ case '#_LOCATIONSTATE':
471
+ $replace = $this->location_state;
472
+ break;
473
+ case '#_LOCATIONPOSTCODE':
474
+ $replace = $this->location_postcode;
475
+ break;
476
+ case '#_LOCATIONREGION':
477
+ $replace = $this->location_region;
478
+ break;
479
+ case '#_LOCATIONCOUNTRY':
480
+ $replace = $this->get_country();
481
+ break;
482
+ case '#_LOCATIONFULLLINE':
483
+ $replace = $this->location_address.', ';
484
+ $replace = empty($this->location_town) ? '':', '.$this->location_town;
485
+ $replace = empty($this->location_state) ? '':', '.$this->location_state;
486
+ $replace = empty($this->location_postcode) ? '':', '.$this->location_postcode;
487
+ $replace = empty($this->location_region) ? '':', '.$this->location_region;
488
+ break;
489
+ case '#_LOCATIONFULLBR':
490
+ $replace = $this->location_address.'<br /> ';
491
+ $replace = empty($this->location_town) ? '':'<br /> '.$this->location_town;
492
+ $replace = empty($this->location_state) ? '':'<br /> '.$this->location_state;
493
+ $replace = empty($this->location_postcode) ? '':'<br /> '.$this->location_postcode;
494
+ $replace = empty($this->location_region) ? '':'<br /> '.$this->location_region;
495
+ break;
496
  case '#_MAP': //Depreciated
497
  case '#_LOCATIONMAP':
498
+ ob_start();
499
+ $template = em_locate_template('placeholders/locationmap.php', true, array('EM_Location'=>$this));
500
+ $replace = ob_get_clean();
501
  break;
502
  case '#_DESCRIPTION': //Depreciated
503
  case '#_EXCERPT': //Depreciated
504
  case '#_LOCATIONNOTES':
505
  case '#_LOCATIONEXCERPT':
506
+ $replace = $this->post_content;
507
  if($result == "#_EXCERPT" || $result == "#_LOCATIONEXCERPT"){
508
+ $matches = explode('<!--more', $this->post_content);
509
  $replace = $matches[0];
510
  }
511
  break;
512
+ case '#_LOCATIONIMAGEURL':
513
+ case '#_LOCATIONIMAGE':
514
+ if($this->get_image_url() != ''){
515
+ if($result == '#_LOCATIONIMAGEURL'){
516
+ $replace = $this->get_image_url();
517
+ }else{
518
+ if( empty($placeholders[3][$key]) ){
519
+ $replace = "<img src='".esc_url($this->get_image_url())."' alt='".esc_attr($this->location_name)."'/>";
520
+ }else{
521
+ $image_size = explode(',', $placeholders[3][$key]);
522
+ if( $this->array_is_numeric($image_size) && count($image_size) > 1 ){
523
+ $replace = "<img src='".em_get_thumbnail_url($this->get_image_url(), $image_size[0], $image_size[1])."' alt='".esc_attr($this->location_name)."'/>";
524
+ }else{
525
+ $replace = "<img src='".esc_url($this->get_image_url())."' alt='".esc_attr($this->location_name)."'/>";
526
+ }
527
+ }
528
+ }
529
+ }
530
+ break;
531
  case '#_LOCATIONURL':
532
  case '#_LOCATIONLINK':
533
  case '#_LOCATIONPAGEURL': //Depreciated
534
+
535
+ if( EM_MS_GLOBAL ){
536
+ if( get_site_option('dbem_ms_global_locations_links') && !empty($this->blog_id) && is_main_site() && $this->blog_id != get_current_blog_id() ){
537
+ //linking directly to the blog, we should be on the main blog here
538
+ $link = get_blog_permalink( $this->blog_id, $this->post_id);
539
+ }elseif( !empty($this->blog_id) && is_main_site() && $this->blog_id != get_current_blog_id() ){
540
+ if( get_option('dbem_locations_page') ){
541
+ $link = trailingslashit(get_permalink(get_option('dbem_locations_page')).get_site_option('dbem_ms_locations_slug',EM_LOCATION_SLUG).'/'.$this->location_slug.'-'.$this->location_id);
542
+ }else{
543
+ $link = trailingslashit(home_url()).EM_POST_TYPE_LOCATION_SLUG.'/'.get_site_option('dbem_ms_events_slug',EM_LOCATION_SLUG).'/'.$this->location_slug.'-'.$this->location_id;
544
+ }
545
+ }
546
+ }
547
+ if( empty($link) ){
548
+ $link = get_post_permalink($this->post_id);
549
+ }
550
+ $replace = ($result == '#_LOCATIONURL' || $result == '#_LOCATIONPAGEURL') ? $link : '<a href="'.$link.'" title="'.esc_attr($this->location_name).'">'.esc_html($this->location_name).'</a>';
551
  break;
552
  case '#_PASTEVENTS': //Depreciated
553
  case '#_LOCATIONPASTEVENTS':
555
  case '#_LOCATIONNEXTEVENTS':
556
  case '#_ALLEVENTS': //Depreciated
557
  case '#_LOCATIONALLEVENTS':
558
+ //convert depreciated placeholders for compatability
559
+ $result = ($result == '#_PASTEVENTS') ? '#_LOCATIONPASTEVENTS':$result;
560
+ $result = ($result == '#_NEXTEVENTS') ? '#_LOCATIONNEXTEVENTS':$result;
561
+ $result = ($result == '#_ALLEVENTS') ? '#_LOCATIONALLEVENTS':$result;
562
+ //forget it ever happened? :/
563
+ if ( $result == '#_LOCATIONPASTEVENTS'){ $scope = 'past'; }
564
+ elseif ( $result == '#_LOCATIONNEXTEVENTS' ){ $scope = 'future'; }
565
  else{ $scope = 'all'; }
566
+ $events = EM_Events::get( array('location'=>$this->location_id, 'scope'=>$scope) );
567
  if ( count($events) > 0 ){
568
  foreach($events as $event){
569
  $replace .= $event->output(get_option('dbem_location_event_list_item_format'));
572
  $replace = get_option('dbem_location_no_events_message');
573
  }
574
  break;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
575
  default:
576
  $match = false;
577
  break;
578
  }
579
  if($match){ //if true, we've got a placeholder that needs replacing
580
+ $replace = apply_filters('em_location_output_placeholder', $replace, $this, $full_result, $target); //USE WITH CAUTION! THIS MIGHT GET RENAMED
581
+ $location_string = str_replace($full_result, $replace , $location_string );
582
+ }else{
583
+ $custom_replace = apply_filters('em_location_output_placeholder', $replace, $this, $full_result, $target); //USE WITH CAUTION! THIS MIGHT GET RENAMED
584
+ if($custom_replace != $replace){
585
+ $location_string = str_replace($full_result, $custom_replace , $location_string );
586
+ }
587
  }
588
  }
589
  $name_filter = ($target == "html") ? 'dbem_general':'dbem_general_rss'; //TODO remove dbem_ filters
590
+ $location_string = str_replace('#_LOCATION', apply_filters($name_filter, $this->location_name) , $location_string ); //Depreciated
591
  return apply_filters('em_location_output', $location_string, $this, $format, $target);
592
  }
593
+
594
+ function get_country(){
595
+ $countries = em_get_countries();
596
+ if( !empty($countries[$this->location_country]) ){
597
+ return apply_filters('em_location_get_country', $countries[$this->location_country], $this);
598
+ }
599
+ return apply_filters('em_location_get_country', false, $this);
600
+
601
+ }
602
  }
classes/em-locations.php CHANGED
@@ -4,20 +4,26 @@
4
  * Optimized for specifically retreiving locations (whether eventful or not). If you want event data AND location information for each event, use EM_Events
5
  *
6
  */
7
- class EM_Locations extends EM_Object {
 
 
 
 
 
 
8
  /**
9
  * Returns an array of EM_Location objects
10
  * @param boolean $eventful
11
  * @param boolean $return_objects
12
  * @return array
13
  */
14
- function get( $args = array() ){
15
  global $wpdb;
16
- $events_table = $wpdb->prefix . EM_EVENTS_TABLE;
17
- $locations_table = $wpdb->prefix . EM_LOCATIONS_TABLE;
18
 
19
  //Quick version, we can accept an array of IDs, which is easy to retrieve
20
- if( self::array_is_numeric($args) && count() ){ //Array of numbers, assume they are event IDs to retreive
21
  //We can just get all the events here and return them
22
  $sql = "SELECT * FROM $locations_table WHERE location_id=".implode(" OR location_id=", $args);
23
  $results = $wpdb->get_results($sql,ARRAY_A);
@@ -25,9 +31,13 @@ class EM_Locations extends EM_Object {
25
  foreach($results as $result){
26
  $locations[$result['location_id']] = new EM_Location($result);
27
  }
28
- return $locations; //We return all the events matched as an EM_Event array.
29
- }
30
-
 
 
 
 
31
 
32
  //We assume it's either an empty array or array of search arguments to merge with defaults
33
  $args = self::get_default_search($args);
@@ -50,31 +60,49 @@ class EM_Locations extends EM_Object {
50
  //Now, build orderby sql
51
  $orderby_sql = ( count($orderby) > 0 ) ? 'ORDER BY '. implode(', ', $orderby) : '';
52
 
53
-
 
 
 
 
 
54
  //Create the SQL statement and execute
55
  $sql = "
56
- SELECT $fields FROM $locations_table
57
  LEFT JOIN $events_table ON {$locations_table}.location_id={$events_table}.location_id
58
  $where
59
- GROUP BY location_id
60
  $orderby_sql
61
  $limit $offset
62
  ";
63
-
 
 
 
 
64
  $results = $wpdb->get_results($sql, ARRAY_A);
65
 
66
  //If we want results directly in an array, why not have a shortcut here?
67
  if( $args['array'] == true ){
68
- return $results;
69
  }
70
 
71
- $locations = array();
72
- foreach ($results as $location){
73
- $locations[] = new EM_Location($location);
 
 
 
 
 
74
  }
75
  return apply_filters('em_locations_get', $locations, $args);
76
  }
77
 
 
 
 
 
78
  /**
79
  * Output a set of matched of events
80
  * @param array $args
@@ -87,41 +115,37 @@ class EM_Locations extends EM_Object {
87
  if( is_object(current($args)) && get_class((current($args))) == 'EM_Location' ){
88
  $func_args = func_get_args();
89
  $locations = $func_args[0];
90
- $args = apply_filters('em_locations_output_args', self::get_default_search($func_args[1]), $locations);
 
91
  $limit = ( !empty($args['limit']) && is_numeric($args['limit']) ) ? $args['limit']:false;
92
  $offset = ( !empty($args['offset']) && is_numeric($args['offset']) ) ? $args['offset']:0;
93
  $page = ( !empty($args['page']) && is_numeric($args['page']) ) ? $args['page']:1;
 
94
  }else{
95
  $args = apply_filters('em_locations_output_args', self::get_default_search($args) );
96
  $limit = ( !empty($args['limit']) && is_numeric($args['limit']) ) ? $args['limit']:false;
97
  $offset = ( !empty($args['offset']) && is_numeric($args['offset']) ) ? $args['offset']:0;
98
  $page = ( !empty($args['page']) && is_numeric($args['page']) ) ? $args['page']:1;
99
- $args['limit'] = false;
100
- $args['offset'] = false;
101
- $args['page'] = false;
 
 
102
  $locations = self::get( $args );
103
  }
104
  //What format shall we output this to, or use default
105
  $format = ( $args['format'] == '' ) ? get_option( 'dbem_location_list_item_format' ) : $args['format'] ;
106
 
107
  $output = "";
108
- $locations_count = count($locations);
109
- $locations = apply_filters('em_locations_output_locations', $locations);
110
-
111
  if ( count($locations) > 0 ) {
112
- $location_count = 0;
113
- $locations_shown = 0;
114
  foreach ( $locations as $EM_Location ) {
115
- if( ($locations_shown < $limit || empty($limit)) && ($location_count >= $offset || $offset === 0) ){
116
- $output .= $EM_Location->output($format);
117
- $locations_shown++;
118
- }
119
- $location_count++;
120
  }
121
  //Add headers and footers to output
122
  if( $format == get_option ( 'dbem_location_list_item_format' ) ){
123
  $single_event_format_header = get_option ( 'dbem_location_list_item_format_header' );
124
- $single_event_format_header = ( $single_event_format_header != '' ) ? $single_event_format_header : "<ul class='dbem_events_list'>";
125
  $single_event_format_footer = get_option ( 'dbem_location_list_item_format_footer' );
126
  $single_event_format_footer = ( $single_event_format_footer != '' ) ? $single_event_format_footer : "</ul>";
127
  $output = $single_event_format_header . $output . $single_event_format_footer;
@@ -130,26 +154,39 @@ class EM_Locations extends EM_Object {
130
  if( !empty($args['pagination']) && !empty($limit) && $locations_count >= $limit ){
131
  //Show the pagination links (unless there's less than 10 events
132
  $page_link_template = preg_replace('/(&|\?)page=\d+/i','',$_SERVER['REQUEST_URI']);
133
- $page_link_template = em_add_get_params($page_link_template, array('page'=>'%PAGE%'));
134
  $output .= apply_filters('em_events_output_pagination', em_paginate( $page_link_template, $locations_count, $limit, $page), $page_link_template, $locations_count, $limit, $page);
135
  }
136
  } else {
137
- $output = get_option ( 'dbem_no_events_message' );
138
  }
139
  //FIXME check if reference is ok when restoring object, due to changes in php5 v 4
140
  $EM_Location_old= $EM_Location;
141
  return apply_filters('em_locations_output', $output, $locations, $args);
142
  }
143
 
 
 
 
 
 
 
 
 
 
 
 
 
 
144
  /**
145
  * Builds an array of SQL query conditions based on regularly used arguments
146
  * @param array $args
147
  * @return array
148
  */
149
- function build_sql_conditions( $args = array() ){
150
  global $wpdb;
151
- $events_table = $wpdb->prefix . EM_EVENTS_TABLE;
152
- $locations_table = $wpdb->prefix . EM_LOCATIONS_TABLE;
153
 
154
  $conditions = parent::build_sql_conditions($args);
155
  //eventful locations
@@ -160,10 +197,29 @@ class EM_Locations extends EM_Object {
160
  }
161
  //owner lookup
162
  if( !empty($args['owner']) ){
163
- if ( get_option('dbem_permissions_locations') < 1 && !em_verify_admin() ){
164
- $conditions['owner'] = "location_owner=".get_current_user_id();
 
 
 
 
 
 
165
  }
166
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
167
  return apply_filters('em_locations_build_sql_conditions', $conditions, $args);
168
  }
169
 
@@ -182,32 +238,57 @@ class EM_Locations extends EM_Object {
182
  $defaults = array(
183
  'eventful' => false, //Locations that have an event (scope will also play a part here
184
  'eventless' => false, //Locations WITHOUT events, eventful takes precedence
185
- 'orderby' => 'name',
186
- 'scope' => 'all' //we probably want to search all locations by default, not like events
 
 
 
 
 
 
 
 
187
  );
 
 
 
 
 
 
 
 
188
  $array['eventful'] = ( !empty($array['eventful']) && $array['eventful'] == true );
189
  $array['eventless'] = ( !empty($array['eventless']) && $array['eventless'] == true );
190
  if( is_admin() ){
191
- //by default, we only get categories the owner can manage
192
- switch( get_option('dbem_permissions_locations') ){
193
- case 0:
194
- $defaults['owner'] = get_current_user_id();
195
- break;
196
- case 1:
197
- $wp_user_search = new WP_User_Search(null, null, 'administrator');
198
- $users = $wp_user_search->get_results();
199
- $users[] = get_current_user_id();
200
- $users[] = 0;
201
- $defaults['owner'] = implode(',', $users);
202
- break;
203
- case 2:
204
- $defaults['owner'] = false;
205
- break;
206
- }
207
- $defaults['owner'] = ( em_verify_admin() ) ? false:$defaults['owner'];
208
  }
209
  return apply_filters('em_locations_get_default_search', parent::get_default_search($defaults, $array), $array, $defaults);
210
  }
211
- //TODO for all the static plural classes like this one, we might benefit from bulk actions like delete/add/save etc.... just a random thought.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
212
  }
213
  ?>
4
  * Optimized for specifically retreiving locations (whether eventful or not). If you want event data AND location information for each event, use EM_Events
5
  *
6
  */
7
+ class EM_Locations extends EM_Object implements Iterator {
8
+ /**
9
+ * Array of EM_Location objects
10
+ * @var array EM_Location
11
+ */
12
+ var $locations = array();
13
+
14
  /**
15
  * Returns an array of EM_Location objects
16
  * @param boolean $eventful
17
  * @param boolean $return_objects
18
  * @return array
19
  */
20
+ function get( $args = array(), $count=false ){
21
  global $wpdb;
22
+ $events_table = EM_EVENTS_TABLE;
23
+ $locations_table = EM_LOCATIONS_TABLE;
24
 
25
  //Quick version, we can accept an array of IDs, which is easy to retrieve
26
+ if( self::array_is_numeric($args) ){ //Array of numbers, assume they are event IDs to retreive
27
  //We can just get all the events here and return them
28
  $sql = "SELECT * FROM $locations_table WHERE location_id=".implode(" OR location_id=", $args);
29
  $results = $wpdb->get_results($sql,ARRAY_A);
31
  foreach($results as $result){
32
  $locations[$result['location_id']] = new EM_Location($result);
33
  }
34
+ return apply_filters('em_locations_get', $locations, $args); //We return all the events matched as an EM_Event array.
35
+ }elseif( is_numeric($args) ){
36
+ //return an event in the usual array format
37
+ return apply_filters('em_locations_get', array(new EM_Location($args)), $args);
38
+ }elseif( is_array($args) && is_object(current($args)) && get_class((current($args))) == 'EM_Location' ){
39
+ return apply_filters('em_locations_get', $args, $args);
40
+ }
41
 
42
  //We assume it's either an empty array or array of search arguments to merge with defaults
43
  $args = self::get_default_search($args);
60
  //Now, build orderby sql
61
  $orderby_sql = ( count($orderby) > 0 ) ? 'ORDER BY '. implode(', ', $orderby) : '';
62
 
63
+ $fields = ( $count ) ? $locations_table.'.location_id':$locations_table.'.post_id';
64
+ if( EM_MS_GLOBAL ){
65
+ $selectors = ( $count ) ? 'COUNT('.$locations_table.'.location_id)':$locations_table.'.post_id, '.$locations_table.'.blog_id';
66
+ }else{
67
+ $selectors = ( $count ) ? 'COUNT('.$locations_table.'.location_id)':$locations_table.'.post_id';
68
+ }
69
  //Create the SQL statement and execute
70
  $sql = "
71
+ SELECT $selectors FROM $locations_table
72
  LEFT JOIN $events_table ON {$locations_table}.location_id={$events_table}.location_id
73
  $where
74
+ GROUP BY {$locations_table}.location_id
75
  $orderby_sql
76
  $limit $offset
77
  ";
78
+
79
+ //If we're only counting results, return the number of results
80
+ if( $count ){
81
+ return apply_filters('em_locations_get_array', count($wpdb->get_col($sql)), $args);
82
+ }
83
  $results = $wpdb->get_results($sql, ARRAY_A);
84
 
85
  //If we want results directly in an array, why not have a shortcut here?
86
  if( $args['array'] == true ){
87
+ return apply_filters('em_locations_get_array', $results, $args);
88
  }
89
 
90
+ if( EM_MS_GLOBAL ){
91
+ foreach ( $results as $location ){
92
+ $locations[] = em_get_location($location['post_id'], $location['blog_id']);
93
+ }
94
+ }else{
95
+ foreach ( $results as $location ){
96
+ $locations[] = em_get_location($location['post_id'], 'post_id');
97
+ }
98
  }
99
  return apply_filters('em_locations_get', $locations, $args);
100
  }
101
 
102
+ function count( $args = array() ){
103
+ return apply_filters('em_locations_count', self::get($args, true), $args);
104
+ }
105
+
106
  /**
107
  * Output a set of matched of events
108
  * @param array $args
115
  if( is_object(current($args)) && get_class((current($args))) == 'EM_Location' ){
116
  $func_args = func_get_args();
117
  $locations = $func_args[0];
118
+ $args = (!empty($func_args[1])) ? $func_args[1] : array();
119
+ $args = apply_filters('em_locations_output_args', self::get_default_search($args), $locations);
120
  $limit = ( !empty($args['limit']) && is_numeric($args['limit']) ) ? $args['limit']:false;
121
  $offset = ( !empty($args['offset']) && is_numeric($args['offset']) ) ? $args['offset']:0;
122
  $page = ( !empty($args['page']) && is_numeric($args['page']) ) ? $args['page']:1;
123
+ $locations_count = count($locations);
124
  }else{
125
  $args = apply_filters('em_locations_output_args', self::get_default_search($args) );
126
  $limit = ( !empty($args['limit']) && is_numeric($args['limit']) ) ? $args['limit']:false;
127
  $offset = ( !empty($args['offset']) && is_numeric($args['offset']) ) ? $args['offset']:0;
128
  $page = ( !empty($args['page']) && is_numeric($args['page']) ) ? $args['page']:1;
129
+ $args_count = $args;
130
+ $args_count['limit'] = 0;
131
+ $args_count['offset'] = 0;
132
+ $args_count['page'] = 1;
133
+ $locations_count = self::count($args_count);
134
  $locations = self::get( $args );
135
  }
136
  //What format shall we output this to, or use default
137
  $format = ( $args['format'] == '' ) ? get_option( 'dbem_location_list_item_format' ) : $args['format'] ;
138
 
139
  $output = "";
140
+ $locations = apply_filters('em_locations_output_locations', $locations);
 
 
141
  if ( count($locations) > 0 ) {
 
 
142
  foreach ( $locations as $EM_Location ) {
143
+ $output .= $EM_Location->output($format);
 
 
 
 
144
  }
145
  //Add headers and footers to output
146
  if( $format == get_option ( 'dbem_location_list_item_format' ) ){
147
  $single_event_format_header = get_option ( 'dbem_location_list_item_format_header' );
148
+ $single_event_format_header = ( $single_event_format_header != '' ) ? $single_event_format_header : "<ul class='em-locations-list'>";
149
  $single_event_format_footer = get_option ( 'dbem_location_list_item_format_footer' );
150
  $single_event_format_footer = ( $single_event_format_footer != '' ) ? $single_event_format_footer : "</ul>";
151
  $output = $single_event_format_header . $output . $single_event_format_footer;
154
  if( !empty($args['pagination']) && !empty($limit) && $locations_count >= $limit ){
155
  //Show the pagination links (unless there's less than 10 events
156
  $page_link_template = preg_replace('/(&|\?)page=\d+/i','',$_SERVER['REQUEST_URI']);
157
+ $page_link_template = em_add_get_params($page_link_template, array('page'=>'%PAGE%'), false); //don't html encode, so em_paginate does its thing
158
  $output .= apply_filters('em_events_output_pagination', em_paginate( $page_link_template, $locations_count, $limit, $page), $page_link_template, $locations_count, $limit, $page);
159
  }
160
  } else {
161
+ $output = get_option ( 'dbem_no_locations_message' );
162
  }
163
  //FIXME check if reference is ok when restoring object, due to changes in php5 v 4
164
  $EM_Location_old= $EM_Location;
165
  return apply_filters('em_locations_output', $output, $locations, $args);
166
  }
167
 
168
+ function delete( $args = array() ){
169
+ if( !is_object(current($args)) && get_class((current($args))) != 'EM_Location' ){
170
+ $locations = self::get($args);
171
+ }else{
172
+ $locations = $args;
173
+ }
174
+ $results = array();
175
+ foreach ( $locations as $EM_Location ){
176
+ $results[] = $EM_Location->delete();
177
+ }
178
+ return apply_filters('em_locations_delete', in_array(false, $results), $locations);
179
+ }
180
+
181
  /**
182
  * Builds an array of SQL query conditions based on regularly used arguments
183
  * @param array $args
184
  * @return array
185
  */
186
+ function build_sql_conditions( $args = array(), $count=false ){
187
  global $wpdb;
188
+ $events_table = EM_EVENTS_TABLE;
189
+ $locations_table = EM_LOCATIONS_TABLE;
190
 
191
  $conditions = parent::build_sql_conditions($args);
192
  //eventful locations
197
  }
198
  //owner lookup
199
  if( !empty($args['owner']) ){
200
+ $conditions['owner'] = "location_owner=".$args['owner'];
201
+ }
202
+ //blog id in events table
203
+ if( is_multisite() && array_key_exists('blog',$args) && is_numeric($args['blog']) ){
204
+ if( is_main_site($args['blog']) ){
205
+ $conditions['blog'] = "($locations_table.blog_id={$args['blog']} OR $locations_table.blog_id IS NULL)";
206
+ }else{
207
+ $conditions['blog'] = "($locations_table.blog_id={$args['blog']})";
208
  }
209
  }
210
+ //status
211
+ if( array_key_exists('status',$args) && is_numeric($args['status']) ){
212
+ $null = ($args['status'] == 0) ? ' OR `location_status` = 0':'';
213
+ $conditions['status'] = "(`location_status`={$args['status']}{$null} )";
214
+ }else{
215
+ $conditions['status'] = "(`location_status` IS NOT NULL)";
216
+ }
217
+ //private locations
218
+ if( !empty($args['private']) ){
219
+ $conditions['private'] = "(`location_private`=0)";
220
+ }elseif( !empty($args['private_only']) ){
221
+ $conditions['private_only'] = "(`location_private`=1)";
222
+ }
223
  return apply_filters('em_locations_build_sql_conditions', $conditions, $args);
224
  }
225
 
238
  $defaults = array(
239
  'eventful' => false, //Locations that have an event (scope will also play a part here
240
  'eventless' => false, //Locations WITHOUT events, eventful takes precedence
241
+ 'orderby' => 'location_name',
242
+ 'town' => false,
243
+ 'state' => false,
244
+ 'country' => false,
245
+ 'region' => false,
246
+ 'status' => 1, //approved locations only
247
+ 'scope' => 'all', //we probably want to search all locations by default, not like events
248
+ 'blog' => get_current_blog_id(),
249
+ 'private' => !current_user_can('read_private_locations'),
250
+ 'private_only' => false
251
  );
252
+ if(is_multisite()){
253
+ global $bp;
254
+ if( !is_main_site() && !array_key_exists('blog', $array) ){
255
+ $array['blog'] = get_current_blog_id();
256
+ }elseif( empty($array['blog']) && get_site_option('dbem_ms_global_locations') ) {
257
+ $array['blog'] = false;
258
+ }
259
+ }
260
  $array['eventful'] = ( !empty($array['eventful']) && $array['eventful'] == true );
261
  $array['eventless'] = ( !empty($array['eventless']) && $array['eventless'] == true );
262
  if( is_admin() ){
263
+ $defaults['owner'] = !current_user_can('read_others_locations') ? get_current_user_id():false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
264
  }
265
  return apply_filters('em_locations_get_default_search', parent::get_default_search($defaults, $array), $array, $defaults);
266
  }
267
+
268
+ //Iteratior methods
269
+ public function rewind(){
270
+ reset($this->locations);
271
+ }
272
+
273
+ public function current(){
274
+ $var = current($this->locations);
275
+ return $var;
276
+ }
277
+
278
+ public function key(){
279
+ $var = key($this->locations);
280
+ return $var;
281
+ }
282
+
283
+ public function next(){
284
+ $var = next($this->locations);
285
+ return $var;
286
+ }
287
+
288
+ public function valid(){
289
+ $key = key($this->locations);
290
+ $var = ($key !== NULL && $key !== FALSE);
291
+ return $var;
292
+ }
293
  }
294
  ?>
classes/em-mailer.php CHANGED
@@ -23,7 +23,10 @@ class EM_Mailer {
23
  if( preg_match('/^[_.0-9a-z-]+@([0-9a-z][0-9a-z-]+.)+[a-z]{2,3}$/i', $receiver) ){
24
  $this->load_phpmailer();
25
  $mail = new EM_PHPMailer();
26
- //$mail->SMTPDebug = true;
 
 
 
27
  $mail->ClearAllRecipients();
28
  $mail->ClearAddresses();
29
  $mail->ClearAttachments();
23
  if( preg_match('/^[_.0-9a-z-]+@([0-9a-z][0-9a-z-]+.)+[a-z]{2,3}$/i', $receiver) ){
24
  $this->load_phpmailer();
25
  $mail = new EM_PHPMailer();
26
+ //$mail->SMTPDebug = true;
27
+ if( get_option('dbem_smtp_html') ){
28
+ $mail->isHTML();
29
+ }
30
  $mail->ClearAllRecipients();
31
  $mail->ClearAddresses();
32
  $mail->ClearAttachments();
classes/em-map.php DELETED
@@ -1,60 +0,0 @@
1
- <?php
2
- /**
3
- * Obtains the html required to display a google map for given location(s)
4
- *
5
- */
6
- class EM_Map extends EM_Object {
7
- /**
8
- * Shortcode for producing a google map with all the locations. Unfinished and undocumented.
9
- * @param array $atts
10
- * @return string
11
- */
12
- function get_global($atts) {
13
- //TODO Finish and document this feature, need to add balloons here
14
- if (get_option('dbem_gmap_is_active') == '1') {
15
- ob_start();
16
- $atts['em_ajax'] = true;
17
- $atts['query'] = 'GlobalMapData';
18
- $rand = substr(md5(rand().rand()),0,5);
19
- //build js array of arguments to send to event query
20
- ?>
21
- <div class='em-locations-map' id='em-locations-map-<?php echo $rand; ?>' style='width:<?php echo $atts['width']; ?>px; height:<?php echo $atts['height']; ?>px'><em><?php _e('Loading Map....', 'dbem'); ?></em></div>
22
- <div class='em-locations-map-coords' id='em-locations-map-coords-<?php echo $rand; ?>' style="display:none; visibility:hidden;"><?php echo EM_Object::json_encode($atts); ?></div>
23
- <?php
24
- return apply_filters('em_map_get_global', ob_get_clean());
25
- }else{
26
- return '';
27
- }
28
- }
29
-
30
-
31
- /**
32
- * Returns th HTML and JS required to produce a google map in for this location.
33
- * @param EM_Location $location
34
- * @return string
35
- */
36
- function get_single($args) {
37
- //TODO do some validation here of defaults
38
- //FIXME change baloon to balloon for consistent spelling
39
- $location = $args['location'];
40
- if ( get_option('dbem_gmap_is_active') && ( is_object($location) && $location->latitude != 0 && $location->longitude != 0 ) ) {
41
- $width = (isset($args['width'])) ? $args['width']:'400';
42
- $height = (isset($args['height'])) ? $args['height']:'300';
43
- ob_start();
44
- $rand = substr(md5(rand().rand()),0,5);
45
- ?>
46
- <div class='em-location-map' id='em-location-map-<?php echo $rand ?>' style='background: #CDCDCD; width: <?php echo $width ?>px; height: <?php echo $height ?>px'><?php _e('Loading Map....', 'dbem'); ?></div>
47
- <div class='em-location-map-info' id='em-location-map-info-<?php echo $rand ?>' style="display:none; visibility:hidden;"><div class="em-map-balloon" style="font-size:12px;"><div class="em-map-balloon-content" ><?php echo $location->output(get_option('dbem_location_baloon_format')); ?></div></div></div>
48
- <div class='em-location-map-coords' id='em-location-map-coords-<?php echo $rand ?>' style="display:none; visibility:hidden;">
49
- <span class="lat"><?php echo $location->latitude; ?></span>
50
- <span class="lng"><?php echo $location->longitude; ?></span>
51
- </div>
52
- <?php
53
- return ob_get_clean();
54
- }elseif( is_object($location) && $location->latitude == 0 && $location->longitude == 0 ){
55
- return '<i>'. __('Map Unavailable', 'dbem') .'</i>';
56
- }else{
57
- return '';
58
- }
59
- }
60
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
classes/em-notices.php ADDED
@@ -0,0 +1,196 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ *
4
+ * @author marcus
5
+ *
6
+ */
7
+ class EM_Notices implements Iterator {
8
+ var $notices = array('errors'=>array(), 'infos'=>array(), 'alerts'=>array(), 'confirms'=>array());
9
+
10
+ function __construct(){
11
+ session_start();
12
+ //Grab from session
13
+ if( !empty($_SESSION['events-manager']['notices']) && is_serialized($_SESSION['events-manager']['notices']) ){
14
+ $this->notices = unserialize($_SESSION['events-manager']['notices']);
15
+ }
16
+ //Flush notices that weren't made to stay cross-requests, we can do this if initialized immediately.
17
+ foreach($this->notices as $notice_type => $notices){
18
+ foreach ($notices as $key => $notice){
19
+ if( empty($notice['static']) ){
20
+ unset($this->notices[$notice_type][$key]);
21
+ }else{
22
+ unset($this->notices[$notice_type][$key]['static']); //so it gets removed next request
23
+ }
24
+ }
25
+ }
26
+ add_action('shutdown', array(&$this,'destruct'));
27
+ add_filter('wp_redirect', array(&$this,'destruct'), 1,1);
28
+ }
29
+
30
+ function destruct($redirect = false){
31
+ //die('destructing');
32
+ $_SESSION['events-manager']['notices'] = serialize($this->notices);
33
+ return $redirect;
34
+ }
35
+
36
+ function __toString(){
37
+ $string = false;
38
+ if(count($this->notices['errors']) > 0){
39
+ $string .= "<div class='em-warning em-warning-errors error'>{$this->get_errors()}</div>";
40
+ }
41
+ if(count($this->notices['alerts']) > 0){
42
+ $string .= "<div class='em-warning em-warning-alerts updated'>{$this->get_alerts()}</div>";
43
+ }
44
+ if(count($this->notices['infos']) > 0){
45
+ $string .= "<div class='em-warning em-warning-infos updated'>{$this->get_infos()}</div>";
46
+ }
47
+ if(count($this->notices['confirms']) > 0){
48
+ $string .= "<div class='em-warning em-warning-confirms updated'>{$this->get_confirms()}</div>";
49
+ }
50
+ return ($string !== false) ? "<div class='statusnotice'>".$string."</div>" : '';
51
+ }
52
+
53
+ /* General */
54
+ function add($string, $type, $static = false){
55
+ if( is_array($string) ){
56
+ $result = true;
57
+ foreach($string as $string_item){
58
+ if( $this->add($string_item, $type, $static) === false ){ $result = false; }
59
+ }
60
+ return $result;
61
+ }
62
+ if($string != ''){
63
+ if( isset($this->notices[$type]) ){
64
+ $notice_key = 0;
65
+ foreach( $this->notices[$type] as $notice_key => $notice ){
66
+ if($string == $notice['string']){
67
+ return $notice_key;
68
+ }
69
+ }
70
+ $i = $notice_key+1;
71
+ $this->notices[$type][$i]['string'] = $string;
72
+ if( $static ){
73
+ $this->notices[$type][$i]['static'] = true;
74
+ }
75
+ return $i;
76
+ }else{
77
+ return false;
78
+ }
79
+ }else{
80
+ return false;
81
+ }
82
+ }
83
+ function remove($key, $type){
84
+ if( isset($this->notices[$type]) ){
85
+ unset($this->notices[$type][$key]);
86
+ return true;
87
+ }else{
88
+ return false;
89
+ }
90
+ }
91
+ function remove_all(){
92
+ $this->notices = array('errors'=>array(), 'infos'=>array(), 'alerts'=>array(), 'confirms'=>array());
93
+ }
94
+ function get($type){
95
+ if( isset($this->notices[$type]) ){
96
+ $string = '';
97
+ foreach ($this->notices[$type] as $key => $error){
98
+ $class = substr($type, 0, (strlen($type)-1));
99
+ $string .= "<p>{$error['string']}</p>";
100
+ if( empty($error['static']) || $error['static'] !== true){
101
+ $this->remove($key, $type);
102
+ }
103
+ }
104
+ return $string;
105
+ }
106
+ return false;
107
+ }
108
+ function count($type){
109
+ if( isset($this->notices[$type]) ){
110
+ return count($this->notices[$type]);
111
+ }
112
+ return 0;
113
+ }
114
+
115
+ /* Errors */
116
+ function add_error($string, $static=false){
117
+ return $this->add($string, 'errors', $static);
118
+ }
119
+ function remove_error($key){
120
+ return $this->remove($key, 'errors');
121
+ }
122
+ function get_errors(){
123
+ return $this->get('errors');
124
+ }
125
+ function count_errors(){
126
+ return $this->count('errors');
127
+ }
128
+
129
+ /* Alerts */
130
+ function add_alert($string, $static=false){
131
+ return $this->add($string, 'alerts', $static);
132
+ }
133
+ function remove_alert($key){
134
+ return $this->remove($key, 'alerts');
135
+ }
136
+ function get_alerts(){
137
+ return $this->get('alerts');
138
+ }
139
+ function count_alerts(){
140
+ return $this->count('alerts');
141
+ }
142
+
143
+ /* Info */
144
+ function add_info($string, $static=false){
145
+ return $this->add($string, 'infos', $static);
146
+ }
147
+ function remove_info($key){
148
+ return $this->remove($key, 'infos');
149
+ }
150
+ function get_infos(){
151
+ return $this->get('infos');
152
+ }
153
+ function count_infos(){
154
+ return $this->count('infos');
155
+ }
156
+
157
+ /* Confirms */
158
+ function add_confirm($string, $static=false){
159
+ return $this->add($string, 'confirms', $static);
160
+ }
161
+ function remove_confirm($key){
162
+ return $this->remove($key, 'confirms');
163
+ }
164
+ function get_confirms(){
165
+ return $this->get('confirms');
166
+ }
167
+ function count_confirms(){
168
+ return $this->count('confirms');
169
+ }
170
+
171
+ //Iterator Implementation
172
+ function rewind(){
173
+ reset($this->bookings);
174
+ }
175
+ function current(){
176
+ $var = current($this->bookings);
177
+ return $var;
178
+ }
179
+ function key(){
180
+ $var = key($this->bookings);
181
+ return $var;
182
+ }
183
+ function next(){
184
+ $var = next($this->bookings);
185
+ return $var;
186
+ }
187
+ function valid(){
188
+ $key = key($this->bookings);
189
+ $var = ($key !== NULL && $key !== FALSE);
190
+ return $var;
191
+ }
192
+
193
+ }
194
+ global $EM_Notices;
195
+ $EM_Notices = new EM_Notices();
196
+ ?>
classes/em-object.php CHANGED
@@ -4,8 +4,11 @@
4
  *
5
  */
6
  class EM_Object {
7
-
8
  var $fields = array();
 
 
 
 
9
 
10
  /**
11
  * Takes the array and provides a clean array of search parameters, along with details
@@ -14,6 +17,7 @@ class EM_Object {
14
  * @return array
15
  */
16
  function get_default_search($defaults=array(), $array = array()){
 
17
  //TODO accept all objects as search options as well as ids (e.g. location vs. location_id, person vs. person_id)
18
  //Create minimal defaults array, merge it with supplied defaults array
19
  $super_defaults = array(
@@ -34,7 +38,9 @@ class EM_Object {
34
  'pagination'=>false,
35
  'array'=>false,
36
  'owner'=>false,
37
- 'rsvp'=>false
 
 
38
  );
39
  //Return default if nothing passed
40
  if( empty($defaults) && empty($array) ){
@@ -43,12 +49,12 @@ class EM_Object {
43
  //TODO decide on search defaults shared across all objects and then validate here
44
  $defaults = array_merge($super_defaults, $defaults);
45
 
46
- //We are still dealing with recurrence_id, location_id, category_id in some place, so we do a quick replace here just in case
47
- if( array_key_exists('recurrence_id', $array) && !array_key_exists('recurrence', $array) ) { $array['recurrence'] = $array['recurrence_id']; }
48
- if( array_key_exists('location_id', $array) && !array_key_exists('location', $array) ) { $array['location'] = $array['location_id']; }
49
- if( array_key_exists('category_id', $array) && !array_key_exists('category', $array) ) { $array['category'] = $array['category_id']; }
50
-
51
  if(is_array($array)){
 
 
 
 
 
52
  //Clean all id lists
53
  $array = self::clean_id_atts($array, array('location', 'event', 'category'));
54
 
@@ -65,7 +71,9 @@ class EM_Object {
65
  }
66
  //return clean array
67
  $defaults = array_merge ( $defaults, $array ); //No point using WP's cleaning function, we're doing it already.
 
68
  }
 
69
  //Do some spring cleaning for known values
70
  //Month & Year - may be array or single number
71
  $month_regex = '/^[0-9]{1,2}$/';
@@ -80,6 +88,17 @@ class EM_Object {
80
  }else{
81
  $defaults['year'] = preg_match($year_regex, $defaults['year']) ? $defaults['year']:'';
82
  }
 
 
 
 
 
 
 
 
 
 
 
83
  //Order - it's either ASC or DESC, so let's just validate
84
  if( !is_array($defaults['order']) && preg_match('/,/', $defaults['order']) ) {
85
  $defaults['order'] = explode(',', $defaults['order']);
@@ -97,7 +116,8 @@ class EM_Object {
97
  $defaults['offset'] = (is_numeric($defaults['offset'])) ? $defaults['offset']:$super_defaults['offset'];
98
  $defaults['recurring'] = ($defaults['recurring'] == true);
99
  $defaults['owner'] = (is_numeric($defaults['owner'])) ? $defaults['owner']:$super_defaults['owner'];
100
- //Calculate offset in event page is set
 
101
  if($defaults['page'] > 1){
102
  $defaults['offset'] = $defaults['limit'] * ($defaults['page']-1);
103
  }else{
@@ -113,8 +133,8 @@ class EM_Object {
113
  */
114
  function build_sql_conditions( $args = array() ){
115
  global $wpdb;
116
- $events_table = $wpdb->prefix . EM_EVENTS_TABLE;
117
- $locations_table = $wpdb->prefix . EM_LOCATIONS_TABLE;
118
 
119
  $args = apply_filters('em_object_build_sql_conditions_args',$args);
120
 
@@ -124,7 +144,8 @@ class EM_Object {
124
  $recurrence = $args['recurrence'];
125
  $category = $args['category'];
126
  $location = $args['location'];
127
- $rsvp = $args['rsvp'];
 
128
  $owner = $args['owner'];
129
  $event = $args['event'];
130
  $month = $args['month'];
@@ -148,7 +169,12 @@ class EM_Object {
148
  $date_month_start = $month[0];
149
  $date_month_end = $month[1];
150
  }else{
151
- $date_month_start = $date_month_end = $month;
 
 
 
 
 
152
  }
153
  //Sort out year range, if supplied an array of array(year,year), it'll check between these two years
154
  if( self::array_is_numeric($year) ){
@@ -159,25 +185,66 @@ class EM_Object {
159
  }
160
  $date_start = $date_year_start."-".$date_month_start."-01";
161
  $date_end = date('Y-m-t', mktime(0,0,0,$date_month_end,1,$date_year_end));
162
- $scope = $date_start.",".$date_end; //just modify the scope here
163
  }
164
  //No date requested, so let's look at scope
165
- if ( preg_match ( "/^[0-9]{4}-[0-9]{2}-[0-9]{2},[0-9]{4}-[0-9]{2}-[0-9]{2}$/", $scope ) ) {
166
  //This is an array, let's split it up
167
- $dates = explode(',', $scope);
168
- $date_start = $dates[0];
169
- $date_end = $dates[1];
170
  $conditions['scope'] = " ( ( event_start_date <= CAST('$date_end' AS DATE) AND event_end_date >= CAST('$date_start' AS DATE) ) OR (event_start_date BETWEEN CAST('$date_start' AS DATE) AND CAST('$date_end' AS DATE)) OR (event_end_date BETWEEN CAST('$date_start' AS DATE) AND CAST('$date_end' AS DATE)) )";
171
  } elseif ( preg_match ( "/^[0-9]{4}-[0-9]{2}-[0-9]{2}$/", $scope ) ) {
172
  //Scope can also be a specific date. However, if 'day', 'month', or 'year' are set, that will take precedence
173
  $conditions['scope'] = " ( event_start_date = CAST('$scope' AS DATE) OR ( event_start_date <= CAST('$scope' AS DATE) AND event_end_date >= CAST('$scope' AS DATE) ) )";
174
  } else {
175
  if ($scope == "past"){
176
- $conditions['scope'] = " event_start_date < '$today'";
 
 
 
 
177
  }elseif ($scope == "today"){
178
- $conditions['scope'] = " ( (event_start_date = CAST('$today' AS DATE)) OR (event_start_date <= CAST('$today' AS DATE) AND event_end_date >= CAST('$today' AS DATE)) )";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
179
  }elseif ($scope == "future"){
180
- $conditions['scope'] = " (event_start_date >= CAST('$today' AS DATE) OR (event_end_date >= CAST('$today' AS DATE) AND event_end_date != '0000-00-00' AND event_end_date IS NOT NULL))";
 
 
 
 
 
 
181
  }
182
  }
183
 
@@ -187,10 +254,10 @@ class EM_Object {
187
  }elseif ( self::array_is_numeric($location) ){
188
  $conditions['location'] = "( {$locations_table}.location_id = " . implode(" OR {$locations_table}.location_id = ", $location) .' )';
189
  }elseif ( is_object($location) && get_class($location)=='EM_Location' ){ //Now we deal with objects
190
- $conditions['location'] = " {$locations_table}.location_id = $location->id";
191
  }elseif ( is_array($location) && @get_class(current($location)=='EM_Location') ){ //we can accept array of ids or EM_Location objects
192
  foreach($location as $EM_Location){
193
- $location_ids[] = $EM_Location->id;
194
  }
195
  $conditions['location'] = "( {$locations_table}.location_id=". implode(" {$locations_table}.location_id=", $location_ids) ." )";
196
  }
@@ -201,30 +268,76 @@ class EM_Object {
201
  }elseif ( self::array_is_numeric($event) ){ //array of ids
202
  $conditions['event'] = "( {$events_table}.event_id = " . implode(" OR {$events_table}.event_id = ", $event) .' )';
203
  }elseif ( is_object($event) && get_class($event)=='EM_Event' ){ //Now we deal with objects
204
- $conditions['event'] = " {$events_table}.event_id = $event->id";
205
  }elseif ( is_array($event) && @get_class(current($event)=='EM_Event') ){ //we can accept array of ids or EM_event objects
206
  foreach($event as $EM_Event){
207
- $event_ids[] = $EM_Event->id;
208
  }
209
  $conditions['event'] = "( {$events_table}.event_id=". implode(" {$events_table}.event_id=", $event_ids) ." )";
210
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
211
 
212
  //Add conditions for category selection
213
  //Filter by category, can be id or comma seperated ids
214
  //TODO create an exclude category option
215
  if ( is_numeric($category) && $category > 0 ){
216
- $conditions['category'] = " event_category_id = $category";
 
 
 
 
 
 
 
 
217
  }elseif( self::array_is_numeric($category) ){
218
- $conditions['category'] = "( event_category_id = ". implode(' OR event_category_id = ', $category).")";
 
 
 
 
 
 
 
 
 
 
 
 
 
219
  }
220
 
221
  //If we want rsvped items, we usually check the event
222
- if( $rsvp == 1 ){
223
- $conditions['rsvp'] = 'event_rsvp=1';
224
  }
225
  //Default ownership belongs to an event, child objects can just overwrite this if needed.
226
  if( is_numeric($owner) ){
227
- $conditions['owner'] = 'event_author='.$owner;
228
  }
229
  return apply_filters('em_object_build_sql_conditions', $conditions);
230
  }
@@ -266,7 +379,60 @@ class EM_Object {
266
  }
267
  return apply_filters('em_object_build_sql_orderby', $orderby);
268
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
269
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
270
  /**
271
  * Save an array into this class.
272
  * If you provide a record from the database table corresponding to this class type it will add the data to this object.
@@ -277,25 +443,42 @@ class EM_Object {
277
  //Save core data
278
  if( is_array($array) ){
279
  $array = apply_filters('em_to_object', $array);
280
- foreach ( $this->fields as $key => $val ) {
281
  if(array_key_exists($key, $array)){
282
  if( !is_object($array[$key]) && !is_array($array[$key]) ){
283
  $array[$key] = ($addslashes) ? stripslashes($array[$key]):$array[$key];
 
 
284
  }
285
- $this->$val['name'] = $array[$key];
286
  }
287
  }
288
  }
289
  }
 
 
 
 
 
 
 
 
 
290
 
291
  /**
292
  * Returns this object in the form of an array, useful for saving directly into a database table.
293
  * @return array
294
  */
295
- function to_array(){
296
  $array = array();
297
  foreach ( $this->fields as $key => $val ) {
298
- $array[$key] = $this->$val['name'];
 
 
 
 
 
 
299
  }
300
  return apply_filters('em_to_array', $array);
301
  }
@@ -327,9 +510,9 @@ class EM_Object {
327
  $return = array();
328
  foreach($this->fields as $fieldName => $fieldArray){
329
  if($inverted_array){
330
- $return[$fieldArray['name']] = $fieldName;
331
  }else{
332
- $return[$fieldName] = $fieldArray['name'];
333
  }
334
  }
335
  return apply_filters('em_object_get_fields', $return, $this, $inverted_array);
@@ -370,7 +553,7 @@ class EM_Object {
370
  $array[$key] = (int) $string;
371
  }elseif( self::array_is_numeric($string) ){
372
  $array[$key] = $string;
373
- }elseif( preg_match('/^([0-9],?)+$/', $string) ){
374
  $array[$key] = explode(',', $string);
375
  }else{
376
  //No format we accept
@@ -392,8 +575,12 @@ class EM_Object {
392
  function email_send($subject, $body, $email){
393
  global $EM_Mailer;
394
  if( !$EM_Mailer->send($subject,$body,$email) ){
395
- foreach($EM_Mailer->errors as $error){
396
- $this->errors[] = $error;
 
 
 
 
397
  }
398
  return false;
399
  }
@@ -413,6 +600,31 @@ class EM_Object {
413
  }
414
  }
415
  return (!in_array(false, $results) && count($results) > 0);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
416
  }
417
 
418
  /**
@@ -426,11 +638,11 @@ class EM_Object {
426
  }else{
427
  $return = self::array_to_json($array);
428
  }
429
- if( isset($_GET['callback']) ){
430
- $return = $_GET['callback']."($return)";
431
  }
432
  return apply_filters('em_object_json_encode', $return, $array);
433
- }
434
 
435
  /**
436
  * Compatible json encoder function for PHP4
@@ -483,4 +695,152 @@ class EM_Object {
483
  }
484
  return $result;
485
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
486
  }
4
  *
5
  */
6
  class EM_Object {
 
7
  var $fields = array();
8
+ var $required_fields = array();
9
+ var $feedback_message = "";
10
+ var $errors = array();
11
+ var $mime_types = array(1 => 'gif', 2 => 'jpg', 3 => 'png');
12
 
13
  /**
14
  * Takes the array and provides a clean array of search parameters, along with details
17
  * @return array
18
  */
19
  function get_default_search($defaults=array(), $array = array()){
20
+ global $wpdb;
21
  //TODO accept all objects as search options as well as ids (e.g. location vs. location_id, person vs. person_id)
22
  //Create minimal defaults array, merge it with supplied defaults array
23
  $super_defaults = array(
38
  'pagination'=>false,
39
  'array'=>false,
40
  'owner'=>false,
41
+ 'rsvp'=>false, //depreciated for bookings
42
+ 'bookings'=>false,
43
+ 'search'=>false
44
  );
45
  //Return default if nothing passed
46
  if( empty($defaults) && empty($array) ){
49
  //TODO decide on search defaults shared across all objects and then validate here
50
  $defaults = array_merge($super_defaults, $defaults);
51
 
 
 
 
 
 
52
  if(is_array($array)){
53
+ //We are still dealing with recurrence_id, location_id, category_id in some place, so we do a quick replace here just in case
54
+ if( array_key_exists('recurrence_id', $array) && !array_key_exists('recurrence', $array) ) { $array['recurrence'] = $array['recurrence_id']; }
55
+ if( array_key_exists('location_id', $array) && !array_key_exists('location', $array) ) { $array['location'] = $array['location_id']; }
56
+ if( array_key_exists('category_id', $array) && !array_key_exists('category', $array) ) { $array['category'] = $array['category_id']; }
57
+
58
  //Clean all id lists
59
  $array = self::clean_id_atts($array, array('location', 'event', 'category'));
60
 
71
  }
72
  //return clean array
73
  $defaults = array_merge ( $defaults, $array ); //No point using WP's cleaning function, we're doing it already.
74
+
75
  }
76
+
77
  //Do some spring cleaning for known values
78
  //Month & Year - may be array or single number
79
  $month_regex = '/^[0-9]{1,2}$/';
88
  }else{
89
  $defaults['year'] = preg_match($year_regex, $defaults['year']) ? $defaults['year']:'';
90
  }
91
+ //Deal with scope and date searches
92
+ if ( !is_array($defaults['scope']) && preg_match ( "/^[0-9]{4}-[0-9]{2}-[0-9]{2},[0-9]{4}-[0-9]{2}-[0-9]{2}$/", $defaults['scope'] ) ) {
93
+ //This is to become an array, so let's split it up
94
+ $defaults['scope'] = explode(',', $defaults['scope']);
95
+ }
96
+ if( is_array($defaults['scope']) ){
97
+ //looking for a date range here, so we'll verify the dates validate, if not get the default.
98
+ if ( !preg_match("/^[0-9]{4}-[0-9]{2}-[0-9]{2}$/", $defaults['scope'][0]) || !preg_match("/^[0-9]{4}-[0-9]{2}-[0-9]{2}$/", $defaults['scope'][1]) ) {
99
+ $defaults['scope'] = $super_defaults['scope'];
100
+ }
101
+ }
102
  //Order - it's either ASC or DESC, so let's just validate
103
  if( !is_array($defaults['order']) && preg_match('/,/', $defaults['order']) ) {
104
  $defaults['order'] = explode(',', $defaults['order']);
116
  $defaults['offset'] = (is_numeric($defaults['offset'])) ? $defaults['offset']:$super_defaults['offset'];
117
  $defaults['recurring'] = ($defaults['recurring'] == true);
118
  $defaults['owner'] = (is_numeric($defaults['owner'])) ? $defaults['owner']:$super_defaults['owner'];
119
+ $defaults['search'] = ($defaults['search']) ? trim($wpdb->escape(like_escape($defaults['search']))):false;
120
+ //Calculate offset if event page is set
121
  if($defaults['page'] > 1){
122
  $defaults['offset'] = $defaults['limit'] * ($defaults['page']-1);
123
  }else{
133
  */
134
  function build_sql_conditions( $args = array() ){
135
  global $wpdb;
136
+ $events_table = EM_EVENTS_TABLE;
137
+ $locations_table = EM_LOCATIONS_TABLE;
138
 
139
  $args = apply_filters('em_object_build_sql_conditions_args',$args);
140
 
144
  $recurrence = $args['recurrence'];
145
  $category = $args['category'];
146
  $location = $args['location'];
147
+ $bookings = $args['rsvp'];
148
+ $bookings = !empty($args['bookings']) ? $args['bookings']:$bookings;
149
  $owner = $args['owner'];
150
  $event = $args['event'];
151
  $month = $args['month'];
169
  $date_month_start = $month[0];
170
  $date_month_end = $month[1];
171
  }else{
172
+ if( !empty($month) ){
173
+ $date_month_start = $date_month_end = $month;
174
+ }else{
175
+ $date_month_start = 1;
176
+ $date_month_end = 12;
177
+ }
178
  }
179
  //Sort out year range, if supplied an array of array(year,year), it'll check between these two years
180
  if( self::array_is_numeric($year) ){
185
  }
186
  $date_start = $date_year_start."-".$date_month_start."-01";
187
  $date_end = date('Y-m-t', mktime(0,0,0,$date_month_end,1,$date_year_end));
188
+ $scope = array($date_start,$date_end); //just modify the scope here
189
  }
190
  //No date requested, so let's look at scope
191
+ if ( is_array($scope) ) {
192
  //This is an array, let's split it up
193
+ $date_start = $scope[0];
194
+ $date_end = $scope[1];
 
195
  $conditions['scope'] = " ( ( event_start_date <= CAST('$date_end' AS DATE) AND event_end_date >= CAST('$date_start' AS DATE) ) OR (event_start_date BETWEEN CAST('$date_start' AS DATE) AND CAST('$date_end' AS DATE)) OR (event_end_date BETWEEN CAST('$date_start' AS DATE) AND CAST('$date_end' AS DATE)) )";
196
  } elseif ( preg_match ( "/^[0-9]{4}-[0-9]{2}-[0-9]{2}$/", $scope ) ) {
197
  //Scope can also be a specific date. However, if 'day', 'month', or 'year' are set, that will take precedence
198
  $conditions['scope'] = " ( event_start_date = CAST('$scope' AS DATE) OR ( event_start_date <= CAST('$scope' AS DATE) AND event_end_date >= CAST('$scope' AS DATE) ) )";
199
  } else {
200
  if ($scope == "past"){
201
+ if( get_option('dbem_events_current_are_past') ){
202
+ $conditions['scope'] = " event_start_date < '$today'";
203
+ }else{
204
+ $conditions['scope'] = " event_end_date < '$today'";
205
+ }
206
  }elseif ($scope == "today"){
207
+ $conditions['scope'] = " (event_start_date = CAST('$today' AS DATE))";
208
+ if( !get_option('dbem_events_current_are_past') ){
209
+ $conditions['scope'] .= " OR (event_start_date <= CAST('$today' AS DATE) AND event_end_date >= CAST('$today' AS DATE))";
210
+ }
211
+ }elseif ($scope == "tomorrow"){
212
+ $tomorrow = date('Y-m-d',current_time('timestamp')+60*60*24);
213
+ $conditions['scope'] = "(event_start_date = CAST('$tomorrow' AS DATE))";
214
+ if( !get_option('dbem_events_current_are_past') ){
215
+ $conditions['scope'] .= " OR (event_start_date <= CAST('$tomorrow' AS DATE) AND event_end_date >= CAST('$tomorrow' AS DATE))";
216
+ }
217
+ }elseif ($scope == "month"){
218
+ $start_month = date('Y-m-d',current_time('timestamp'));
219
+ $end_month = date('Y-m-t',current_time('timestamp'));
220
+ $conditions['scope'] = " (event_start_date BETWEEN CAST('$start_month' AS DATE) AND CAST('$end_month' AS DATE))";
221
+ if( !get_option('dbem_events_current_are_past') ){
222
+ $conditions['scope'] .= " OR (event_start_date < CAST('$start_month' AS DATE) AND event_end_date >= CAST('$start_month' AS DATE))";
223
+ }
224
+ }elseif ($scope == "next-month"){
225
+ $start_month_timestamp = strtotime('+1 month', current_time('timestamp')); //get the end of this month + 1 day
226
+ $start_month = date('Y-m-1',$start_month_timestamp);
227
+ $end_month = date('Y-m-t',$start_month_timestamp);
228
+ $conditions['scope'] = " (event_start_date BETWEEN CAST('$start_month' AS DATE) AND CAST('$end_month' AS DATE))";
229
+ if( !get_option('dbem_events_current_are_past') ){
230
+ $conditions['scope'] .= " OR (event_start_date < CAST('$start_month' AS DATE) AND event_end_date >= CAST('$start_month' AS DATE))";
231
+ }
232
+ }elseif( preg_match('/(\d\d?)\-months/',$scope,$matches) ){ // next x months means this month (what's left of it), plus the following x months until the end of that month.
233
+ $months_to_add = $matches[1];
234
+ $start_month = date('Y-m-d',current_time('timestamp'));
235
+ $end_month = date('Y-m-t',strtotime("+$months_to_add month", current_time('timestamp')));
236
+ $conditions['scope'] = " (event_start_date BETWEEN CAST('$start_month' AS DATE) AND CAST('$end_month' AS DATE))";
237
+ if( !get_option('dbem_events_current_are_past') ){
238
+ $conditions['scope'] .= " OR (event_start_date < CAST('$start_month' AS DATE) AND event_end_date >= CAST('$start_month' AS DATE))";
239
+ }
240
  }elseif ($scope == "future"){
241
+ $conditions['scope'] = " event_start_date >= CAST('$today' AS DATE)";
242
+ if( !get_option('dbem_events_current_are_past') ){
243
+ $conditions['scope'] .= " OR (event_end_date >= CAST('$today' AS DATE) AND event_end_date != '0000-00-00' AND event_end_date IS NOT NULL)";
244
+ }
245
+ }
246
+ if( !empty($conditions['scope']) ){
247
+ $conditions['scope'] = '('.$conditions['scope'].')';
248
  }
249
  }
250
 
254
  }elseif ( self::array_is_numeric($location) ){
255
  $conditions['location'] = "( {$locations_table}.location_id = " . implode(" OR {$locations_table}.location_id = ", $location) .' )';
256
  }elseif ( is_object($location) && get_class($location)=='EM_Location' ){ //Now we deal with objects
257
+ $conditions['location'] = " {$locations_table}.location_id = $location->location_id";
258
  }elseif ( is_array($location) && @get_class(current($location)=='EM_Location') ){ //we can accept array of ids or EM_Location objects
259
  foreach($location as $EM_Location){
260
+ $location_ids[] = $EM_Location->location_id;
261
  }
262
  $conditions['location'] = "( {$locations_table}.location_id=". implode(" {$locations_table}.location_id=", $location_ids) ." )";
263
  }
268
  }elseif ( self::array_is_numeric($event) ){ //array of ids
269
  $conditions['event'] = "( {$events_table}.event_id = " . implode(" OR {$events_table}.event_id = ", $event) .' )';
270
  }elseif ( is_object($event) && get_class($event)=='EM_Event' ){ //Now we deal with objects
271
+ $conditions['event'] = " {$events_table}.event_id = $event->event_id";
272
  }elseif ( is_array($event) && @get_class(current($event)=='EM_Event') ){ //we can accept array of ids or EM_event objects
273
  foreach($event as $EM_Event){
274
+ $event_ids[] = $EM_Event->event_id;
275
  }
276
  $conditions['event'] = "( {$events_table}.event_id=". implode(" {$events_table}.event_id=", $event_ids) ." )";
277
  }
278
+ //Location specific filters
279
+ //country lookup
280
+ if( !empty($args['country']) ){
281
+ $countries = em_get_countries();
282
+ //we can accept country codes or names
283
+ if( in_array($args['country'], $countries) ){
284
+ //we have a country name,
285
+ $conditions['country'] = "location_country='".array_search($args['country'])."'";
286
+ }elseif( array_key_exists($args['country'], $countries) ){
287
+ //we have a country code
288
+ $conditions['country'] = "location_country='".$args['country']."'";
289
+ }
290
+ }
291
+ //state lookup
292
+ if( !empty($args['state']) ){
293
+ $conditions['state'] = $wpdb->prepare('location_state=%s', $args['state']);
294
+ }
295
+ //state lookup
296
+ if( !empty($args['town']) ){
297
+ $conditions['town'] = $wpdb->prepare('location_town=%s', $args['town']);
298
+ }
299
+ //region lookup
300
+ if( !empty($args['region']) ){
301
+ $conditions['region'] = $wpdb->prepare('location_region=%s', $args['region']);
302
+ }
303
 
304
  //Add conditions for category selection
305
  //Filter by category, can be id or comma seperated ids
306
  //TODO create an exclude category option
307
  if ( is_numeric($category) && $category > 0 ){
308
+ //get the term id directly
309
+ $term = new EM_Category($category);
310
+ if( $term !== false && !is_wp_error($term) ){
311
+ if( EM_MS_GLOBAL ){
312
+ $conditions['category'] = " ".EM_EVENTS_TABLE.".event_id IN ( SELECT object_id FROM ".EM_META_TABLE." WHERE meta_value={$term->term_id} AND meta_key='event-category' ) ";
313
+ }else{
314
+ $conditions['category'] = " ".EM_EVENTS_TABLE.".post_id IN ( SELECT object_id FROM ".$wpdb->term_relationships." WHERE term_taxonomy_id={$term->term_taxonomy_id} ) ";
315
+ }
316
+ }
317
  }elseif( self::array_is_numeric($category) ){
318
+ $term_ids = array();
319
+ foreach($category as $category_id){
320
+ $term = new EM_Category($category_id);
321
+ if( $term !== false && !is_wp_error($term) ){
322
+ $term_ids[] = $term->term_taxonomy_id;
323
+ }
324
+ }
325
+ if( count($term_ids) > 0 ){
326
+ if( EM_MS_GLOBAL ){
327
+ $conditions['category'] = " ".EM_EVENTS_TABLE.".event_id IN ( SELECT object_id FROM ".EM_META_TABLE." WHERE meta_value IN (".implode(',',$term_ids).") AND meta_name='event-category ) ";
328
+ }else{
329
+ $conditions['category'] = " ".EM_EVENTS_TABLE.".post_id IN ( SELECT object_id FROM ".$wpdb->term_relationships." WHERE term_taxonomy_id IN (".implode(',',$term_ids).") ) ";
330
+ }
331
+ }
332
  }
333
 
334
  //If we want rsvped items, we usually check the event
335
+ if( $bookings == 1 ){
336
+ $conditions['bookings'] = 'event_rsvp=1';
337
  }
338
  //Default ownership belongs to an event, child objects can just overwrite this if needed.
339
  if( is_numeric($owner) ){
340
+ $conditions['owner'] = 'event_owner='.$owner;
341
  }
342
  return apply_filters('em_object_build_sql_conditions', $conditions);
343
  }
379
  }
380
  return apply_filters('em_object_build_sql_orderby', $orderby);
381
  }
382
+
383
+ /**
384
+ * Used by "single" objects, e.g. bookings, events, locations to verify if they have the capability to edit this or someone else's object. Relies on the fact that the object has an owner property with id of user (or admin capability must pass).
385
+ * @param string $owner_capability If the object has an owner property and the user id matches that, this capability will be checked for.
386
+ * @param string $admin_capability If the user isn't the owner of the object, this capability will be checked for.
387
+ * @return boolean
388
+ */
389
+ function can_manage( $owner_capability = false, $admin_capability = false, $user_to_check = false ){
390
+ global $em_capabilities_array;
391
+ if( $user_to_check ){
392
+ $user = new WP_User($user_to_check);
393
+ if( empty($user->ID) ) $user = false;
394
+ }
395
+ //if multisite and supoer admin, just return true
396
+ if( is_multisite() && is_super_admin() ){ return true; }
397
+ //do they own this?
398
+ $is_owner = ( $this->owner == get_current_user_id() || empty($this->id) || (!empty($user) && $this->owner == $user->ID) );
399
+ //now check capability
400
+ $can_manage = false;
401
+ if( $is_owner && (current_user_can($owner_capability) || (!empty($user) && $user->has_cap($owner_capability))) ){
402
+ //user owns the object and can therefore manage it
403
+ $can_manage = true;
404
+ }elseif( array_key_exists($owner_capability, $em_capabilities_array) ){
405
+ //currently user is not able to manage as they aren't the owner
406
+ $error_msg = $em_capabilities_array[$owner_capability];
407
+ }
408
+ //admins have special rights
409
+ if( current_user_can($admin_capability) || (!empty($user) && $user->has_cap($admin_capability)) ){
410
+ $can_manage = true;
411
+ }elseif( array_key_exists($admin_capability, $em_capabilities_array) ){
412
+ $error_msg = $em_capabilities_array[$admin_capability];
413
+ }
414
+
415
+ if( !$can_manage && !$is_owner && !empty($error_msg) ){
416
+ $this->add_error($error_msg);
417
+ }
418
+ return $can_manage;
419
+ }
420
 
421
+
422
+ function ms_global_switch(){
423
+ if( EM_MS_GLOBAL && !is_main_site() ){
424
+ //If in multisite global, then get the main blog categories
425
+ global $current_site;
426
+ switch_to_blog($current_site->blog_id);
427
+ }
428
+ }
429
+
430
+ function ms_global_switch_back(){
431
+ if( EM_MS_GLOBAL && !is_main_site() ){
432
+ restore_current_blog();
433
+ }
434
+ }
435
+
436
  /**
437
  * Save an array into this class.
438
  * If you provide a record from the database table corresponding to this class type it will add the data to this object.
443
  //Save core data
444
  if( is_array($array) ){
445
  $array = apply_filters('em_to_object', $array);
446
+ foreach ( array_keys($this->fields) as $key ) {
447
  if(array_key_exists($key, $array)){
448
  if( !is_object($array[$key]) && !is_array($array[$key]) ){
449
  $array[$key] = ($addslashes) ? stripslashes($array[$key]):$array[$key];
450
+ }elseif( is_array($array[$key]) ){
451
+ $array[$key] = ($addslashes) ? stripslashes_deep($array[$key]):$array[$key];
452
  }
453
+ $this->$key = $array[$key];
454
  }
455
  }
456
  }
457
  }
458
+
459
+ /**
460
+ * Copies all the properties to shorter property names for compatability, do not use the old properties.
461
+ */
462
+ function compat_keys(){
463
+ foreach($this->fields as $key => $fieldinfo){
464
+ $this->$fieldinfo['name'] = $this->$key;
465
+ }
466
+ }
467
 
468
  /**
469
  * Returns this object in the form of an array, useful for saving directly into a database table.
470
  * @return array
471
  */
472
+ function to_array($db = false){
473
  $array = array();
474
  foreach ( $this->fields as $key => $val ) {
475
+ if($db){
476
+ if( !empty($this->$key) || $this->$key === 0 || empty($val['null']) ){
477
+ $array[$key] = $this->$key;
478
+ }
479
+ }else{
480
+ $array[$key] = $this->$key;
481
+ }
482
  }
483
  return apply_filters('em_to_array', $array);
484
  }
510
  $return = array();
511
  foreach($this->fields as $fieldName => $fieldArray){
512
  if($inverted_array){
513
+ $return[$fieldName] = $fieldName;
514
  }else{
515
+ $return[$fieldName] = $fieldName;
516
  }
517
  }
518
  return apply_filters('em_object_get_fields', $return, $this, $inverted_array);
553
  $array[$key] = (int) $string;
554
  }elseif( self::array_is_numeric($string) ){
555
  $array[$key] = $string;
556
+ }elseif( !is_array($string) && preg_match('/^([0-9],?)+$/', $string) ){
557
  $array[$key] = explode(',', $string);
558
  }else{
559
  //No format we accept
575
  function email_send($subject, $body, $email){
576
  global $EM_Mailer;
577
  if( !$EM_Mailer->send($subject,$body,$email) ){
578
+ if( is_array($EM_Mailer->errors) ){
579
+ foreach($EM_Mailer->errors as $error){
580
+ $this->errors[] = $error;
581
+ }
582
+ }else{
583
+ $this->errors[] = $EM_Mailer->errors;
584
  }
585
  return false;
586
  }
600
  }
601
  }
602
  return (!in_array(false, $results) && count($results) > 0);
603
+ }
604
+
605
+ /**
606
+ * Returns an array of errors in this object
607
+ * @return array
608
+ */
609
+ function get_errors(){
610
+ if(is_array($this->errors)){
611
+ return $this->errors;
612
+ }else{
613
+ return array();
614
+ }
615
+ }
616
+
617
+ /**
618
+ * Adds an error to the object
619
+ */
620
+ function add_error($errors){
621
+ if(!is_array($errors)){ $errors = array($errors); } //make errors var an array if it isn't already
622
+ if(!is_array($this->errors)){ $this->errors = array(); } //create empty array if this isn't an array
623
+ foreach($errors as $error){
624
+ if( !in_array($error, $this->errors) ){
625
+ $this->errors[] = $error;
626
+ }
627
+ }
628
  }
629
 
630
  /**
638
  }else{
639
  $return = self::array_to_json($array);
640
  }
641
+ if( isset($_REQUEST['callback']) ){
642
+ $return = $_REQUEST['callback']."($return)";
643
  }
644
  return apply_filters('em_object_json_encode', $return, $array);
645
+ }
646
 
647
  /**
648
  * Compatible json encoder function for PHP4
695
  }
696
  return $result;
697
  }
698
+
699
+ /*
700
+ * START IMAGE UPlOAD FUNCTIONS
701
+ * Used for various objects, so shared in one place
702
+ */
703
+ /**
704
+ * Returns the type of image in lowercase, if $path is true, a base filename is returned which indicates where to store the file from the root upload folder.
705
+ * @param unknown_type $path
706
+ * @return mixed|mixed
707
+ */
708
+ function get_image_type($path = false){
709
+ $type = false;
710
+ switch( get_class($this) ){
711
+ case 'EM_Event':
712
+ $dir = (EM_IMAGE_DS == '/') ? 'events/':'';
713
+ $type = 'event';
714
+ break;
715
+ case 'EM_Location':
716
+ $dir = (EM_IMAGE_DS == '/') ? 'locations/':'';
717
+ $type = 'location';
718
+ break;
719
+ case 'EM_Category':
720
+ $dir = (EM_IMAGE_DS == '/') ? 'categories/':'';
721
+ $type = 'category';
722
+ break;
723
+ }
724
+ if($path){
725
+ return apply_filters('em_object_get_image_type',$dir.$type, $path, $this);
726
+ }
727
+ return apply_filters('em_object_get_image_type',$type, $path, $this);
728
+ }
729
+
730
+ function get_image_url($size = 'full'){
731
+ $image_url = $this->image_url;
732
+ if( !empty($this->post_id) && (empty($this->image_url) || $size != 'full') ){
733
+ $post_thumbnail_id = get_post_thumbnail_id( $this->post_id );
734
+ $src = wp_get_attachment_image_src($post_thumbnail_id, $size);
735
+ if( !empty($src[0]) && $size == 'full' ){
736
+ $image_url = $this->image_url = $src[0];
737
+ }elseif(!empty($src[0])){
738
+ $image_url = $src[0];
739
+ }
740
+ //legacy image finder, annoying, but must be done
741
+ if( empty($image_url) ){
742
+ $type = $this->get_image_type();
743
+ $id = ( get_class($this) == "EM_Event" && $this->is_recurrence() ) ? $this->recurrence_id:$this->event_id; //quick fix for recurrences
744
+ if( $type ){
745
+ foreach($this->mime_types as $mime_type) {
746
+ $file_name = $this->get_image_type(true)."-{$id}.$mime_type";
747
+ if( file_exists( EM_IMAGE_UPLOAD_DIR . $file_name) ) {
748
+ $image_url = $this->image_url = EM_IMAGE_UPLOAD_URI.$file_name;
749
+ }
750
+ }
751
+ }
752
+ }
753
+ }
754
+ return apply_filters('em_object_get_image_url', $image_url, $this);
755
+ }
756
+
757
+ function image_delete($force_delete) {
758
+ $type = $this->get_image_type();
759
+ if( $type ){
760
+ if( $this->get_image_url() == '' ){
761
+ $result = true;
762
+ }else{
763
+ $post_thumbnail_id = get_post_thumbnail_id( $this->post_id );
764
+ $delete_attachment = wp_delete_attachment($post_thumbnail_id, $force_delete);
765
+ if( $delete_attachment !== false ){
766
+ //check legacy image
767
+ $type_id_name = $type.'_id';
768
+ $file_name= EM_IMAGE_UPLOAD_DIR.$this->get_image_type(true)."-".$this->$type_id_name;
769
+ $result = false;
770
+ foreach($this->mime_types as $mime_type) {
771
+ if (file_exists($file_name.".".$mime_type)){
772
+ $result = unlink($file_name.".".$mime_type);
773
+ $this->image_url = '';
774
+ }
775
+ }
776
+ }
777
+ }
778
+ }
779
+ return apply_filters('em_object_get_image_url', $result, $this);
780
+ }
781
+
782
+ function image_upload(){
783
+ $type = $this->get_image_type();
784
+ //Handle the attachment as a WP Post
785
+ $attachment = '';
786
+ if ( !empty($_FILES[$type.'_image']['size']) && file_exists($_FILES[$type.'_image']['tmp_name']) && $this->image_validate() ) {
787
+ require_once(ABSPATH . "wp-admin" . '/includes/file.php');
788
+ require_once(ABSPATH . "wp-admin" . '/includes/image.php');
789
+
790
+ $attachment = wp_handle_upload($_FILES[$type.'_image'], array('test_form'=>false), current_time('mysql'));
791
+
792
+ if ( isset($attachment['error']) ){
793
+ $this->add_error('Image Error: ' . $attachment['error'] );
794
+ }
795
+
796
+ /* Attach file to ticket */
797
+ if ( count($this->errors) == 0 && $attachment ){
798
+ $attachment_data = array(
799
+ 'post_mime_type' => $attachment['type'],
800
+ 'post_title' => $this->post_title,
801
+ 'post_content' => '',
802
+ 'post_status' => 'inherit'
803
+ );
804
+ $attachment_id = wp_insert_attachment( $attachment_data, $attachment['file'], $this->post_id );
805
+ $attachment_metadata = wp_generate_attachment_metadata( $attachment_id, $attachment['file'] );
806
+ wp_update_attachment_metadata( $attachment_id, $attachment_metadata );
807
+ //delete the old attachment
808
+ $this->image_delete();
809
+ update_post_meta($this->post_id, '_thumbnail_id', $attachment_id);
810
+ return apply_filters('em_object_image_upload', true, $this);
811
+ }else{
812
+ return apply_filters('em_object_image_upload', false, $this);
813
+ }
814
+ }elseif( !empty($_REQUEST[$type.'_image_delete']) ){
815
+ $this->image_delete();
816
+ }
817
+ return apply_filters('em_object_image_upload', false, $this);
818
+ }
819
+
820
+ function image_validate(){
821
+ $type = $this->get_image_type();
822
+ if( $type ){
823
+ if ( !empty($_FILES[$type.'_image']) && $_FILES[$type.'_image']['size'] > 0 ) {
824
+ if (is_uploaded_file($_FILES[$type.'_image']['tmp_name'])) {
825
+ list($width, $height, $mime_type, $attr) = getimagesize($_FILES[$type.'_image']['tmp_name']);
826
+ $maximum_size = get_option('dbem_image_max_size');
827
+ if ($_FILES[$type.'_image']['size'] > $maximum_size){
828
+ $this->add_error( __('The image file is too big! Maximum size:', 'dbem')." $maximum_size");
829
+ }
830
+ $maximum_width = get_option('dbem_image_max_width');
831
+ $maximum_height = get_option('dbem_image_max_height');
832
+ if (($width > $maximum_width) || ($height > $maximum_height)) {
833
+ $this->add_error( __('The image is too big! Maximum size allowed:','dbem')." $maximum_width x $maximum_height");
834
+ }
835
+ if ( empty($mime_type) || !array_key_exists($mime_type, $this->mime_types) ){
836
+ $this->add_error(__('The image is in a wrong format!','dbem'));
837
+ }
838
+ }
839
+ }
840
+ }
841
+ return apply_filters('em_object_image_validate', count($this->errors) == 0, $this);
842
+ }
843
+ /*
844
+ * END IMAGE UPlOAD FUNCTIONS
845
+ */
846
  }
classes/em-people.php CHANGED
@@ -2,128 +2,33 @@
2
  class EM_People extends EM_Object {
3
 
4
  /**
5
- * Gets all users, if $return_people false an array associative arrays will be returned. If $return_people is true this will return an array of EM_Person objects
6
- * @param $return_people
7
- * @return array
8
  */
9
- function get( $return_people = true ) {
10
- global $wpdb;
11
- $sql = "SELECT * FROM ". $wpdb->prefix.EM_PEOPLE_TABLE ;
12
- $result = $wpdb->get_results($sql, ARRAY_A);
13
- if( $return_people ){
14
- //Return people as EM_Person objects
15
- $people = array();
16
- foreach ($result as $person){
17
- $people[] = new EM_Person($person);
18
- }
19
- return $people;
20
- }
21
- return $result;
22
- }
23
-
24
- function get_new( $args = array() ) {
25
  global $wpdb;
26
- $people_table = $wpdb->prefix.EM_PEOPLE_TABLE;
27
- $bookings_table = $wpdb->prefix.EM_BOOKINGS_TABLE;
28
-
29
- //Quick version, we can accept an array of IDs, which is easy to retrieve
30
- if( self::array_is_numeric($args) ){ //Array of numbers, assume they are event IDs to retreive
31
- //We can just get all the events here and return them
32
- $sql = "SELECT * FROM $people_table WHERE person_id=".implode(" OR person_id=", $args);
33
- $results = $wpdb->get_results(apply_filters('em_people_get_sql',$sql),ARRAY_A);
34
- $people = array();
35
- foreach($results as $result){
36
- $people[$result['person_id']] = new EM_Person($result);
37
  }
38
- return $people; //We return all the people matched as an EM_Event array.
39
  }
40
-
41
- //We assume it's either an empty array or array of search arguments to merge with defaults
42
- $args = self::get_default_search($args);
43
- $limit = ( $args['limit'] && is_numeric($args['limit'])) ? "LIMIT {$args['limit']}" : '';
44
- $offset = ( $limit != "" && is_numeric($args['offset']) ) ? "OFFSET {$args['offset']}" : '';
45
-
46
- //Get the default conditions
47
- $conditions = self::build_sql_conditions($args);
48
- //Put it all together
49
- $where = ( count($conditions) > 0 ) ? " WHERE " . implode ( " AND ", $conditions ):'';
50
-
51
- //Get ordering instructions
52
- $EM_Person = new EM_Person();
53
- $accepted_fields = $EM_Person->get_fields(true);
54
- $orderby = self::build_sql_orderby($args, $accepted_fields, get_option('dbem_people_default_order'));
55
- //Now, build orderby sql
56
- $orderby_sql = ( count($orderby) > 0 ) ? 'ORDER BY '. implode(', ', $orderby) : '';
57
-
58
- //Create the SQL statement and execute
59
- $sql = "
60
- SELECT * FROM $people_table
61
- LEFT JOIN $bookings_table ON {$bookings_table}.person_id={$people_table}.person_id
62
- $where
63
- GROUP BY person_id
64
- $orderby_sql
65
- $limit $offset
66
- ";
67
- $results = $wpdb->get_results( apply_filters('em_people_get_sql',$sql, $args), ARRAY_A);
68
- //If we want results directly in an array, why not have a shortcut here?
69
- if( $args['array'] == true ){
70
- return $results;
71
- }
72
-
73
- //Make returned results EM_Event objects
74
- $results = (is_array($results)) ? $results:array();
75
- $people = array();
76
- foreach ( $results as $person_array ){
77
- $people[$person_array['person_id']] = new EM_Person($person_array);
78
- }
79
-
80
- return apply_filters('em_people_get', $people);
81
- }
82
-
83
- /* Overrides EM_Object method to apply a filter to result
84
- * @see wp-content/plugins/events-manager/classes/EM_Object#build_sql_conditions()
85
- */
86
- function build_sql_conditions( $args = array() ){
87
- global $wpdb;
88
- //FIXME EM_People doesn't build sql conditions in EM_Object
89
- $conditions = array();
90
-
91
- return apply_filters( 'em_people_build_sql_conditions', $conditions, $args );
92
- }
93
-
94
- /* Overrides EM_Object method to apply a filter to result
95
- * @see wp-content/plugins/people-manager/classes/EM_Object#build_sql_orderby()
96
- */
97
- function build_sql_orderby( $args, $accepted_fields, $default_order = 'ASC' ){
98
- return apply_filters( 'em_people_build_sql_orderby', parent::build_sql_orderby($args, $accepted_fields, get_option('dbem_people_default_order')), $args, $accepted_fields, $default_order );
99
  }
100
 
101
- /*
102
- * Adds custom people search defaults
103
- * @param array $array
104
  * @return array
105
- * @uses EM_Object#get_default_search()
106
  */
107
- function get_default_search( $array = array() ){
108
- $defaults = array(
109
- 'scope'=>false,
110
- 'eventful' => false, //cats that have an event (scope will also play a part here
111
- 'eventless' => false, //cats WITHOUT events, eventful takes precedence
112
- );
113
- //figure out default owning permissions, but since public is for viewing events, only impose limitations in admin area
114
- if( is_admin() ){
115
- switch( get_option('dbem_permissions_events') ){
116
- case 0:
117
- $defaults['owner'] = get_current_user_id();
118
- break;
119
- case 1:
120
- $defaults['owner'] = false;
121
- break;
122
- }
123
- $defaults['owner'] = ( em_verify_admin() ) ? false:$defaults['owner'];
124
- }
125
- return apply_filters('em_people_get_default_search', parent::get_default_search($defaults,$array), $array, $defaults);
126
  }
127
-
128
  }
 
 
129
  ?>
2
  class EM_People extends EM_Object {
3
 
4
  /**
5
+ * Handles the action of someone being deleted on WordPress
6
+ * @param int $id
 
7
  */
8
+ function delete_user( $id ){
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
  global $wpdb;
10
+ if( current_user_can('delete_users') ){
11
+ if( $_REQUEST['delete_option'] == 'reassign' && is_numeric($_REQUEST['reassign_user']) ){
12
+ $wpdb->update(EM_EVENTS_TABLE, array('event_owner'=>$_REQUEST['reassign_user']), array('event_owner'=>$id));
13
+ }else{
14
+ //User is being deleted, so we delete their events and cancel their bookings.
15
+ $wpdb->query("DELETE FROM ".EM_EVENTS_TABLE." WHERE event_owner=$id");
 
 
 
 
 
16
  }
 
17
  }
18
+ //set bookings to cancelled
19
+ $wpdb->update(EM_BOOKINGS_TABLE, array('booking_status'=>3, 'person_id'=>0, 'booking_comment'=>__('User deleted by administrators','dbem')), array('person_id'=>$id));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
  }
21
 
22
+ /**
23
+ * Adds phone number to contact info of users, compatible with previous phone field method
24
+ * @param $array
25
  * @return array
 
26
  */
27
+ function user_contactmethods($array){
28
+ $array['dbem_phone'] = __('Phone','dbem') . ' <span class="description">('. __('Events Manager','dbem') .')</span>';
29
+ return $array;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
30
  }
 
31
  }
32
+ add_action('delete_user', array('EM_People','delete_user'),10,1);
33
+ add_filter( 'user_contactmethods' , array('EM_People','user_contactmethods'),10,1);
34
  ?>
classes/em-permalinks.php ADDED
@@ -0,0 +1,191 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if( !class_exists('EM_Permalinks') ){
4
+ class EM_Permalinks {
5
+ static $em_queryvars = array(
6
+ 'event_id','event_slug', 'em_redirect',
7
+ 'location_id','location_slug',
8
+ 'person_id',
9
+ 'booking_id',
10
+ 'category_id', 'category_slug',
11
+ 'ticket_id', 'scope',
12
+ 'calendar_day',
13
+ 'rss', 'page', 'bookings_page', 'payment_gateway','event_categories','event_locations'
14
+ );
15
+
16
+ function init(){
17
+ add_filter('pre_update_option_dbem_events_page', array('EM_Permalinks','option_update'));
18
+ if( get_option('dbem_flush_needed') ){
19
+ add_filter('init', array('EM_Permalinks','flush'));
20
+ }
21
+ add_filter('rewrite_rules_array',array('EM_Permalinks','rewrite_rules_array'));
22
+ add_filter('query_vars',array('EM_Permalinks','query_vars'));
23
+ add_action('parse_query',array('EM_Permalinks','init_objects'), 1);
24
+ add_action('parse_query',array('EM_Permalinks','redirection'), 10);
25
+ if( !defined('EM_EVENT_SLUG') ){ define('EM_EVENT_SLUG','event'); }
26
+ if( !defined('EM_LOCATION_SLUG') ){ define('EM_LOCATION_SLUG','location'); }
27
+ if( !defined('EM_LOCATIONS_SLUG') ){ define('EM_LOCATIONS_SLUG','locations'); }
28
+ if( !defined('EM_CATEGORY_SLUG') ){ define('EM_CATEGORY_SLUG','category'); }
29
+ if( !defined('EM_CATEGORIES_SLUG') ){ define('EM_CATEGORIES_SLUG','categories'); }
30
+ }
31
+
32
+ function flush(){
33
+ global $wp_rewrite;
34
+ $wp_rewrite->flush_rules();
35
+ delete_option('dbem_flush_needed');
36
+ }
37
+
38
+ /**
39
+ * will redirect old links to new link structures.
40
+ * @return mixed
41
+ */
42
+ function redirection(){
43
+ global $wpdb, $wp_rewrite, $post, $wp_query;
44
+ if( $wp_query->get('em_redirect') ){
45
+ //is this a querystring url?
46
+ if( $wp_query->get('event_slug') ){
47
+ $event = $wpdb->get_row('SELECT event_id, post_id FROM '.EM_EVENTS_TABLE." WHERE event_slug='".$wp_query->get('event_slug')."' AND (blog_id=".get_current_blog_id()." OR blog_id IS NULL)", ARRAY_A);
48
+ if( $event !== false ){
49
+ $EM_Event = em_get_event($event['event_id']);
50
+ $url = get_permalink($EM_Event->post_id);
51
+ }
52
+ }elseif( $wp_query->get('location_slug') ){
53
+ $location = $wpdb->get_row('SELECT location_id, post_id FROM '.EM_LOCATIONS_TABLE." WHERE location_slug='".$wp_query->get('location_slug')."' AND (blog_id=".get_current_blog_id()." OR blog_id IS NULL)", ARRAY_A);
54
+ if( $location !== false ){
55
+ $EM_Location = em_get_location($location['location_id']);
56
+ $url = get_permalink($EM_Location->post_id);
57
+ }
58
+ }elseif( $wp_query->get('category_slug') ){
59
+ $url = get_term_link($wp_query->get('category_slug'), EM_TAXONOMY_CATEGORY);
60
+ }
61
+ if(!empty($url)){
62
+ wp_redirect($url,301);
63
+ exit();
64
+ }
65
+ }
66
+ }
67
+ // Adding a new rule
68
+ function rewrite_rules_array($rules){
69
+ //get the slug of the event page
70
+ $events_page_id = get_option ( 'dbem_events_page' );
71
+ $events_page = get_post($events_page_id);
72
+ $em_rules = array();
73
+ if( is_object($events_page) ){
74
+ $events_slug = preg_replace('/\/$/', '', str_replace( trailingslashit(home_url()), '', get_permalink($events_page_id) ));
75
+ $em_rules[$events_slug.'/(\d{4}-\d{2}-\d{2})$'] = 'index.php?pagename='.$events_slug.'&calendar_day=$matches[1]'; //event calendar date search
76
+ $em_rules[$events_slug.'/my\-bookings$'] = 'index.php?pagename='.$events_slug.'&bookings_page=1'; //page for users to manage bookings
77
+ $em_rules[$events_slug.'/rss$'] = 'index.php?pagename='.$events_slug.'&rss=1'; //rss page
78
+ $em_rules[$events_slug.'/feed$'] = 'index.php?pagename='.$events_slug.'&rss=1'; //compatible rss page
79
+ $em_rules[$events_slug.'/payments/(.+)$'] = 'index.php?pagename='.$events_slug.'&payment_gateway=$matches[1]'; //single event booking form with slug
80
+ if( EM_POST_TYPE_EVENT_SLUG == $events_slug ){
81
+ //make sure we hard-code rewrites for child pages of events
82
+ $child_posts = get_posts(array('post_type'=>'page', 'post_parent'=>$events_page->ID));
83
+ foreach($child_posts as $child_post){
84
+ $em_rules[$events_slug.'/'.$child_post->post_name.'/?$'] = 'index.php?page_id='.$child_post->ID; //single event booking form with slug
85
+ }
86
+ }
87
+ if( EM_MS_GLOBAL && !get_site_option('dbem_ms_global_events_links', true) ){
88
+ //MS Mode has slug also for global links
89
+ $em_rules[$events_slug.'/'.get_site_option('dbem_ms_events_slug',EM_EVENT_SLUG).'/(.+)$'] = 'index.php?pagename='.$events_slug.'&em_redirect=1&event_slug=$matches[1]'; //single event from subsite
90
+ }
91
+ //add redirection for backwards compatability
92
+ $em_rules[$events_slug.'/'.EM_EVENT_SLUG.'/(.+)$'] = 'index.php?pagename='.$events_slug.'&em_redirect=1&event_slug=$matches[1]'; //single event
93
+ $em_rules[$events_slug.'/'.EM_LOCATION_SLUG.'/(.+)$'] = 'index.php?pagename='.$events_slug.'&em_redirect=1&location_slug=$matches[1]'; //single location page
94
+ $em_rules[$events_slug.'/'.EM_CATEGORY_SLUG.'/(.+)$'] = 'index.php?pagename='.$events_slug.'&em_redirect=1&category_slug=$matches[1]'; //single category page slug
95
+ }else{
96
+ $events_slug = EM_POST_TYPE_EVENT_SLUG;
97
+ $em_rules[$events_slug.'/(\d{4}-\d{2}-\d{2})$'] = 'index.php?post_type='.EM_POST_TYPE_EVENT.'&scope=$matches[1]'; //event calendar date search
98
+ $em_rules[$events_slug.'/my\-bookings$'] = 'index.php?post_type='.EM_POST_TYPE_EVENT.'&bookings_page=1'; //page for users to manage bookings
99
+ $em_rules[$events_slug.'/rss$'] = 'index.php?post_type='.EM_POST_TYPE_EVENT.'&rss=1'; //rss page
100
+ $em_rules[$events_slug.'/payments/(.+)$'] = 'index.php?post_type='.EM_POST_TYPE_EVENT.'&payment_gateway=$matches[1]'; //single event booking form with slug
101
+ }
102
+ //If in MS global mode and locations are linked on same site
103
+ if( EM_MS_GLOBAL && !get_site_option('dbem_ms_global_locations_links', true) ){
104
+ $locations_page_id = get_option ( 'dbem_locations_page' );
105
+ $locations_page = get_post($locations_page_id);
106
+ if( is_object($locations_page) ){
107
+ $locations_slug = preg_replace('/\/$/', '', str_replace( trailingslashit(home_url()), '', get_permalink($locations_page_id) ));
108
+ $em_rules[$locations_slug.'/'.get_site_option('dbem_ms_locations_slug',EM_LOCATION_SLUG).'/(.+)$'] = 'index.php?pagename='.$locations_slug.'&location_slug=$matches[1]'; //single event booking form with slug
109
+ }
110
+ }
111
+ return $em_rules + $rules;
112
+ }
113
+
114
+ /**
115
+ * Depreciated, use get_post_permalink() from now on or the output function with a placeholder
116
+ * Generate a URL. Pass each section of a link as a parameter, e.g. EM_Permalinks::url('event',$event_id); will create an event link.
117
+ * @param mixed
118
+ */
119
+ function url(){
120
+ global $wp_rewrite;
121
+ $args = func_get_args();
122
+ $em_uri = get_permalink(get_option("dbem_events_page")); //PAGE URI OF EM
123
+ if ( $wp_rewrite->using_permalinks() /*&& !defined('EM_DISABLE_PERMALINKS')*/ ) {
124
+ $event_link = trailingslashit(trailingslashit($em_uri). implode('/',$args));
125
+ }
126
+ return $event_link;
127
+ }
128
+
129
+ /**
130
+ * checks if the events page has changed, and sets a flag to flush wp_rewrite.
131
+ * @param mixed $val
132
+ * @return mixed
133
+ */
134
+ function option_update( $val ){
135
+ if( get_option('dbem_events_page') != $val ){
136
+ update_option('dbem_flush_needed',1);
137
+ }
138
+ return $val;
139
+ }
140
+
141
+ // Adding the id var so that WP recognizes it
142
+ function query_vars($vars){
143
+ foreach(self::$em_queryvars as $em_queryvar){
144
+ array_push($vars, $em_queryvar);
145
+ }
146
+ return $vars;
147
+ }
148
+
149
+ /**
150
+ * Not the "WP way" but for now this'll do!
151
+ */
152
+ function init_objects(){
153
+ //Build permalinks here
154
+ global $wp_query, $wp_rewrite;
155
+ if ( $wp_rewrite->using_permalinks() ) {
156
+ foreach(self::$em_queryvars as $em_queryvar){
157
+ if( $wp_query->get($em_queryvar) ) {
158
+ $_REQUEST[$em_queryvar] = $wp_query->get($em_queryvar);
159
+ }
160
+ }
161
+ }
162
+ //dirty rss condition
163
+ if( !empty($_REQUEST['rss']) ){
164
+ $_REQUEST['rss_main'] = 'main';
165
+ }
166
+ }
167
+ }
168
+ EM_Permalinks::init();
169
+ }
170
+
171
+ //Specific links that aren't generated by objects
172
+
173
+ /**
174
+ * returns the url of the my bookings page, depending on the settings page and if BP is installed.
175
+ * @return string
176
+ */
177
+ function em_get_my_bookings_url(){
178
+ global $bp, $wp_rewrite;
179
+ if( is_object($bp) ){
180
+ //get member url
181
+ return $bp->events->link.'attending/';
182
+ }elseif( get_option('dbem_bookings_my_page') ){
183
+ return get_permalink(get_option('dbem_bookings_my_page'));
184
+ }else{
185
+ if( $wp_rewrite->using_permalinks() && !defined('EM_DISABLE_PERMALINKS') ){
186
+ return trailingslashit(EM_URI)."my-bookings/";
187
+ }else{
188
+ return preg_match('/\?/',EM_URI) ? EM_URI.'&bookings_page=1':EM_URI.'?bookings_page=1';
189
+ }
190
+ }
191
+ }
classes/em-person.php CHANGED
@@ -1,154 +1,91 @@
1
  <?php
2
  // TODO make person details more secure and integrate with WP user data
3
- class EM_Person extends EM_Object{
4
- //DB Fields
5
- var $id = '';
6
- var $owner = '';
7
- var $name = '';
8
- var $email = '';
9
- var $phone = '';
10
- //Other Vars
11
- var $fields = array(
12
- 'person_id' => array('name'=>'id','type'=>'%d'),
13
- 'person_name' => array('name'=>'name','type'=>'%s'),
14
- 'person_email' => array('name'=>'email','type'=>'%s'),
15
- 'person_phone' => array('name'=>'phone','type'=>'%s')
16
- );
17
- var $required_fields = array('person_id', 'person_name', 'person_email', 'person_phone');
18
- var $feedback_message = "";
19
- var $errors = array();
20
 
21
- function EM_Person( $person_data = false ){
22
- if( $person_data != 0 ){
23
- //Load person data
24
- $person = array();
25
- if( is_array($person_data) ){
26
- $person = $person_data;
27
- }elseif( is_numeric($person_data) ){
28
- //Retreiving from the database
29
- global $wpdb;
30
- $sql = "SELECT * FROM ". $wpdb->prefix . EM_PEOPLE_TABLE ." WHERE person_id ='$person_data'";
31
- $person = $wpdb->get_row($sql, ARRAY_A);
32
  }
33
- //Save into the object
34
- $this->to_object($person);
35
- }
36
- }
37
-
38
- /**
39
- * Load an record into this object by passing an associative array of table criterie to search for.
40
- * Returns boolean depending on whether a record is found or not.
41
- * @param $search
42
- * @return boolean
43
- */
44
- function get($search) {
45
- global $wpdb;
46
- $conds = array();
47
- foreach($search as $key => $value) {
48
- if( array_key_exists($key, $this->fields) ){
49
- $conds[] = "`$key`='$value'";
50
- }
51
  }
52
- $sql = "SELECT * FROM ". $wpdb->prefix.EM_PEOPLE_TABLE ." WHERE " . implode(' AND ', $conds) ;
53
- $result = $wpdb->get_row($sql, ARRAY_A);
54
- if($result){
55
- $this->to_object($result);
56
- return true;
 
57
  }else{
58
- return false;
59
  }
 
 
60
  }
61
 
62
- function get_post(){
63
- $this->name = ( !empty($_REQUEST['person_name']) ) ? stripslashes($_REQUEST['person_name']) : '' ;
64
- $this->email = ( !empty($_REQUEST['person_email']) ) ? $_REQUEST['person_email'] : '';
65
- $this->phone = ( !empty($_REQUEST['person_phone']) ) ? $_REQUEST['person_phone'] : '';
66
- return apply_filters('em_person_get_post', $this->validate(), $this);
67
- }
68
-
69
- function save(){
70
  global $wpdb;
71
- do_action('em_person_save_pre',$this);
72
- if($this->validate()){
73
- //Does this person already exist?
74
- $this->load_similar();
75
- $table = $wpdb->prefix.EM_PEOPLE_TABLE;
76
- $data = $this->to_array();
77
- unset($data['person_id']);
78
- if($this->id != ''){
79
- $where = array( 'person_id' => $this->id );
80
- $result = $wpdb->update($table, $data, $where);
81
- }else{
82
- $result = $wpdb->insert($table, $data);
83
- $this->id = $wpdb->insert_id;
84
  }
85
- $this->feedback_message = ($result) ? __('Changes saved.'): __('Could not edit person details.','dbem');
86
- return apply_filters('em_save_delete', $result, $this);
87
- }else{
88
- $this->feedback_message = __('Could not edit person details.','dbem');
89
- return apply_filters('em_save_delete', false, $this);
90
- }
91
- }
92
-
93
- function delete(){
94
- global $wpdb;
95
- do_action('em_person_delete_pre', $this);
96
- $results = array();
97
- $results[] = $wpdb->query ( $wpdb->prepare("DELETE FROM ". $wpdb->prefix . EM_PEOPLE_TABLE ." WHERE person_id=%d", $this->id) );
98
- $results[] = $wpdb->query ( $wpdb->prepare("DELETE FROM ". $wpdb->prefix . EM_BOOKINGS_TABLE ." WHERE person_id=%d", $this->id) );
99
- return apply_filters('em_event_delete', !in_array(false,$results), $this);
100
- }
101
-
102
- function validate(){
103
- if( !preg_match('/^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}$/', $this->email) ){
104
- $this->errors[] = __('Please provide a valid email address.', 'dbem');
105
- return false;
106
- }
107
- return true;
108
- }
109
-
110
- function get_bookings(){
111
- global $wpdb;
112
- $results = $wpdb->get_results("SELECT * FROM ".$wpdb->prefix.EM_BOOKINGS_TABLE." WHERE person_id={$this->id}",ARRAY_A);
113
  $bookings = array();
114
- foreach($results as $booking_data){
115
- $bookings[] = new EM_Booking($booking_data);
 
 
 
 
 
 
 
 
116
  }
117
- return $bookings;
118
  }
119
-
120
  /**
121
- * Checks agains the database to see if this user exists already
122
- * @return boolean|int
123
  */
124
- function find_similar(){
125
  global $wpdb;
126
- $sql = "SELECT * FROM ". $wpdb->prefix.EM_PEOPLE_TABLE ." WHERE person_name='%s' AND person_email='%s' AND person_phone='%s'";
127
- $row = $wpdb->get_row( $wpdb->prepare($sql, array($this->name, $this->email, $this->phone)), ARRAY_A );
128
- if( is_array($row) ){
129
- return $row['person_id'];
130
  }
131
- return false;
132
  }
133
 
134
- /**
135
- * Checks if a similar record exists (same name, email and phone) and if so it loads
136
- * @return boolean
137
- */
138
- function load_similar(){
139
- $return = $this->find_similar();
140
- if( is_numeric($return) ){
141
- $this->id = $return;
142
- return true;
143
- }
144
- return false;
145
- }
 
 
 
 
146
 
147
- /**
148
- * Can the user manage this event?
149
- */
150
- function can_manage(){
151
- return ( get_option('dbem_permissions_events') || $this->owner == get_current_user_id() || em_verify_admin() );
152
  }
153
  }
154
  ?>
1
  <?php
2
  // TODO make person details more secure and integrate with WP user data
3
+ class EM_Person extends WP_User{
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
 
5
+ function EM_Person( $person_id = false, $username = false ){
6
+ if( is_array($person_id) ){
7
+ if( array_key_exists('person_id',$person_id) ){
8
+ $person_id = $person_id['person_id'];
9
+ }elseif ( array_key_exists('user_id',$person_id) ){
10
+ $person_id = $person_id['user_id'];
11
+ }else{
12
+ $person_id = $person_id['ID'];
 
 
 
13
  }
14
+ }elseif( is_object($person_id) && get_class($person_id) == 'WP_User'){
15
+ $person_id = $person_id->ID; //create new object if passed a wp_user
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
  }
17
+ if($username){
18
+ parent::__construct($person_id, $username);
19
+ }elseif( is_numeric($person_id) && $person_id == 0 ){
20
+ $this->ID = 0;
21
+ $this->display_name = 'Non-Registered User';
22
+ $this->user_email = 'n/a';
23
  }else{
24
+ parent::__construct($person_id);
25
  }
26
+ $this->phone = get_metadata('user', $this->ID, 'dbem_phone', true); //extra field for EM
27
+ do_action('em_person',$this, $person_id, $username);
28
  }
29
 
30
+ function get_bookings($ids_only = false){
 
 
 
 
 
 
 
31
  global $wpdb;
32
+ if( is_multisite() ){
33
+ if( !is_main_site() ){
34
+ //not the main blog, force single blog search
35
+ $blog_condition = "AND e.blog_id=".get_current_blog_id();
36
+ }elseif(is_main_site() && !get_option('dbem_ms_global_events')){
37
+ $blog_condition = "AND (e.blog_id=".get_current_blog_id().' OR e.blog_id IS NULL)';
 
 
 
 
 
 
 
38
  }
39
+ }
40
+ $EM_Booking = new EM_Booking(); //empty booking for fields
41
+ $results = $wpdb->get_results("SELECT b.".implode(', b.', array_keys($EM_Booking->fields))." FROM ".EM_BOOKINGS_TABLE." b, ".EM_EVENTS_TABLE." e WHERE e.event_id=b.event_id AND person_id={$this->id} {$blog_condition} ORDER BY event_start_date DESC",ARRAY_A);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
42
  $bookings = array();
43
+ if($ids_only){
44
+ foreach($results as $booking_data){
45
+ $bookings[] = $booking_data['booking_id'];
46
+ }
47
+ return $bookings;
48
+ }else{
49
+ foreach($results as $booking_data){
50
+ $bookings[] = new EM_Booking($booking_data);
51
+ }
52
+ return new EM_Bookings($bookings);
53
  }
 
54
  }
55
+
56
  /**
57
+ * @return EM_Events
 
58
  */
59
+ function get_events(){
60
  global $wpdb;
61
+ $events = array();
62
+ foreach( $this->get_bookings()->get_bookings() as $EM_Booking ){
63
+ $events[$EM_Booking->event_id] = $EM_Booking->get_event();
 
64
  }
65
+ return $events;
66
  }
67
 
68
+ function display_summary(){
69
+ ob_start();
70
+ ?>
71
+ <table>
72
+ <tr>
73
+ <td><?php echo get_avatar($this->ID); ?></td>
74
+ <td style="padding-left:10px; vertical-align: top;">
75
+ <strong><?php _e('Name','dbem'); ?></strong> : <a href="<?php echo EM_ADMIN_URL ?>&amp;page=events-manager-bookings&amp;person_id=<?php echo $this->ID; ?>"><?php echo $this->get_name() ?></a><br /><br />
76
+ <strong><?php _e('Email','dbem'); ?></strong> : <?php echo $this->user_email; ?><br /><br />
77
+ <strong><?php _e('Phone','dbem'); ?></strong> : <?php echo $this->phone; ?>
78
+ </td>
79
+ </tr>
80
+ </table>
81
+ <?php
82
+ return ob_get_clean();
83
+ }
84
 
85
+ function get_name(){
86
+ $full_name = $this->user_firstname . " " . $this->user_lastname ;
87
+ $full_name = trim($full_name);
88
+ return !empty($full_name) ? $full_name : $this->display_name;
 
89
  }
90
  }
91
  ?>
classes/em-recurrence.php DELETED
@@ -1,89 +0,0 @@
1
- <?php
2
- /**
3
- * Object that holds event recurrence info
4
- * The EM_Event objects will handle adding / editing / deleting recurrences, this just holds the recurring info
5
- * and provides extra functions to obtain related events.
6
- * @author marcus
7
- */
8
- class EM_Recurrence extends EM_Object{
9
- //TODO We NEED to add an author and rsvp to this recurrence.....
10
- var $fields = array(
11
- 'recurrence_id' => 'id',
12
- 'recurrence_author' => 'author',
13
- 'recurrence_name' => 'name',
14
- 'recurrence_start_time' => 'start_time',
15
- 'recurrence_end_time' => 'end_time',
16
- 'recurrence_start_date' => 'start_date',
17
- 'recurrence_end_date' => 'end_date',
18
- 'recurrence_notes' => 'notes',
19
- 'recurrence_rsvp' => 'rsvp',
20
- 'recurrence_seats' => 'seats',
21
- 'recurrence_contactperson_id' => 'contactperson_id',
22
- 'location_id' => 'location_id',
23
- 'recurrence_id' => 'recurrence_id',
24
- 'recurrence_category_id' => 'category_id',
25
- 'recurrence_attributes' => 'attributes',
26
- 'recurrence_interval' => 'interval',
27
- 'recurrence_freq' => 'freq',
28
- 'recurrence_byday' => 'byday',
29
- 'recurrence_byweekno' => 'byweekno',
30
- );
31
- /**
32
- * Array of EM_Event objects
33
- * @var array
34
- */
35
- var $events = array();
36
-
37
- /**
38
- * Initialize object. You can provide event data in an associative array (using database table field names), an id number, or false (default) to create empty event.
39
- * If you provide an event array or object, it will convert it into a recurrence (useful if you want to change event data into recurrence).
40
- * @param mixed $event_data
41
- * @return null
42
- */
43
- function EM_Recurrence($event_data = false) {
44
- global $wpdb;
45
- if( $event_data !== false ){
46
- $recurrence = array();
47
- if( is_array($event_data) && isset($event_data['recurrence_name']) ){
48
- //Directly inserting array of recurrence data
49
- $recurrence = $event_data;
50
- }elseif( is_numeric($event_data) || isset($event_data['recurrence_id']) ){
51
- //$event_data is recurrence_id - Retreiving from the database
52
- $recurrence_id = (is_array($event_data)) ? $event_data['recurrence_id']:$event_data;
53
- $sql = "SELECT * FROM ". $wpdb->prefix . EM_RECURRENCE_TABLE ." WHERE recurrence_id = $recurrence_id";
54
- $result = $wpdb->get_row( $sql, ARRAY_A );
55
- if($result){
56
- $this->location = new EM_Location ( $recurrence ['location_id'] );
57
- $recurrence = $result;
58
- }
59
- }
60
- $this->to_object($recurrence);
61
- }
62
- }
63
-
64
- /**
65
- * Removes recurrence record.
66
- * @param $recurrence_id
67
- * @return null
68
- */
69
- function delete() {
70
- global $wpdb;
71
- $sql = "DELETE FROM ".$wpdb->prefix.EM_RECURRENCE_TABLE." WHERE recurrence_id = '{$this->id}';";
72
- $wpdb->query($sql);
73
- }
74
-
75
- /**
76
- * Save an array into this class
77
- * @param $array
78
- * @return null
79
- */
80
- function to_object( $array = array() ){
81
- //Save event core data
82
- parent::to_object($array);
83
- //Save location info
84
- $this->location = new EM_Location($array['location_id']);
85
- //Save contact person info
86
- }
87
-
88
- }
89
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
classes/em-ticket-booking.php ADDED
@@ -0,0 +1,222 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class EM_Ticket_Booking extends EM_Object{
3
+ //DB Fields
4
+ var $ticket_booking_id;
5
+ var $booking_id;
6
+ var $ticket_id;
7
+ var $ticket_booking_price;
8
+ var $ticket_booking_spaces;
9
+ var $fields = array(
10
+ 'ticket_booking_id' => array('name'=>'id','type'=>'%d'),
11
+ 'ticket_id' => array('name'=>'ticket_id','type'=>'%d'),
12
+ 'booking_id' => array('name'=>'booking_id','type'=>'%d'),
13
+ 'ticket_booking_price' => array('name'=>'price','type'=>'%f'),
14
+ 'ticket_booking_spaces' => array('name'=>'spaces','type'=>'%d')
15
+ );
16
+ //Other Vars
17
+ /**
18
+ * Contains ticket object
19
+ * @var EM_Ticket
20
+ */
21
+ var $ticket;
22
+ /**
23
+ * Contains the booking object of this
24
+ * @var EM_Booking
25
+ */
26
+ var $booking;
27
+ var $required_fields = array( 'ticket_id', 'ticket_booking_spaces');
28
+
29
+ /**
30
+ * Creates ticket object and retreives ticket data (default is a blank ticket object). Accepts either array of ticket data (from db) or a ticket id.
31
+ * @param mixed $ticket_data
32
+ * @return null
33
+ */
34
+ function EM_Ticket_Booking( $ticket_data = false ){
35
+ if( $ticket_data !== false ){
36
+ //Load ticket data
37
+ $ticket = array();
38
+ if( is_array($ticket_data) ){
39
+ $ticket = $ticket_data;
40
+ }elseif( is_numeric($ticket_data) ){
41
+ //Retreiving from the database
42
+ global $wpdb;
43
+ $sql = "SELECT * FROM ". EM_TICKETS_BOOKINGS_TABLE ." WHERE ticket_booking_id ='$ticket_data'";
44
+ $ticket = $wpdb->get_row($sql, ARRAY_A);
45
+ }
46
+ //Save into the object
47
+ $this->to_object($ticket);
48
+ $this->compat_keys();
49
+ }
50
+ }
51
+
52
+ /**
53
+ * Saves the ticket into the database, whether a new or existing ticket
54
+ * @return boolean
55
+ */
56
+ function save(){
57
+ global $wpdb;
58
+ $table = EM_TICKETS_BOOKINGS_TABLE;
59
+ do_action('em_ticket_booking_save_pre',$this);
60
+ //First the person
61
+ if($this->validate()){
62
+ //Now we save the ticket
63
+ $this->booking_id = $this->get_booking()->id; //event wouldn't exist before save, so refresh id
64
+ $data = $this->to_array(true); //add the true to remove the nulls
65
+ if($this->ticket_booking_id != ''){
66
+ if($this->get_spaces() > 0){
67
+ $where = array( 'ticket_booking_id' => $this->ticket_booking_id );
68
+ $result = $wpdb->update($table, $data, $where, $this->get_types($data));
69
+ $this->feedback_message = __('Changes saved','dbem');
70
+ }else{
71
+ $this->result = $this->delete();
72
+ }
73
+ }else{
74
+ if($this->get_spaces() > 0){
75
+ //TODO better error handling
76
+ $result = $wpdb->insert($table, $data, $this->get_types($data));
77
+ $this->ticket_booking_id = $wpdb->insert_id;
78
+ $this->feedback_message = __('Ticket booking created','dbem');
79
+ }else{
80
+ //no point saving a booking with no spaces
81
+ $result = false;
82
+ }
83
+ }
84
+ if( $result === false ){
85
+ $this->feedback_message = __('There was a problem saving the ticket booking.', 'dbem');
86
+ $this->errors[] = __('There was a problem saving the ticket booking.', 'dbem');
87
+ }
88
+ return apply_filters('em_ticket_booking_save', ( count($this->errors) == 0 ), $this);
89
+ }else{
90
+ $this->feedback_message = __('There was a problem saving the ticket booking.', 'dbem');
91
+ $this->errors[] = __('There was a problem saving the ticket booking.', 'dbem');
92
+ return apply_filters('em_ticket_booking_save', false, $this);
93
+ }
94
+ return true;
95
+ }
96
+
97
+
98
+ /**
99
+ * Validates the ticket for saving. Should be run during any form submission or saving operation.
100
+ * @return boolean
101
+ */
102
+ function validate(){
103
+ $missing_fields = Array ();
104
+ foreach ( $this->required_fields as $field ) {
105
+ $true_field = $this->fields[$field]['name'];
106
+ if ( $this->$true_field == "") {
107
+ $missing_fields[] = $field;
108
+ }
109
+ }
110
+ if ( count($missing_fields) > 0){
111
+ // TODO Create friendly equivelant names for missing fields notice in validation
112
+ $this->errors[] = __ ( 'Missing fields: ' ) . implode ( ", ", $missing_fields ) . ". ";
113
+ }
114
+ return apply_filters('em_event_validate', count($this->errors) == 0, $this );
115
+ }
116
+
117
+ /**
118
+ * Get the total number of spaces booked for this ticket within this booking.
119
+ * @return int
120
+ */
121
+ function get_spaces(){
122
+ return apply_filters('em_booking_get_spaces',$this->ticket_booking_spaces,$this);
123
+ }
124
+
125
+ /**
126
+ * Gets the total price for this whole booking. Seting $force_reset to true will recheck spaces, even if previously done so.
127
+ * @param boolean $force_refresh
128
+ * @return float
129
+ */
130
+ function get_price( $force_refresh=false, $format = false, $add_tax = 'x' ){
131
+ if( $force_refresh || $this->ticket_booking_price == 0 || $add_tax !== 'x' || get_option('dbem_bookings_tax_auto_add') ){
132
+ //get the ticket, calculate price on spaces
133
+ $this->ticket_booking_price = $this->get_ticket()->get_price(false, $add_tax) * $this->ticket_booking_spaces;
134
+ }
135
+ if($format){
136
+ return apply_filters('em_booking_get_prices', em_get_currency_symbol().number_format($this->ticket_booking_price,2),$this);
137
+ }
138
+ return apply_filters('em_booking_get_prices',$this->ticket_booking_price,$this);
139
+ }
140
+
141
+ /**
142
+ * Smart event locator, saves a database read if possible.
143
+ */
144
+ function get_booking(){
145
+ global $EM_Booking;
146
+ if( is_object($this->booking) && get_class($this->booking)=='EM_Booking' && ($this->booking->booking_id == $this->booking_id || (empty($this->ticket_booking_id) && empty($this->booking_id))) ){
147
+ return $this->booking;
148
+ }elseif( is_object($EM_Booking) && $EM_Booking->booking_id == $this->booking_id ){
149
+ $this->booking = $EM_Booking;
150
+ }else{
151
+ if(is_numeric($this->booking_id)){
152
+ $this->booking = new EM_Booking($this->booking_id);
153
+ }else{
154
+ $this->booking = new EM_Booking();
155
+ }
156
+ }
157
+ return apply_filters('em_ticket_booking_get_booking', $this->booking, $this);;
158
+ }
159
+
160
+ /**
161
+ * Gets the ticket object this booking belongs to, saves a reference in ticket property
162
+ * @return EM_Ticket
163
+ */
164
+ function get_ticket(){
165
+ global $EM_Ticket;
166
+ if( is_object($this->ticket) && get_class($this->ticket)=='EM_Ticket' && $this->ticket->id == $this->ticket_id ){
167
+ return $this->ticket;
168
+ }elseif( is_object($EM_Ticket) && $EM_Ticket->id == $this->ticket_id ){
169
+ $this->ticket = $EM_Ticket;
170
+ }else{
171
+ $this->ticket = new EM_Ticket($this->ticket_id);
172
+ }
173
+ return $this->ticket;
174
+ }
175
+
176
+ /**
177
+ * I wonder what this does....
178
+ * @return boolean
179
+ */
180
+ function delete(){
181
+ global $wpdb;
182
+ $sql = $wpdb->prepare("DELETE FROM ". EM_TICKETS_BOOKINGS_TABLE . " WHERE ticket_booking_id=%d", $this->ticket_booking_id);
183
+ $result = $wpdb->query( $sql );
184
+ return apply_filters('em_ticket_booking_delete', ($result !== false ), $this);
185
+ }
186
+
187
+
188
+ /**
189
+ * Get the html options for quantities to go within a <select> container
190
+ * @return string
191
+ */
192
+ function get_spaces_options($zero_value = true){
193
+ $available_spaces = $this->get_available_spaces();
194
+ if( $available_spaces >= $this->min || ( empty($this->min) && $available_spaces > 0) ) {
195
+ ob_start();
196
+ ?>
197
+ <select name="em_tickets[<?php echo $this->ticket_booking_id ?>][spaces]">
198
+ <?php
199
+ $min = ($this->min > 0) ? $this->min:1;
200
+ $max = ($this->max > 0) ? $this->max:get_option('dbem_bookings_form_max');
201
+ ?>
202
+ <?php if($zero_value) : ?><option>0</option><?php endif; ?>
203
+ <?php for( $i=$min; $i<=$max; $i++ ): ?>
204
+ <option><?php echo $i ?></option>
205
+ <?php endfor; ?>
206
+ </select>
207
+ <?php
208
+ return ob_get_clean();
209
+ }else{
210
+ return false;
211
+ }
212
+
213
+ }
214
+
215
+ /**
216
+ * Can the user manage this event?
217
+ */
218
+ function can_manage(){
219
+ return ( $this->get_booking()->can_manage() );
220
+ }
221
+ }
222
+ ?>
classes/em-ticket.php ADDED
@@ -0,0 +1,338 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class EM_Ticket extends EM_Object{
3
+ //DB Fields
4
+ var $ticket_id;
5
+ var $event_id;
6
+ var $ticket_name;
7
+ var $ticket_description;
8
+ var $ticket_price;
9
+ var $ticket_start;
10
+ var $ticket_end;
11
+ var $ticket_min;
12
+ var $ticket_max;
13
+ var $ticket_spaces = 10;
14
+ var $fields = array(
15
+ 'ticket_id' => array('name'=>'id','type'=>'%d'),
16
+ 'event_id' => array('name'=>'event_id','type'=>'%d'),
17
+ 'ticket_name' => array('name'=>'name','type'=>'%s'),
18
+ 'ticket_description' => array('name'=>'description','type'=>'%s','null'=>1),
19
+ 'ticket_price' => array('name'=>'price','type'=>'%f','null'=>1),
20
+ 'ticket_start' => array('name'=>'start','type'=>'%s','null'=>1),
21
+ 'ticket_end' => array('name'=>'end','type'=>'%s','null'=>1),
22
+ 'ticket_min' => array('name'=>'min','type'=>'%s','null'=>1),
23
+ 'ticket_max' => array('name'=>'max','type'=>'%s','null'=>1),
24
+ 'ticket_spaces' => array('name'=>'spaces','type'=>'%s','null'=>1)
25
+ );
26
+ //Other Vars
27
+ /**
28
+ * Contains only bookings belonging to this ticket.
29
+ * @var EM_Booking
30
+ */
31
+ var $bookings = array();
32
+ var $required_fields = array('ticket_name');
33
+ var $start_timestamp;
34
+ var $end_timestamp;
35
+ /**
36
+ * is this ticket limited by spaces allotted to this ticket? false if no limit (i.e. the events general limit of seats)
37
+ * @var unknown_type
38
+ */
39
+ var $spaces_limit = true;
40
+
41
+ /**
42
+ * Creates ticket object and retreives ticket data (default is a blank ticket object). Accepts either array of ticket data (from db) or a ticket id.
43
+ * @param mixed $ticket_data
44
+ * @return null
45
+ */
46
+ function EM_Ticket( $ticket_data = false ){
47
+ $this->ticket_name = __('Standard Ticket','dbem');
48
+ if( $ticket_data !== false ){
49
+ //Load ticket data
50
+ $ticket = array();
51
+ if( is_array($ticket_data) ){
52
+ $ticket = $ticket_data;
53
+ }elseif( is_numeric($ticket_data) ){
54
+ //Retreiving from the database
55
+ global $wpdb;
56
+ $sql = "SELECT * FROM ". EM_TICKETS_TABLE ." WHERE ticket_id ='$ticket_data'";
57
+ $ticket = $wpdb->get_row($sql, ARRAY_A);
58
+ //Ticket notes
59
+ $notes = $wpdb->get_results("SELECT * FROM ". EM_META_TABLE ." WHERE meta_key='ticket-note' AND object_id ='$ticket_data'", ARRAY_A);
60
+ foreach($notes as $note){
61
+ $this->notes[] = unserialize($note['meta_value']);
62
+ }
63
+ }
64
+ //Save into the object
65
+ $this->to_object($ticket);
66
+ $this->start_timestamp = (!empty($ticket['ticket_start'])) ? strtotime($ticket['ticket_start']):false;
67
+ $this->end_timestamp = (!empty($ticket['ticket_end'])) ? strtotime($ticket['ticket_end']):false;
68
+ }
69
+ $this->compat_keys();
70
+ do_action('em_ticket',$this, $ticket_data);
71
+ }
72
+
73
+ /**
74
+ * Saves the ticket into the database, whether a new or existing ticket
75
+ * @return boolean
76
+ */
77
+ function save(){
78
+ global $wpdb;
79
+ $table = EM_TICKETS_TABLE;
80
+ do_action('em_ticket_save_pre',$this);
81
+ //First the person
82
+ if($this->validate() && $this->can_manage() ){
83
+ //Now we save the ticket
84
+ $data = $this->to_array(true); //add the true to remove the nulls
85
+ if($this->ticket_id != ''){
86
+ //since currently wpdb calls don't accept null, let's build the sql ourselves.
87
+ $set_array = array();
88
+ foreach( $this->fields as $field_name => $field ){
89
+ if( empty($this->$field['name']) && $field['null'] ){
90
+ $set_array[] = "{$field_name}=NULL";
91
+ }else{
92
+ $set_array[] = "{$field_name}='".$wpdb->escape($this->$field['name'])."'";
93
+ }
94
+ }
95
+ $sql = "UPDATE $table SET ".implode(', ', $set_array)." WHERE ticket_id={$this->ticket_id}";
96
+ $result = $wpdb->query($sql);
97
+ $this->feedback_message = __('Changes saved','dbem');
98
+ }else{
99
+ //TODO better error handling
100
+ $result = $wpdb->insert($table, $data, $this->get_types($data));
101
+ $this->ticket_id = $wpdb->insert_id;
102
+ $this->feedback_message = __('Ticket created','dbem');
103
+ }
104
+ if( $result === false ){
105
+ $this->feedback_message = __('There was a problem saving the ticket.', 'dbem');
106
+ $this->errors[] = __('There was a problem saving the ticket.', 'dbem');
107
+ }
108
+ return apply_filters('em_ticket_save', ( count($this->errors) == 0 ), $this);
109
+ }else{
110
+ $this->feedback_message = __('There was a problem saving the ticket.', 'dbem');
111
+ $this->errors[] = __('There was a problem saving the ticket.', 'dbem');
112
+ return apply_filters('em_ticket_save', false, $this);
113
+ }
114
+ return true;
115
+ }
116
+
117
+ /**
118
+ * Get posted data and save it into the object (not db)
119
+ * @return boolean
120
+ */
121
+ function get_post(){
122
+ //We are getting the values via POST or GET
123
+ global $allowedposttags;
124
+ do_action('em_location_get_post_pre', $this);
125
+ $this->ticket_id = ( !empty($_POST['ticket_id']) ) ? $_POST['ticket_id']:'';
126
+ $this->event_id = ( !empty($_POST['event_id']) ) ? $_POST['event_id']:'';
127
+ $this->ticket_name = ( !empty($_POST['ticket_name']) ) ? wp_kses_data(stripslashes($_POST['ticket_name'])):'';
128
+ $this->ticket_description = ( !empty($_POST['ticket_description']) ) ? wp_kses(stripslashes($_POST['ticket_description'], $allowedposttags)):'';
129
+ $this->ticket_price = ( !empty($_POST['ticket_price']) ) ? $_POST['ticket_price']:'';
130
+ $this->ticket_start = ( !empty($_POST['ticket_start']) ) ? $_POST['ticket_start']:'';
131
+ $this->ticket_end = ( !empty($_POST['ticket_end']) ) ? $_POST['ticket_end']:'';
132
+ $this->start_timestamp = ( !empty($_POST['ticket_start']) ) ? strtotime($_POST['ticket_start']):'';
133
+ $this->end_timestamp = ( !empty($_POST['ticket_end']) ) ? strtotime($_POST['ticket_end']):'';
134
+ $this->ticket_min = ( !empty($_POST['ticket_min']) ) ? $_POST['ticket_min']:'';
135
+ $this->ticket_max = ( !empty($_POST['ticket_max']) ) ? $_POST['ticket_max']:'';
136
+ $this->ticket_spaces = ( !empty($_POST['ticket_spaces']) ) ? $_POST['ticket_spaces']:'';
137
+ do_action('em_ticket_get_post', $this);
138
+ }
139
+
140
+
141
+ /**
142
+ * Validates the ticket for saving. Should be run during any form submission or saving operation.
143
+ * @return boolean
144
+ */
145
+ function validate(){
146
+ $missing_fields = Array ();
147
+ $this->errors = array();
148
+ foreach ( $this->required_fields as $field ) {
149
+ $true_field = $this->fields[$field]['name'];
150
+ if ( $this->$true_field == "") {
151
+ $missing_fields[] = $field;
152
+ }
153
+ }
154
+ if( !empty($this->ticket_price) && !is_numeric($this->ticket_price) ){
155
+ $this->add_error(__('Please enter a valid ticket price e.g. 10.50 (no currency signs)','dbem'));
156
+ }
157
+ if ( count($missing_fields) > 0){
158
+ // TODO Create friendly equivelant names for missing fields notice in validation
159
+ $this->errors[] = __ ( 'Missing fields: ' ) . implode ( ", ", $missing_fields ) . ". ";
160
+ }
161
+ return apply_filters('em_event_validate', count($this->errors) == 0, $this );
162
+ }
163
+
164
+ function is_available(){
165
+ $timestamp = current_time('timestamp');
166
+ $available_spaces = $this->get_available_spaces();
167
+ $condition_1 = (empty($this->ticket_start) || $this->start_timestamp <= $timestamp);
168
+ $condition_2 = ($this->end_timestamp >= $timestamp || empty($this->ticket_end));
169
+ $condition_3 = $this->get_event()->end > $timestamp;
170
+ if( $condition_1 && $condition_2 && $condition_3 ){
171
+ //Time Constraints met, now quantities
172
+ if( $available_spaces > 0 && ($available_spaces >= $this->ticket_min || empty($this->ticket_min)) ){
173
+ return apply_filters('em_ticket_is_available',true,$this);
174
+ }
175
+ }
176
+ return apply_filters('em_ticket_is_available',false,$this);
177
+ }
178
+
179
+ /**
180
+ * Gets the total price for this ticket.
181
+ * @return float
182
+ */
183
+ function get_price($format = false, $add_tax = 'x' ){
184
+ $price = $this->ticket_price;
185
+ if( is_numeric(get_option('dbem_bookings_tax')) && get_option('dbem_bookings_tax') > 0 ){
186
+ //tax could be added here
187
+ if( $add_tax === true || ($add_tax !== false && get_option('dbem_bookings_tax_auto_add')) ){
188
+ $price = $price * (1 + get_option('dbem_bookings_tax')/100);
189
+ }
190
+ }
191
+ if($format){
192
+ return apply_filters('em_ticket_get_price', em_get_currency_symbol().number_format($price,2),$this);
193
+ }
194
+ return apply_filters('em_ticket_get_price',number_format($price,2),$this);
195
+ }
196
+
197
+ /**
198
+ * Get the total number of tickets (spaces) available, bearing in mind event-wide maxiumums and ticket priority settings.
199
+ * @return int
200
+ */
201
+ function get_spaces(){
202
+ return apply_filters('em_ticket_get_spaces',$this->ticket_spaces,$this);
203
+ }
204
+
205
+ /**
206
+ * Returns the number of available spaces left in this ticket, bearing in mind event-wide restrictions, previous bookings, approvals and other tickets.
207
+ * @return int
208
+ */
209
+ function get_available_spaces(){
210
+ $event_available_spaces = $this->get_event()->get_bookings()->get_available_spaces();
211
+ $ticket_available_spaces = $this->get_spaces() - $this->get_booked_spaces();
212
+ $return = ($ticket_available_spaces <= $event_available_spaces) ? $ticket_available_spaces:$event_available_spaces;
213
+ return apply_filters('em_ticket_get_available_spaces', $return, $this);
214
+ }
215
+
216
+ /**
217
+ * Returns the number of available spaces left in this ticket, bearing in mind event-wide restrictions, previous bookings, approvals and other tickets.
218
+ * @return int
219
+ */
220
+ function get_booked_spaces($force_reload=false){
221
+ //get all bookings for this event
222
+ $spaces = 0;
223
+ if( is_object($this->bookings) && $force_reload ){
224
+ return $this->bookings;
225
+ }
226
+ foreach( $this->get_bookings()->get_bookings()->bookings as $EM_Booking ){ //get_bookings() is used twice so we get the confirmed (or all if confirmation disabled) bookings of this ticket's total bookings.
227
+ //foreach booking, get this ticket booking info if found
228
+ foreach($EM_Booking->get_tickets_bookings()->tickets_bookings as $EM_Ticket_Booking){
229
+ if( $EM_Ticket_Booking->ticket_id == $this->ticket_id ){
230
+ $spaces += $EM_Ticket_Booking->get_spaces();
231
+ }
232
+ }
233
+ }
234
+ return apply_filters('em_ticket_get_available_spaces', $spaces, $this);
235
+ }
236
+
237
+ /**
238
+ * Smart event locator, saves a database read if possible.
239
+ * @return EM_Event
240
+ */
241
+ function get_event(){
242
+ return em_get_event($this->event_id);
243
+ }
244
+
245
+ /**
246
+ * returns array of EM_Booking objects that have this ticket
247
+ * @return EM_Bookings
248
+ */
249
+ function get_bookings(){
250
+ $bookings = array();
251
+ foreach( $this->get_event()->get_bookings()->bookings as $EM_Booking ){
252
+ foreach($EM_Booking->get_tickets_bookings()->tickets_bookings as $EM_Ticket_Booking){
253
+ if( $EM_Ticket_Booking->ticket_id == $this->ticket_id ){
254
+ $bookings[$EM_Booking->booking_id] = $EM_Booking;
255
+ }
256
+ }
257
+ }
258
+ $this->bookings = new EM_Bookings($bookings);
259
+ return $this->bookings;
260
+ }
261
+
262
+ /**
263
+ * I wonder what this does....
264
+ * @return boolean
265
+ */
266
+ function delete(){
267
+ global $wpdb;
268
+ $result = false;
269
+ if( $this->can_manage() ){
270
+ if( count($this->get_bookings()->bookings) == 0 ){
271
+ $sql = $wpdb->prepare("DELETE FROM ". EM_TICKETS_TABLE . " WHERE ticket_id=%d", $this->ticket_id);
272
+ $result = $wpdb->query( $sql );
273
+ }else{
274
+ $this->feedback_message = __('You cannot delete a ticket that has a booking on it.','dbem');
275
+ $this->add_error($this->feedback_message);
276
+ return false;
277
+ }
278
+ }
279
+ return ( $result !== false );
280
+ }
281
+
282
+ /**
283
+ * Get the html options for quantities to go within a <select> container
284
+ * @return string
285
+ */
286
+ function get_spaces_options($zero_value = true, $default_value = 0){
287
+ $available_spaces = $this->get_available_spaces();
288
+ if( $this->is_available() ) {
289
+ ob_start();
290
+ ?>
291
+ <select name="em_tickets[<?php echo $this->ticket_id ?>][spaces]" class="em-ticket-select">
292
+ <?php
293
+ $min = ($this->ticket_min > 0) ? $this->ticket_min:1;
294
+ $max = ($this->ticket_max > 0) ? $this->ticket_max:get_option('dbem_bookings_form_max');
295
+ ?>
296
+ <?php if($zero_value) : ?><option>0</option><?php endif; ?>
297
+ <?php for( $i=$min; $i<=$available_spaces && $i<=$max; $i++ ): ?>
298
+ <option <?php if($i == $default_value){ echo 'selected="selected"'; $shown_default = true; } ?>><?php echo $i ?></option>
299
+ <?php endfor; ?>
300
+ <?php if(empty($shown_default) && $default_value > 0 ): ?><option selected="selected"><?php echo $default_value; ?></option><?php endif; ?>
301
+ </select>
302
+ <?php
303
+ return apply_filters('em_ticket_get_spaces_options', ob_get_clean(), $zero_value, $default_value, $this);
304
+ }else{
305
+ return false;
306
+ }
307
+
308
+ }
309
+
310
+ /**
311
+ * Can the user manage this event?
312
+ */
313
+ function can_manage(){
314
+ return $this->get_event()->can_manage('manage_bookings','manage_others_bookings');
315
+ }
316
+
317
+ /**
318
+ * Outputs properties with formatting
319
+ * @param string $property
320
+ * @return string
321
+ */
322
+ function output_property($property){
323
+ switch($property){
324
+ case 'start':
325
+ $value = date_i18n( get_option('date_format'), $this->start_timestamp );
326
+ break;
327
+ case 'end':
328
+ $value = date_i18n( get_option('date_format'), $this->end_timestamp );
329
+ break;
330
+ break;
331
+ default:
332
+ $value = $this->$property;
333
+ break;
334
+ }
335
+ return apply_filters('em_ticket_output_property',$value,$this);
336
+ }
337
+ }
338
+ ?>
classes/em-tickets-bookings.php ADDED
@@ -0,0 +1,283 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Deals with the each ticket booked in a single booking
4
+ * @author marcus
5
+ *
6
+ */
7
+ class EM_Tickets_Bookings extends EM_Object implements Iterator{
8
+
9
+ /**
10
+ * Array of EM_Ticket_Booking objects for a specific event
11
+ * @var array
12
+ */
13
+ var $tickets_bookings = array();
14
+ /**
15
+ * This object belongs to this booking object
16
+ * @var EM_Booking
17
+ */
18
+ var $booking;
19
+ /**
20
+ * This object belongs to this booking object
21
+ * @var EM_Ticket
22
+ */
23
+ var $ticket;
24
+ var $spaces;
25
+ var $price;
26
+
27
+ /**
28
+ * Creates an EM_Tickets instance,
29
+ * @param EM_Event $event
30
+ * @return null
31
+ */
32
+ function EM_Tickets_Bookings( $object = false ){
33
+ global $wpdb;
34
+ if($object){
35
+ if( is_object($object) && get_class($object) == "EM_Booking"){
36
+ $this->booking = $object;
37
+ $sql = "SELECT * FROM ". EM_TICKETS_BOOKINGS_TABLE ." bt LEFT JOIN ". EM_BOOKINGS_TABLE ." b ON bt.booking_id=b.booking_id WHERE b.booking_id ='{$this->booking->booking_id}'";
38
+ }elseif( is_object($object) && get_class($object) == "EM_Ticket"){
39
+ $this->ticket = $object;
40
+ $sql = "SELECT * FROM ". EM_TICKETS_BOOKINGS_TABLE ." bt LEFT JOIN ". EM_TICKETS_TABLE ." t ON bt.ticket_id=t.ticket_id WHERE t.ticket_id ='{$this->ticket->id}'";
41
+ }elseif( is_numeric($object) ){
42
+ $sql = "SELECT * FROM ". EM_TICKETS_BOOKINGS_TABLE ." bt LEFT JOIN ". EM_BOOKINGS_TABLE ." t ON bt.booking_id=t.booking_id WHERE t.booking_id ='{$object}'";
43
+ }
44
+ $tickets_bookings = $wpdb->get_results($sql, ARRAY_A);
45
+ //Get tickets belonging to this tickets booking.
46
+ foreach ($tickets_bookings as $ticket_booking){
47
+ $EM_Ticket_Booking = new EM_Ticket_Booking($ticket_booking);
48
+ $EM_Ticket_Booking->booking = $this->booking; //save some calls
49
+ $this->tickets_bookings[] = $EM_Ticket_Booking;
50
+ }
51
+ }
52
+ do_action('em_tickets_bookings',$this, $object);
53
+ }
54
+
55
+ /**
56
+ * Saves the ticket bookings for this booking into the database, whether a new or existing booking
57
+ * @return boolean
58
+ */
59
+ function save(){
60
+ global $wpdb;
61
+ do_action('em_tickets_bookings_save_pre',$this);
62
+ foreach( $this->tickets_bookings as $EM_Ticket_Booking ){
63
+ $result = $EM_Ticket_Booking->save();
64
+ if(!$result){
65
+ $this->errors = array_merge($this->errors, $EM_Ticket_Booking->get_errors());
66
+ }
67
+ }
68
+ if( count($this->errors) > 0 ){
69
+ $this->feedback_message = __('There was a problem saving the booking.', 'dbem');
70
+ $this->errors[] = __('There was a problem saving the booking.', 'dbem');
71
+ return apply_filters('em_tickets_bookings_save', false, $this);
72
+ }
73
+ return apply_filters('em_tickets_bookings_save', true, $this);
74
+ }
75
+
76
+ /**
77
+ * Add a booking into this event object, checking that there's enough space for the event
78
+ * @param EM_Ticket_Booking $EM_Ticket_Booking
79
+ * @return boolean
80
+ */
81
+ function add( $EM_Ticket_Booking, $override = false ){ //note, $override was a quick fix, not necessarily permanent, so don't depend on it just yet
82
+ global $wpdb,$EM_Mailer;
83
+ //Does the ticket we want to book have enough spaeces?
84
+ if ( $override || $EM_Ticket_Booking->get_ticket()->get_available_spaces() >= $EM_Ticket_Booking->get_spaces() ) {
85
+ $ticket_booking_key = $this->has_ticket($EM_Ticket_Booking->ticket_id);
86
+ if( $ticket_booking_key !== false && is_object($this->tickets_bookings[$ticket_booking_key]) ){
87
+ //previously booked ticket, so let's just replace it
88
+ $this->tickets_bookings[$ticket_booking_key]->spaces = $EM_Ticket_Booking->get_spaces();
89
+ $this->tickets_bookings[$ticket_booking_key]->get_price(true);
90
+ return apply_filters('em_tickets_bookings_add',true,$this);
91
+ }elseif( $EM_Ticket_Booking->get_spaces() > 0 ){
92
+ //new ticket in booking
93
+ $this->tickets_bookings[] = $EM_Ticket_Booking;
94
+ $this->get_spaces(true);
95
+ $this->get_price(true);
96
+ return apply_filters('em_tickets_bookings_add',true,$this);
97
+ }
98
+ } else {
99
+ $this->errors[] = __('Booking cannot be made, not enough spaces available!', 'dbem');
100
+ return apply_filters('em_tickets_bookings_add',false,$this);
101
+ }
102
+ return apply_filters('em_tickets_bookings_add',false,$this);
103
+ }
104
+
105
+ /**
106
+ * Checks if this set has a specific ticket booked, returning the key of the ticket in the EM_Tickets_Bookings->ticket_bookings array
107
+ * @param int $ticket_id
108
+ * @return mixed
109
+ */
110
+ function has_ticket( $ticket_id ){
111
+ foreach ($this->tickets_bookings as $key => $EM_Ticket_Booking){
112
+ if( $EM_Ticket_Booking->ticket_id == $ticket_id ){
113
+ return apply_filters('em_tickets_has_ticket',$key,$this);
114
+ }
115
+ }
116
+ return apply_filters('em_tickets_has_ticket',false,$this);
117
+ }
118
+
119
+ /**
120
+ * Smart event locator, saves a database read if possible.
121
+ */
122
+ function get_booking(){
123
+ global $EM_Booking;
124
+ $booking_id = $this->get_booking_id();
125
+ if( is_object($this->booking) && get_class($this->booking)=='EM_Booking' && $this->booking->booking_id == $booking_id ){
126
+ return $this->booking;
127
+ }elseif( is_object($EM_Booking) && $EM_Booking->booking_id == $booking_id ){
128
+ $this->booking = $EM_Booking;
129
+ }else{
130
+ if(is_numeric($booking_id)){
131
+ $this->booking = new EM_Booking($booking_id);
132
+ }else{
133
+ $this->booking = new EM_Booking();
134
+ }
135
+ }
136
+ return apply_filters('em_tickets_bookings_get_booking', $this->booking, $this);;
137
+ }
138
+
139
+ function get_booking_id(){
140
+ if( count($this->tickets_bookings) > 0 ){
141
+ foreach($this->tickets_bookings as $EM_Booking_Ticket){ break; } //get first array item
142
+ return apply_filters('em_tickets_bookings_get_booking_id', $EM_Booking_Ticket->id, $this);
143
+ }
144
+ return apply_filters('em_tickets_bookings_get_booking_id', false, $this);
145
+ }
146
+
147
+ /**
148
+ * Delete all ticket bookings
149
+ * @return boolean
150
+ */
151
+ function delete(){
152
+ global $wpdb;
153
+ if( $this->get_booking()->can_manage() ){
154
+ $result = $wpdb->query("DELETE FROM ".EM_TICKETS_BOOKINGS_TABLE." WHERE booking_id='{$this->get_booking()->id}'");
155
+ //echo "<pre>";print_r($this->get_booking());echo "</pre>";
156
+ }else{
157
+ //FIXME ticket bookings
158
+ $ticket_ids = array();
159
+ foreach( $this->tickets_bookings as $EM_Ticket_Booking ){
160
+ if( $EM_Ticket_Booking->can_manage() ){
161
+ $tickets_bookings_ids[] = $EM_Ticket_Booking->booking_id;
162
+ }else{
163
+ $this->errors[] = sprintf(__('You do not have the rights to manage this %s.','dbem'),__('Booking','dbem'));
164
+ }
165
+ }
166
+ if(count($ticket_ids) > 0){
167
+ $result = $wpdb->query("DELETE FROM ".EM_TICKETS_BOOKINGS_TABLE." WHERE ticket_booking_id IN (".implode(',',$ticket_ids).")");
168
+ }
169
+ }
170
+ return apply_filters('em_tickets_bookings_get_booking_id', ($result == true), $this);
171
+ }
172
+
173
+ /**
174
+ * Go through the tickets in this object and validate them
175
+ */
176
+ function validate(){
177
+ $errors = array();
178
+ foreach($this->tickets_bookings as $EM_Ticket_Booking){
179
+ $errors[] = $EM_Ticket_Booking->validate();
180
+ }
181
+ return apply_filters('em_tickets_bookings_validate', !in_array(false, $errors), $this);
182
+ }
183
+
184
+ /**
185
+ * Get the total number of spaces booked in this booking. Seting $force_reset to true will recheck spaces, even if previously done so.
186
+ * @param unknown_type $force_refresh
187
+ * @return mixed
188
+ */
189
+ function get_spaces( $force_refresh=false ){
190
+ if($force_refresh || $this->spaces == 0){
191
+ $spaces = 0;
192
+ foreach($this->tickets_bookings as $EM_Ticket_Booking){
193
+ $spaces += $EM_Ticket_Booking->get_spaces();
194
+ }
195
+ $this->spaces = $spaces;
196
+ }
197
+ return apply_filters('em_booking_get_spaces',$this->spaces,$this);
198
+ }
199
+
200
+ /**
201
+ * Gets the total price for this whole booking by adding up subtotals of booked tickets. Seting $force_reset to true will recheck spaces, even if previously done so.
202
+ * @param boolean $force_refresh
203
+ * @return float
204
+ */
205
+ function get_price( $force_refresh=false, $format = false, $add_tax = 'x' ){
206
+ $price = 0;
207
+ if($force_refresh || $this->price == 0 || $add_tax !== 'x' || get_option('dbem_bookings_tax_auto_add')){
208
+ foreach($this->tickets_bookings as $EM_Ticket_Booking){
209
+ $price += $EM_Ticket_Booking->get_price($force_refresh, false, $add_tax);
210
+ }
211
+ $this->price = $price;
212
+ }
213
+ if($format){
214
+ return apply_filters('em_tickets_bookings_get_prices', em_get_currency_symbol().number_format($this->price,2),$this);
215
+ }
216
+ return apply_filters('em_tickets_bookings_get_prices',$this->price,$this);
217
+ }
218
+
219
+ /**
220
+ * Goes through each ticket and populates it with the bookings made
221
+ */
222
+ function get_ticket_bookings(){
223
+ foreach( $this->tickets as $EM_Ticket ){
224
+ $EM_Ticket->get_bookings();
225
+ }
226
+ }
227
+
228
+ /* Overrides EM_Object method to apply a filter to result
229
+ * @see wp-content/plugins/events-manager/classes/EM_Object#build_sql_conditions()
230
+ */
231
+ function build_sql_conditions( $args = array() ){
232
+ $conditions = apply_filters( 'em_tickets_build_sql_conditions', parent::build_sql_conditions($args), $args );
233
+ if( is_numeric($args['status']) ){
234
+ $conditions['status'] = 'ticket_status='.$args['status'];
235
+ }
236
+ return apply_filters('em_tickets_bookings_build_sql_conditions', $conditions, $args);
237
+ }
238
+
239
+ /* Overrides EM_Object method to apply a filter to result
240
+ * @see wp-content/plugins/events-manager/classes/EM_Object#build_sql_orderby()
241
+ */
242
+ function build_sql_orderby( $args, $accepted_fields, $default_order = 'ASC' ){
243
+ return apply_filters( 'em_tickets_bookings_build_sql_orderby', parent::build_sql_orderby($args, $accepted_fields, get_option('dbem_events_default_order')), $args, $accepted_fields, $default_order );
244
+ }
245
+
246
+ /*
247
+ * Adds custom Events search defaults
248
+ * @param array $array
249
+ * @return array
250
+ * @uses EM_Object#get_default_search()
251
+ */
252
+ function get_default_search( $array = array() ){
253
+ $defaults = array(
254
+ 'status' => false,
255
+ 'person' => true //to add later, search by person's tickets...
256
+ );
257
+ $defaults['owner'] = !current_user_can('manage_others_bookings') ? get_current_user_id():false;
258
+ return apply_filters('em_tickets_bookings_get_default_search', parent::get_default_search($defaults,$array), $array, $defaults);
259
+ }
260
+
261
+ //Iterator Implementation
262
+ public function rewind(){
263
+ reset($this->tickets_bookings);
264
+ }
265
+ public function current(){
266
+ $var = current($this->tickets_bookings);
267
+ return $var;
268
+ }
269
+ public function key(){
270
+ $var = key($this->tickets_bookings);
271
+ return $var;
272
+ }
273
+ public function next(){
274
+ $var = next($this->tickets_bookings);
275
+ return $var;
276
+ }
277
+ public function valid(){
278
+ $key = key($this->tickets_bookings);
279
+ $var = ($key !== NULL && $key !== FALSE);
280
+ return $var;
281
+ }
282
+ }
283
+ ?>
classes/em-tickets.php ADDED
@@ -0,0 +1,241 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Deals with the ticket info for an event
4
+ * @author marcus
5
+ *
6
+ */
7
+ class EM_Tickets extends EM_Object implements Iterator{
8
+
9
+ /**
10
+ * Array of EM_Ticket objects for a specific event
11
+ * @var array
12
+ */
13
+ var $tickets = array();
14
+ /**
15
+ * @var int
16
+ */
17
+ var $event_id;
18
+ /**
19
+ * @var EM_Booking
20
+ */
21
+ var $booking;
22
+ var $spaces;
23
+
24
+
25
+ /**
26
+ * Creates an EM_Tickets instance,
27
+ * @param EM_Event $event
28
+ * @return null
29
+ */
30
+ function EM_Tickets( $object = false ){
31
+ global $wpdb;
32
+ if( is_numeric($object) || (is_object($object) && in_array(get_class($object), array("EM_Event","EM_Booking"))) ){
33
+ $this->event_id = (is_object($object)) ? $object->event_id:$object;
34
+ $sql = "SELECT * FROM ". EM_TICKETS_TABLE ." WHERE event_id ='{$this->event_id}' ORDER BY ".get_option('dbem_bookings_tickets_orderby');
35
+ $tickets = $wpdb->get_results($sql, ARRAY_A);
36
+ foreach ($tickets as $ticket){
37
+ $EM_Ticket = new EM_Ticket($ticket);
38
+ $EM_Ticket->event_id = $this->event_id;
39
+ $this->tickets[] = $EM_Ticket;
40
+ }
41
+ }elseif( is_array($object) ){ //expecting an array of EM_Ticket objects or ticket db array
42
+ if( is_object(current($object)) && get_class(current($object)) == 'EM_Ticket' ){
43
+ $this->tickets = $object;
44
+ }else{
45
+ foreach($object as $ticket){
46
+ $EM_Ticket = new EM_Ticket($ticket);
47
+ $EM_Ticket->event_id = $this->event_id;
48
+ $this->tickets[] = $EM_Ticket;
49
+ }
50
+ }
51
+ }
52
+ do_action('em_tickets', $this, $object);
53
+ }
54
+
55
+ /**
56
+ * @return EM_Event
57
+ */
58
+ function get_event(){
59
+ global $EM_Event;
60
+ if( is_object($EM_Event) && $EM_Event->event_id == $this->event_id ){
61
+ return $EM_Event;
62
+ }else{
63
+ return new EM_Event($this->event_id);
64
+ }
65
+ }
66
+
67
+ /**
68
+ * Get the first EM_Ticket object in this instance. Returns false if no tickets available.
69
+ * @return EM_Ticket
70
+ */
71
+ function get_first(){
72
+ if( count($this->tickets) > 0 ){
73
+ foreach($this->tickets as $EM_Ticket){
74
+ return $EM_Ticket;
75
+ }
76
+ }else{
77
+ return false;
78
+ }
79
+ }
80
+
81
+ /**
82
+ * Delete tickets in thie object
83
+ * @return boolean
84
+ */
85
+ function delete(){
86
+ global $wpdb;
87
+ //get all the ticket ids
88
+ $result = false;
89
+ $ticket_ids = array();
90
+ foreach( $this->tickets as $EM_Ticket ){
91
+ $ticket_ids[] = $EM_Ticket->id;
92
+ }
93
+ //check that tickets don't have bookings
94
+ if(count($ticket_ids) > 0){
95
+ $bookings = $wpdb->get_var("SELECT COUNT(*) FROM ". EM_TICKETS_BOOKINGS_TABLE." WHERE ticket_id IN (".implode(',',$ticket_ids).")");
96
+ if( $bookings > 0 ){
97
+ $result = false;
98
+ $this->add_error(__('You cannot delete tickets if there are any bookings associated with them. Please delete these bookings first.','dbem'));
99
+ }else{
100
+ $result = $wpdb->query("DELETE FROM ".EM_TICKETS_TABLE." WHERE event_id IN (".implode(',',$ticket_ids).")");
101
+ }
102
+ }
103
+ return ($result !== false);
104
+ }
105
+
106
+ /**
107
+ * Retrieve multiple ticket info via POST
108
+ * @return boolean
109
+ */
110
+ function get_post(){
111
+ //Build Event Array
112
+ do_action('em_tickets_get_post_pre', $this);
113
+ $this->tickets = array(); //clean current tickets out
114
+ if( !empty($_POST['em_tickets']) && is_array($_POST['em_tickets']) ){
115
+ //get all ticket data and create objects
116
+ foreach($_POST['em_tickets'] as $ticket_data){
117
+ $EM_Ticket = new EM_Ticket($ticket_data);
118
+ $this->tickets[] = $EM_Ticket;
119
+ }
120
+ }else{
121
+ //we create a blank standard ticket
122
+ $EM_Ticket = new EM_Ticket(array(
123
+ 'event_id' => $this->event_id,
124
+ 'ticket_name' => __('Standard','dbem')
125
+ ));
126
+ $this->tickets[] = $EM_Ticket;
127
+ }
128
+ return apply_filters('em_tickets_get_post', $this->validate(), $this);
129
+ }
130
+
131
+ /**
132
+ * Go through the tickets in this object and validate them
133
+ */
134
+ function validate(){
135
+ $this->errors = array();
136
+ foreach($this->tickets as $EM_Ticket){
137
+ if( !$EM_Ticket->validate() ){
138
+ $this->add_error($EM_Ticket->get_errors());
139
+ }
140
+ }
141
+ return apply_filters('em_tickets_validate', count($this->errors) == 0, $this);
142
+ }
143
+
144
+ /**
145
+ * Save tickets into DB
146
+ */
147
+ function save(){
148
+ $errors = array();
149
+ foreach( $this->tickets as $EM_Ticket ){
150
+ /* @var $EM_Ticket EM_Ticket */
151
+ $EM_Ticket->event_id = $this->event_id; //pass on saved event_data
152
+ $errors[] = $EM_Ticket->save();
153
+ }
154
+ return apply_filters('em_tickets_save', !in_array(false, $errors), $this);
155
+ }
156
+
157
+ /**
158
+ * Goes through each ticket and populates it with the bookings made
159
+ */
160
+ function get_ticket_bookings(){
161
+ foreach( $this->tickets as $EM_Ticket ){
162
+ $EM_Ticket->get_bookings();
163
+ }
164
+ }
165
+
166
+ /**
167
+ * Get the total number of spaces this event has. This will show the lower value of event global spaces limit or total ticket spaces. Setting $force_refresh to true will recheck spaces, even if previously done so.
168
+ * @param boolean $force_refresh
169
+ * @return int
170
+ */
171
+ function get_spaces( $force_refresh=false ){
172
+ $spaces = 0;
173
+ if($force_refresh || $this->spaces == 0){
174
+ foreach( $this->tickets as $EM_Ticket ){
175
+ /* @var $EM_Ticket EM_Ticket */
176
+ $spaces += $EM_Ticket->get_spaces();
177
+ }
178
+ $this->spaces = $spaces;
179
+ }
180
+ return apply_filters('em_booking_get_spaces',$this->spaces,$this);
181
+ }
182
+
183
+ /* Overrides EM_Object method to apply a filter to result
184
+ * @see wp-content/plugins/events-manager/classes/EM_Object#build_sql_conditions()
185
+ */
186
+ function build_sql_conditions( $args = array() ){
187
+ $conditions = apply_filters( 'em_tickets_build_sql_conditions', parent::build_sql_conditions($args), $args );
188
+ if( is_numeric($args['ticket_status']) ){
189
+ $conditions['ticket_status'] = 'ticket_status='.$args['status'];
190
+ }
191
+ return apply_filters('em_tickets_build_sql_conditions', $conditions, $args);
192
+ }
193
+
194
+ /* Overrides EM_Object method to apply a filter to result
195
+ * @see wp-content/plugins/events-manager/classes/EM_Object#build_sql_orderby()
196
+ */
197
+ function build_sql_orderby( $args, $accepted_fields, $default_order = 'ASC' ){
198
+ return apply_filters( 'em_tickets_build_sql_orderby', parent::build_sql_orderby($args, $accepted_fields, get_option('dbem_events_default_order')), $args, $accepted_fields, $default_order );
199
+ }
200
+
201
+ /*
202
+ * Adds custom Events search defaults
203
+ * @param array $array
204
+ * @return array
205
+ * @uses EM_Object#get_default_search()
206
+ */
207
+ function get_default_search( $array = array() ){
208
+ $defaults = array(
209
+ 'ticket_status' => false,
210
+ 'person' => true //to add later, search by person's tickets...
211
+ );
212
+ if( is_admin() ){
213
+ //figure out default owning permissions
214
+ $defaults['owner'] = !current_user_can('manage_others_bookings') ? get_current_user_id():false;
215
+ }
216
+ return apply_filters('em_tickets_get_default_search', parent::get_default_search($defaults,$array), $array, $defaults);
217
+ }
218
+
219
+ //Iterator Implementation
220
+ public function rewind(){
221
+ reset($this->tickets);
222
+ }
223
+ public function current(){
224
+ $var = current($this->tickets);
225
+ return $var;
226
+ }
227
+ public function key(){
228
+ $var = key($this->tickets);
229
+ return $var;
230
+ }
231
+ public function next(){
232
+ $var = next($this->tickets);
233
+ return $var;
234
+ }
235
+ public function valid(){
236
+ $key = key($this->tickets);
237
+ $var = ($key !== NULL && $key !== FALSE);
238
+ return $var;
239
+ }
240
+ }
241
+ ?>
classes/phpmailer/class.phpmailer.php CHANGED
@@ -1,1506 +1,2473 @@
1
  <?php
2
- ////////////////////////////////////////////////////
3
- // PHPMailer - PHP email class
4
- //
5
- // Class for sending email using either
6
- // sendmail, PHP mail(), or SMTP. Methods are
7
- // based upon the standard AspEmail(tm) classes.
8
- //
9
- // Copyright (C) 2001 - 2003 Brent R. Matzelle
10
- //
11
- // License: LGPL, see LICENSE
12
- ////////////////////////////////////////////////////
 
 
 
 
 
 
 
 
 
 
 
13
 
14
  /**
15
  * PHPMailer - PHP email transport class
 
16
  * @package PHPMailer
17
- * @author Brent R. Matzelle
18
- * @copyright 2001 - 2003 Brent R. Matzelle
 
 
 
 
 
19
  */
20
- class EM_PHPMailer
21
- {
22
- /////////////////////////////////////////////////
23
- // PUBLIC VARIABLES
24
- /////////////////////////////////////////////////
25
-
26
- /**
27
- * Email priority (1 = High, 3 = Normal, 5 = low).
28
- * @var int
29
- */
30
- var $Priority = 3;
31
-
32
- /**
33
- * Sets the CharSet of the message.
34
- * @var string
35
- */
36
- var $CharSet = "iso-8859-1";
37
-
38
- /**
39
- * Sets the Content-type of the message.
40
- * @var string
41
- */
42
- var $ContentType = "text/plain";
43
-
44
- /**
45
- * Sets the Encoding of the message. Options for this are "8bit",
46
- * "7bit", "binary", "base64", and "quoted-printable".
47
- * @var string
48
- */
49
- var $Encoding = "8bit";
50
-
51
- /**
52
- * Holds the most recent mailer error message.
53
- * @var string
54
- */
55
- var $ErrorInfo = "";
56
-
57
- /**
58
- * Sets the From email address for the message.
59
- * @var string
60
- */
61
- var $From = "root@localhost";
62
-
63
- /**
64
- * Sets the From name of the message.
65
- * @var string
66
- */
67
- var $FromName = "Root User";
68
-
69
- /**
70
- * Sets the Sender email (Return-Path) of the message. If not empty,
71
- * will be sent via -f to sendmail or as 'MAIL FROM' in smtp mode.
72
- * @var string
73
- */
74
- var $Sender = "";
75
-
76
- /**
77
- * Sets the Subject of the message.
78
- * @var string
79
- */
80
- var $Subject = "";
81
-
82
- /**
83
- * Sets the Body of the message. This can be either an HTML or text body.
84
- * If HTML then run IsHTML(true).
85
- * @var string
86
- */
87
- var $Body = "";
88
-
89
- /**
90
- * Sets the text-only body of the message. This automatically sets the
91
- * email to multipart/alternative. This body can be read by mail
92
- * clients that do not have HTML email capability such as mutt. Clients
93
- * that can read HTML will view the normal Body.
94
- * @var string
95
- */
96
- var $AltBody = "";
97
-
98
- /**
99
- * Sets word wrapping on the body of the message to a given number of
100
- * characters.
101
- * @var int
102
- */
103
- var $WordWrap = 0;
104
-
105
- /**
106
- * Method to send mail: ("mail", "sendmail", or "smtp").
107
- * @var string
108
- */
109
- var $Mailer = "mail";
110
-
111
- /**
112
- * Sets the path of the sendmail program.
113
- * @var string
114
- */
115
- var $Sendmail = "/usr/sbin/sendmail";
116
-
117
- /**
118
- * Path to PHPMailer plugins. This is now only useful if the SMTP class
119
- * is in a different directory than the PHP include path.
120
- * @var string
121
- */
122
- var $PluginDir = "";
123
-
124
- /**
125
- * Holds PHPMailer version.
126
- * @var string
127
- */
128
- var $Version = "1.73";
129
-
130
- /**
131
- * Sets the email address that a reading confirmation will be sent.
132
- * @var string
133
- */
134
- var $ConfirmReadingTo = "";
135
-
136
- /**
137
- * Sets the hostname to use in Message-Id and Received headers
138
- * and as default HELO string. If empty, the value returned
139
- * by SERVER_NAME is used or 'localhost.localdomain'.
140
- * @var string
141
- */
142
- var $Hostname = "";
143
-
144
- /////////////////////////////////////////////////
145
- // SMTP VARIABLES
146
- /////////////////////////////////////////////////
147
-
148
- /**
149
- * Sets the SMTP hosts. All hosts must be separated by a
150
- * semicolon. You can also specify a different port
151
- * for each host by using this format: [hostname:port]
152
- * (e.g. "smtp1.example.com:25;smtp2.example.com").
153
- * Hosts will be tried in order.
154
- * @var string
155
- */
156
- var $Host = "localhost";
157
-
158
- /**
159
- * Sets the default SMTP server port.
160
- * @var int
161
- */
162
- var $Port = 25;
163
-
164
- /**
165
- * Sets the SMTP HELO of the message (Default is $Hostname).
166
- * @var string
167
- */
168
- var $Helo = "";
169
-
170
- /**
171
- * Sets SMTP authentication. Utilizes the Username and Password variables.
172
- * @var bool
173
- */
174
- var $SMTPAuth = false;
175
-
176
- /**
177
- * Sets SMTP username.
178
- * @var string
179
- */
180
- var $Username = "";
181
-
182
- /**
183
- * Sets SMTP password.
184
- * @var string
185
- */
186
- var $Password = "";
187
-
188
- /**
189
- * Sets the SMTP server timeout in seconds. This function will not
190
- * work with the win32 version.
191
- * @var int
192
- */
193
- var $Timeout = 10;
194
-
195
- /**
196
- * Sets SMTP class debugging on or off.
197
- * @var bool
198
- */
199
- var $SMTPDebug = false;
200
-
201
- /**
202
- * Prevents the SMTP connection from being closed after each mail
203
- * sending. If this is set to true then to close the connection
204
- * requires an explicit call to SmtpClose().
205
- * @var bool
206
- */
207
- var $SMTPKeepAlive = false;
208
-
209
- /**#@+
210
- * @access private
211
- */
212
- var $smtp = NULL;
213
- var $to = array();
214
- var $cc = array();
215
- var $bcc = array();
216
- var $ReplyTo = array();
217
- var $attachment = array();
218
- var $CustomHeader = array();
219
- var $message_type = "";
220
- var $boundary = array();
221
- var $language = array();
222
- var $error_count = 0;
223
- var $LE = "\n";
224
- /**#@-*/
225
-
226
- /////////////////////////////////////////////////
227
- // VARIABLE METHODS
228
- /////////////////////////////////////////////////
229
-
230
- /**
231
- * Sets message type to HTML.
232
- * @param bool $bool
233
- * @return void
234
- */
235
- function IsHTML($bool) {
236
- if($bool == true)
237
- $this->ContentType = "text/html";
238
- else
239
- $this->ContentType = "text/plain";
240
- }
241
-
242
- /**
243
- * Sets Mailer to send message using SMTP.
244
- * @return void
245
- */
246
- function IsSMTP() {
247
- $this->Mailer = "smtp";
248
- }
249
-
250
- /**
251
- * Sets Mailer to send message using PHP mail() function.
252
- * @return void
253
- */
254
- function IsMail() {
255
- $this->Mailer = "mail";
256
- }
257
-
258
- /**
259
- * Sets Mailer to send message using the $Sendmail program.
260
- * @return void
261
- */
262
- function IsSendmail() {
263
- $this->Mailer = "sendmail";
264
- }
265
-
266
- /**
267
- * Sets Mailer to send message using the qmail MTA.
268
- * @return void
269
- */
270
- function IsQmail() {
271
- $this->Sendmail = "/var/qmail/bin/sendmail";
272
- $this->Mailer = "sendmail";
273
- }
274
-
275
-
276
- /////////////////////////////////////////////////
277
- // RECIPIENT METHODS
278
- /////////////////////////////////////////////////
279
-
280
- /**
281
- * Adds a "To" address.
282
- * @param string $address
283
- * @param string $name
284
- * @return void
285
- */
286
- function AddAddress($address, $name = "") {
287
- $cur = count($this->to);
288
- $this->to[$cur][0] = trim($address);
289
- $this->to[$cur][1] = $name;
290
- }
291
-
292
- /**
293
- * Adds a "Cc" address. Note: this function works
294
- * with the SMTP mailer on win32, not with the "mail"
295
- * mailer.
296
- * @param string $address
297
- * @param string $name
298
- * @return void
299
- */
300
- function AddCC($address, $name = "") {
301
- $cur = count($this->cc);
302
- $this->cc[$cur][0] = trim($address);
303
- $this->cc[$cur][1] = $name;
304
- }
305
-
306
- /**
307
- * Adds a "Bcc" address. Note: this function works
308
- * with the SMTP mailer on win32, not with the "mail"
309
- * mailer.
310
- * @param string $address
311
- * @param string $name
312
- * @return void
313
- */
314
- function AddBCC($address, $name = "") {
315
- $cur = count($this->bcc);
316
- $this->bcc[$cur][0] = trim($address);
317
- $this->bcc[$cur][1] = $name;
318
- }
319
-
320
- /**
321
- * Adds a "Reply-to" address.
322
- * @param string $address
323
- * @param string $name
324
- * @return void
325
- */
326
- function AddReplyTo($address, $name = "") {
327
- $cur = count($this->ReplyTo);
328
- $this->ReplyTo[$cur][0] = trim($address);
329
- $this->ReplyTo[$cur][1] = $name;
330
- }
331
-
332
-
333
- /////////////////////////////////////////////////
334
- // MAIL SENDING METHODS
335
- /////////////////////////////////////////////////
336
-
337
- /**
338
- * Creates message and assigns Mailer. If the message is
339
- * not sent successfully then it returns false. Use the ErrorInfo
340
- * variable to view description of the error.
341
- * @return bool
342
- */
343
- function Send() {
344
- $header = "";
345
- $body = "";
346
- $result = true;
347
-
348
- if((count($this->to) + count($this->cc) + count($this->bcc)) < 1)
349
- {
350
- $this->SetError($this->Lang("provide_address"));
351
- return false;
352
- }
353
 
354
- // Set whether the message is multipart/alternative
355
- if(!empty($this->AltBody))
356
- $this->ContentType = "multipart/alternative";
357
-
358
- $this->error_count = 0; // reset errors
359
- $this->SetMessageType();
360
- $header .= $this->CreateHeader();
361
- $body = $this->CreateBody();
362
-
363
- if($body == "") { return false; }
364
-
365
- // Choose the mailer
366
- switch($this->Mailer)
367
- {
368
- case "sendmail":
369
- $result = $this->SendmailSend($header, $body);
370
- break;
371
- case "mail":
372
- $result = $this->MailSend($header, $body);
373
- break;
374
- case "smtp":
375
- $result = $this->SmtpSend($header, $body);
376
- break;
377
- default:
378
- $this->SetError($this->Mailer . $this->Lang("mailer_not_supported"));
379
- $result = false;
380
- break;
381
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
382
 
383
- return $result;
384
- }
385
-
386
- /**
387
- * Sends mail using the $Sendmail program.
388
- * @access private
389
- * @return bool
390
- */
391
- function SendmailSend($header, $body) {
392
- if ($this->Sender != "")
393
- $sendmail = sprintf("%s -oi -f %s -t", $this->Sendmail, $this->Sender);
394
- else
395
- $sendmail = sprintf("%s -oi -t", $this->Sendmail);
396
-
397
- if(!@$mail = popen($sendmail, "w"))
398
- {
399
- $this->SetError($this->Lang("execute") . $this->Sendmail);
400
- return false;
401
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
402
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
403
  fputs($mail, $header);
404
  fputs($mail, $body);
405
-
406
- $result = pclose($mail) >> 8 & 0xFF;
407
- if($result != 0)
408
- {
409
- $this->SetError($this->Lang("execute") . $this->Sendmail);
410
- return false;
411
  }
412
-
413
- return true;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
414
  }
 
415
 
416
- /**
417
- * Sends mail using the PHP mail() function.
418
- * @access private
419
- * @return bool
420
- */
421
- function MailSend($header, $body) {
422
- $to = "";
423
- for($i = 0; $i < count($this->to); $i++)
424
- {
425
- if($i != 0) { $to .= ", "; }
426
- $to .= $this->to[$i][0];
 
 
 
427
  }
428
-
429
- if ($this->Sender != "" && strlen(ini_get("safe_mode"))< 1)
430
- {
431
- $old_from = ini_get("sendmail_from");
432
- ini_set("sendmail_from", $this->Sender);
433
- $params = sprintf("-oi -f %s", $this->Sender);
434
- $rt = @mail($to, $this->EncodeHeader($this->Subject), $body,
435
- $header, $params);
 
 
 
 
 
436
  }
437
- else
438
- $rt = @mail($to, $this->EncodeHeader($this->Subject), $body, $header);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
439
 
440
- if (isset($old_from))
441
- ini_set("sendmail_from", $old_from);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
442
 
443
- if(!$rt)
444
- {
445
- $this->SetError($this->Lang("instantiate"));
446
- return false;
447
- }
448
 
449
- return true;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
450
  }
451
 
452
- /**
453
- * Sends mail via SMTP using PhpSMTP (Author:
454
- * Chris Ryan). Returns bool. Returns false if there is a
455
- * bad MAIL FROM, RCPT, or DATA input.
456
- * @access private
457
- * @return bool
458
- */
459
- function SmtpSend($header, $body) {
460
- include_once($this->PluginDir . "class.smtp.php");
461
- $error = "";
462
- $bad_rcpt = array();
463
-
464
- if(!$this->SmtpConnect())
465
- return false;
466
-
467
- $smtp_from = ($this->Sender == "") ? $this->From : $this->Sender;
468
- if(!$this->smtp->Mail($smtp_from))
469
- {
470
- $error = $this->Lang("from_failed") . $smtp_from;
471
- $this->SetError($error);
472
- $this->smtp->Reset();
473
- return false;
474
  }
475
 
476
- // Attempt to send attach all recipients
477
- for($i = 0; $i < count($this->to); $i++)
478
- {
479
- if(!$this->smtp->Recipient($this->to[$i][0]))
480
- $bad_rcpt[] = $this->to[$i][0];
481
- }
482
- for($i = 0; $i < count($this->cc); $i++)
483
- {
484
- if(!$this->smtp->Recipient($this->cc[$i][0]))
485
- $bad_rcpt[] = $this->cc[$i][0];
486
- }
487
- for($i = 0; $i < count($this->bcc); $i++)
488
- {
489
- if(!$this->smtp->Recipient($this->bcc[$i][0]))
490
- $bad_rcpt[] = $this->bcc[$i][0];
491
- }
492
 
493
- if(count($bad_rcpt) > 0) // Create error message
494
- {
495
- for($i = 0; $i < count($bad_rcpt); $i++)
496
- {
497
- if($i != 0) { $error .= ", "; }
498
- $error .= $bad_rcpt[$i];
499
  }
500
- $error = $this->Lang("recipients_failed") . $error;
501
- $this->SetError($error);
502
- $this->smtp->Reset();
503
- return false;
504
- }
505
 
506
- if(!$this->smtp->Data($header . $body))
507
- {
508
- $this->SetError($this->Lang("data_not_accepted"));
509
- $this->smtp->Reset();
510
- return false;
511
- }
512
- if($this->SMTPKeepAlive == true)
513
- $this->smtp->Reset();
514
- else
515
- $this->SmtpClose();
516
 
517
- return true;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
518
  }
519
 
520
- /**
521
- * Initiates a connection to an SMTP server. Returns false if the
522
- * operation failed.
523
- * @access private
524
- * @return bool
525
- */
526
- function SmtpConnect() {
527
- if($this->smtp == NULL) { $this->smtp = new EM_SMTP(); }
528
-
529
- $this->smtp->do_debug = $this->SMTPDebug;
530
- $hosts = explode(";", $this->Host);
531
- $index = 0;
532
- $connection = ($this->smtp->Connected());
533
-
534
- // Retry while there is no connection
535
- while($index < count($hosts) && $connection == false)
536
- {
537
- if(strstr($hosts[$index], ":"))
538
- {
539
- $hostA = explode(':', $hosts[$index]);
540
- if (is_numeric(end($hostA)))
541
- $port = array_pop($hostA);
542
- else
543
- $port = $this->Port;
544
- $host = implode(':', $hostA);
545
  }
546
- else
547
- {
548
- $host = $hosts[$index];
549
- $port = $this->Port;
 
 
 
 
 
 
550
  }
 
 
551
 
552
- if($this->smtp->Connect($host, $port, $this->Timeout))
553
- {
554
- if ($this->Helo != '')
555
- $this->smtp->Hello($this->Helo);
556
- else
557
- $this->smtp->Hello($this->ServerHostname());
558
-
559
- if($this->SMTPAuth)
560
- {
561
- if(!$this->smtp->Authenticate($this->Username,
562
- $this->Password))
563
- {
564
- $this->SetError($this->Lang("authenticate"));
565
- $this->smtp->Reset();
566
- $connection = false;
567
- }
568
- }
569
- $connection = true;
570
- }
571
- $index++;
572
- }
573
- if(!$connection)
574
- $this->SetError($this->Lang("connect_host"));
575
-
576
- return $connection;
577
- }
578
-
579
- /**
580
- * Closes the active SMTP session if one exists.
581
- * @return void
582
- */
583
- function SmtpClose() {
584
- if($this->smtp != NULL)
585
- {
586
- if($this->smtp->Connected())
587
- {
588
- $this->smtp->Quit();
589
- $this->smtp->Close();
590
  }
 
 
 
 
 
 
 
 
 
591
  }
 
 
592
  }
593
 
594
- /**
595
- * Sets the language for all class error messages. Returns false
596
- * if it cannot load the language file. The default language type
597
- * is English.
598
- * @param string $lang_type Type of language (e.g. Portuguese: "br")
599
- * @param string $lang_path Path to the language file directory
600
- * @access public
601
- * @return bool
602
- */
603
- function SetLanguage($lang_type, $lang_path = "language/") {
604
- if(file_exists($lang_path.'phpmailer.lang-'.$lang_type.'.php'))
605
- include($lang_path.'phpmailer.lang-'.$lang_type.'.php');
606
- else if(file_exists($lang_path.'phpmailer.lang-en.php'))
607
- include($lang_path.'phpmailer.lang-en.php');
608
- else
609
- {
610
- $this->SetError("Could not load language file");
611
- return false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
612
  }
613
- $this->language = $PHPMAILER_LANG;
614
-
615
- return true;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
616
  }
617
 
618
- /////////////////////////////////////////////////
619
- // MESSAGE CREATION METHODS
620
- /////////////////////////////////////////////////
621
-
622
- /**
623
- * Creates recipient headers.
624
- * @access private
625
- * @return string
626
- */
627
- function AddrAppend($type, $addr) {
628
- $addr_str = $type . ": ";
629
- $addr_str .= $this->AddrFormat($addr[0]);
630
- if(count($addr) > 1)
631
- {
632
- for($i = 1; $i < count($addr); $i++)
633
- $addr_str .= ", " . $this->AddrFormat($addr[$i]);
634
  }
635
- $addr_str .= $this->LE;
636
-
637
- return $addr_str;
638
- }
639
-
640
- /**
641
- * Formats an address correctly.
642
- * @access private
643
- * @return string
644
- */
645
- function AddrFormat($addr) {
646
- if(empty($addr[1]))
647
- $formatted = $addr[0];
648
- else
649
- {
650
- $formatted = $this->EncodeHeader($addr[1], 'phrase') . " <" .
651
- $addr[0] . ">";
652
  }
 
 
653
 
654
- return $formatted;
655
- }
656
-
657
- /**
658
- * Wraps message for use with mailers that do not
659
- * automatically perform wrapping and for quoted-printable.
660
- * Original written by philippe.
661
- * @access private
662
- * @return string
663
- */
664
- function WrapText($message, $length, $qp_mode = false) {
665
- $soft_break = ($qp_mode) ? sprintf(" =%s", $this->LE) : $this->LE;
666
-
667
- $message = $this->FixEOL($message);
668
- if (substr($message, -1) == $this->LE)
669
- $message = substr($message, 0, -1);
670
-
671
- $line = explode($this->LE, $message);
672
- $message = "";
673
- for ($i=0 ;$i < count($line); $i++)
674
- {
675
- $line_part = explode(" ", $line[$i]);
676
- $buf = "";
677
- for ($e = 0; $e<count($line_part); $e++)
678
- {
679
- $word = $line_part[$e];
680
- if ($qp_mode and (strlen($word) > $length))
681
- {
682
- $space_left = $length - strlen($buf) - 1;
683
- if ($e != 0)
684
- {
685
- if ($space_left > 20)
686
- {
687
- $len = $space_left;
688
- if (substr($word, $len - 1, 1) == "=")
689
- $len--;
690
- elseif (substr($word, $len - 2, 1) == "=")
691
- $len -= 2;
692
- $part = substr($word, 0, $len);
693
- $word = substr($word, $len);
694
- $buf .= " " . $part;
695
- $message .= $buf . sprintf("=%s", $this->LE);
696
- }
697
- else
698
- {
699
- $message .= $buf . $soft_break;
700
- }
701
- $buf = "";
702
- }
703
- while (strlen($word) > 0)
704
- {
705
- $len = $length;
706
- if (substr($word, $len - 1, 1) == "=")
707
- $len--;
708
- elseif (substr($word, $len - 2, 1) == "=")
709
- $len -= 2;
710
- $part = substr($word, 0, $len);
711
- $word = substr($word, $len);
712
-
713
- if (strlen($word) > 0)
714
- $message .= $part . sprintf("=%s", $this->LE);
715
- else
716
- $buf = $part;
717
- }
718
- }
719
- else
720
- {
721
- $buf_o = $buf;
722
- $buf .= ($e == 0) ? $word : (" " . $word);
723
-
724
- if (strlen($buf) > $length and $buf_o != "")
725
- {
726
- $message .= $buf_o . $soft_break;
727
- $buf = $word;
728
- }
729
- }
730
- }
731
- $message .= $buf . $this->LE;
732
- }
733
 
734
- return $message;
735
- }
736
-
737
- /**
738
- * Set the body wrapping.
739
- * @access private
740
- * @return void
741
- */
742
- function SetWordWrap() {
743
- if($this->WordWrap < 1)
744
- return;
745
-
746
- switch($this->message_type)
747
- {
748
- case "alt":
749
- // fall through
750
- case "alt_attachments":
751
- $this->AltBody = $this->WrapText($this->AltBody, $this->WordWrap);
752
- break;
753
- default:
754
- $this->Body = $this->WrapText($this->Body, $this->WordWrap);
755
- break;
756
- }
757
  }
758
 
759
- /**
760
- * Assembles message header.
761
- * @access private
762
- * @return string
763
- */
764
- function CreateHeader() {
765
- $result = "";
766
-
767
- // Set the boundaries
768
- $uniq_id = md5(uniqid(time()));
769
- $this->boundary[1] = "b1_" . $uniq_id;
770
- $this->boundary[2] = "b2_" . $uniq_id;
771
-
772
- $result .= $this->HeaderLine("Date", $this->RFCDate());
773
- if($this->Sender == "")
774
- $result .= $this->HeaderLine("Return-Path", trim($this->From));
775
- else
776
- $result .= $this->HeaderLine("Return-Path", trim($this->Sender));
777
-
778
- // To be created automatically by mail()
779
- if($this->Mailer != "mail")
780
- {
781
- if(count($this->to) > 0)
782
- $result .= $this->AddrAppend("To", $this->to);
783
- else if (count($this->cc) == 0)
784
- $result .= $this->HeaderLine("To", "undisclosed-recipients:;");
785
- if(count($this->cc) > 0)
786
- $result .= $this->AddrAppend("Cc", $this->cc);
787
- }
788
 
789
- $from = array();
790
- $from[0][0] = trim($this->From);
791
- $from[0][1] = $this->FromName;
792
- $result .= $this->AddrAppend("From", $from);
793
-
794
- // sendmail and mail() extract Bcc from the header before sending
795
- if((($this->Mailer == "sendmail") || ($this->Mailer == "mail")) && (count($this->bcc) > 0))
796
- $result .= $this->AddrAppend("Bcc", $this->bcc);
797
-
798
- if(count($this->ReplyTo) > 0)
799
- $result .= $this->AddrAppend("Reply-to", $this->ReplyTo);
800
-
801
- // mail() sets the subject itself
802
- if($this->Mailer != "mail")
803
- $result .= $this->HeaderLine("Subject", $this->EncodeHeader(trim($this->Subject)));
804
-
805
- $result .= sprintf("Message-ID: <%s@%s>%s", $uniq_id, $this->ServerHostname(), $this->LE);
806
- $result .= $this->HeaderLine("X-Priority", $this->Priority);
807
- $result .= $this->HeaderLine("X-Mailer", "PHPMailer [version " . $this->Version . "]");
808
-
809
- if($this->ConfirmReadingTo != "")
810
- {
811
- $result .= $this->HeaderLine("Disposition-Notification-To",
812
- "<" . trim($this->ConfirmReadingTo) . ">");
813
- }
814
 
815
- // Add custom headers
816
- for($index = 0; $index < count($this->CustomHeader); $index++)
817
- {
818
- $result .= $this->HeaderLine(trim($this->CustomHeader[$index][0]),
819
- $this->EncodeHeader(trim($this->CustomHeader[$index][1])));
820
- }
821
- $result .= $this->HeaderLine("MIME-Version", "1.0");
822
-
823
- switch($this->message_type)
824
- {
825
- case "plain":
826
- $result .= $this->HeaderLine("Content-Transfer-Encoding", $this->Encoding);
827
- $result .= sprintf("Content-Type: %s; charset=\"%s\"",
828
- $this->ContentType, $this->CharSet);
829
- break;
830
- case "attachments":
831
- // fall through
832
- case "alt_attachments":
833
- if($this->InlineImageExists())
834
- {
835
- $result .= sprintf("Content-Type: %s;%s\ttype=\"text/html\";%s\tboundary=\"%s\"%s",
836
- "multipart/related", $this->LE, $this->LE,
837
- $this->boundary[1], $this->LE);
838
- }
839
- else
840
- {
841
- $result .= $this->HeaderLine("Content-Type", "multipart/mixed;");
842
- $result .= $this->TextLine("\tboundary=\"" . $this->boundary[1] . '"');
843
- }
844
- break;
845
- case "alt":
846
- $result .= $this->HeaderLine("Content-Type", "multipart/alternative;");
847
- $result .= $this->TextLine("\tboundary=\"" . $this->boundary[1] . '"');
848
- break;
849
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
850
 
851
- if($this->Mailer != "mail")
852
- $result .= $this->LE.$this->LE;
853
-
854
- return $result;
855
- }
856
-
857
- /**
858
- * Assembles the message body. Returns an empty string on failure.
859
- * @access private
860
- * @return string
861
- */
862
- function CreateBody() {
863
- $result = "";
864
-
865
- $this->SetWordWrap();
866
-
867
- switch($this->message_type)
868
- {
869
- case "alt":
870
- $result .= $this->GetBoundary($this->boundary[1], "",
871
- "text/plain", "");
872
- $result .= $this->EncodeString($this->AltBody, $this->Encoding);
873
- $result .= $this->LE.$this->LE;
874
- $result .= $this->GetBoundary($this->boundary[1], "",
875
- "text/html", "");
876
-
877
- $result .= $this->EncodeString($this->Body, $this->Encoding);
878
- $result .= $this->LE.$this->LE;
879
-
880
- $result .= $this->EndBoundary($this->boundary[1]);
881
- break;
882
- case "plain":
883
- $result .= $this->EncodeString($this->Body, $this->Encoding);
884
- break;
885
- case "attachments":
886
- $result .= $this->GetBoundary($this->boundary[1], "", "", "");
887
- $result .= $this->EncodeString($this->Body, $this->Encoding);
888
- $result .= $this->LE;
889
-
890
- $result .= $this->AttachAll();
891
- break;
892
- case "alt_attachments":
893
- $result .= sprintf("--%s%s", $this->boundary[1], $this->LE);
894
- $result .= sprintf("Content-Type: %s;%s" .
895
- "\tboundary=\"%s\"%s",
896
- "multipart/alternative", $this->LE,
897
- $this->boundary[2], $this->LE.$this->LE);
898
-
899
- // Create text body
900
- $result .= $this->GetBoundary($this->boundary[2], "",
901
- "text/plain", "") . $this->LE;
902
-
903
- $result .= $this->EncodeString($this->AltBody, $this->Encoding);
904
- $result .= $this->LE.$this->LE;
905
-
906
- // Create the HTML body
907
- $result .= $this->GetBoundary($this->boundary[2], "",
908
- "text/html", "") . $this->LE;
909
-
910
- $result .= $this->EncodeString($this->Body, $this->Encoding);
911
- $result .= $this->LE.$this->LE;
912
-
913
- $result .= $this->EndBoundary($this->boundary[2]);
914
-
915
- $result .= $this->AttachAll();
916
- break;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
917
  }
918
- if($this->IsError())
919
- $result = "";
920
-
921
- return $result;
922
- }
923
-
924
- /**
925
- * Returns the start of a message boundary.
926
- * @access private
927
- */
928
- function GetBoundary($boundary, $charSet, $contentType, $encoding) {
929
- $result = "";
930
- if($charSet == "") { $charSet = $this->CharSet; }
931
- if($contentType == "") { $contentType = $this->ContentType; }
932
- if($encoding == "") { $encoding = $this->Encoding; }
933
-
934
- $result .= $this->TextLine("--" . $boundary);
935
- $result .= sprintf("Content-Type: %s; charset = \"%s\"",
936
- $contentType, $charSet);
937
- $result .= $this->LE;
938
- $result .= $this->HeaderLine("Content-Transfer-Encoding", $encoding);
939
- $result .= $this->LE;
940
-
941
- return $result;
942
- }
943
-
944
- /**
945
- * Returns the end of a message boundary.
946
- * @access private
947
- */
948
- function EndBoundary($boundary) {
949
- return $this->LE . "--" . $boundary . "--" . $this->LE;
950
- }
951
-
952
- /**
953
- * Sets the message type.
954
- * @access private
955
- * @return void
956
- */
957
- function SetMessageType() {
958
- if(count($this->attachment) < 1 && strlen($this->AltBody) < 1)
959
- $this->message_type = "plain";
960
- else
961
- {
962
- if(count($this->attachment) > 0)
963
- $this->message_type = "attachments";
964
- if(strlen($this->AltBody) > 0 && count($this->attachment) < 1)
965
- $this->message_type = "alt";
966
- if(strlen($this->AltBody) > 0 && count($this->attachment) > 0)
967
- $this->message_type = "alt_attachments";
968
  }
 
969
  }
970
 
971
- /**
972
- * Returns a formatted header line.
973
- * @access private
974
- * @return string
975
- */
976
- function HeaderLine($name, $value) {
977
- return $name . ": " . $value . $this->LE;
978
- }
979
-
980
- /**
981
- * Returns a formatted mail line.
982
- * @access private
983
- * @return string
984
- */
985
- function TextLine($value) {
986
- return $value . $this->LE;
987
- }
988
-
989
- /////////////////////////////////////////////////
990
- // ATTACHMENT METHODS
991
- /////////////////////////////////////////////////
992
-
993
- /**
994
- * Adds an attachment from a path on the filesystem.
995
- * Returns false if the file could not be found
996
- * or accessed.
997
- * @param string $path Path to the attachment.
998
- * @param string $name Overrides the attachment name.
999
- * @param string $encoding File encoding (see $Encoding).
1000
- * @param string $type File extension (MIME) type.
1001
- * @return bool
1002
- */
1003
- function AddAttachment($path, $name = "", $encoding = "base64",
1004
- $type = "application/octet-stream") {
1005
- if(!@is_file($path))
1006
- {
1007
- $this->SetError($this->Lang("file_access") . $path);
1008
- return false;
1009
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1010
 
1011
- $filename = basename($path);
1012
- if($name == "")
1013
- $name = $filename;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1014
 
1015
- $cur = count($this->attachment);
1016
- $this->attachment[$cur][0] = $path;
1017
- $this->attachment[$cur][1] = $filename;
1018
- $this->attachment[$cur][2] = $name;
1019
- $this->attachment[$cur][3] = $encoding;
1020
- $this->attachment[$cur][4] = $type;
1021
- $this->attachment[$cur][5] = false; // isStringAttachment
1022
- $this->attachment[$cur][6] = "attachment";
1023
- $this->attachment[$cur][7] = 0;
 
 
 
 
 
 
 
 
 
 
1024
 
1025
- return true;
1026
- }
1027
 
1028
- /**
1029
- * Attaches all fs, string, and binary attachments to the message.
1030
- * Returns an empty string on failure.
1031
- * @access private
1032
- * @return string
1033
- */
1034
- function AttachAll() {
1035
- // Return text of body
1036
- $mime = array();
1037
-
1038
- // Add all attachments
1039
- for($i = 0; $i < count($this->attachment); $i++)
1040
- {
1041
- // Check for string attachment
1042
- $bString = $this->attachment[$i][5];
1043
- if ($bString)
1044
- $string = $this->attachment[$i][0];
1045
- else
1046
- $path = $this->attachment[$i][0];
1047
-
1048
- $filename = $this->attachment[$i][1];
1049
- $name = $this->attachment[$i][2];
1050
- $encoding = $this->attachment[$i][3];
1051
- $type = $this->attachment[$i][4];
1052
- $disposition = $this->attachment[$i][6];
1053
- $cid = $this->attachment[$i][7];
1054
-
1055
- $mime[] = sprintf("--%s%s", $this->boundary[1], $this->LE);
1056
- $mime[] = sprintf("Content-Type: %s; name=\"%s\"%s", $type, $name, $this->LE);
1057
- $mime[] = sprintf("Content-Transfer-Encoding: %s%s", $encoding, $this->LE);
1058
-
1059
- if($disposition == "inline")
1060
- $mime[] = sprintf("Content-ID: <%s>%s", $cid, $this->LE);
1061
-
1062
- $mime[] = sprintf("Content-Disposition: %s; filename=\"%s\"%s",
1063
- $disposition, $name, $this->LE.$this->LE);
1064
-
1065
- // Encode as string attachment
1066
- if($bString)
1067
- {
1068
- $mime[] = $this->EncodeString($string, $encoding);
1069
- if($this->IsError()) { return ""; }
1070
- $mime[] = $this->LE.$this->LE;
1071
- }
1072
- else
1073
- {
1074
- $mime[] = $this->EncodeFile($path, $encoding);
1075
- if($this->IsError()) { return ""; }
1076
- $mime[] = $this->LE.$this->LE;
1077
- }
1078
  }
 
 
1079
 
1080
- $mime[] = sprintf("--%s--%s", $this->boundary[1], $this->LE);
1081
-
1082
- return join("", $mime);
1083
- }
1084
-
1085
- /**
1086
- * Encodes attachment in requested format. Returns an
1087
- * empty string on failure.
1088
- * @access private
1089
- * @return string
1090
- */
1091
- function EncodeFile ($path, $encoding = "base64") {
1092
- if(!@$fd = fopen($path, "rb"))
1093
- {
1094
- $this->SetError($this->Lang("file_open") . $path);
1095
- return "";
 
 
 
 
 
 
1096
  }
 
 
1097
  $magic_quotes = get_magic_quotes_runtime();
1098
  set_magic_quotes_runtime(0);
1099
- $file_buffer = fread($fd, filesize($path));
1100
- $file_buffer = $this->EncodeString($file_buffer, $encoding);
1101
- fclose($fd);
 
1102
  set_magic_quotes_runtime($magic_quotes);
1103
-
1104
- return $file_buffer;
1105
- }
1106
-
1107
- /**
1108
- * Encodes string to requested format. Returns an
1109
- * empty string on failure.
1110
- * @access private
1111
- * @return string
1112
- */
1113
- function EncodeString ($str, $encoding = "base64") {
1114
- $encoded = "";
1115
- switch(strtolower($encoding)) {
1116
- case "base64":
1117
- // chunk_split is found in PHP >= 3.0.6
1118
- $encoded = chunk_split(base64_encode($str), 76, $this->LE);
1119
- break;
1120
- case "7bit":
1121
- case "8bit":
1122
- $encoded = $this->FixEOL($str);
1123
- if (substr($encoded, -(strlen($this->LE))) != $this->LE)
1124
- $encoded .= $this->LE;
1125
- break;
1126
- case "binary":
1127
- $encoded = $str;
1128
- break;
1129
- case "quoted-printable":
1130
- $encoded = $this->EncodeQP($str);
1131
- break;
1132
- default:
1133
- $this->SetError($this->Lang("encoding") . $encoding);
1134
- break;
1135
- }
1136
- return $encoded;
1137
- }
1138
-
1139
- /**
1140
- * Encode a header string to best of Q, B, quoted or none.
1141
- * @access private
1142
- * @return string
1143
- */
1144
- function EncodeHeader ($str, $position = 'text') {
1145
- $x = 0;
1146
-
1147
- switch (strtolower($position)) {
1148
- case 'phrase':
1149
- if (!preg_match('/[\200-\377]/', $str)) {
1150
- // Can't use addslashes as we don't know what value has magic_quotes_sybase.
1151
- $encoded = addcslashes($str, "\0..\37\177\\\"");
1152
-
1153
- if (($str == $encoded) && !preg_match('/[^A-Za-z0-9!#$%&\'*+\/=?^_`{|}~ -]/', $str))
1154
- return ($encoded);
1155
- else
1156
- return ("\"$encoded\"");
1157
- }
1158
- $x = preg_match_all('/[^\040\041\043-\133\135-\176]/', $str, $matches);
1159
- break;
1160
- case 'comment':
1161
- $x = preg_match_all('/[()"]/', $str, $matches);
1162
- // Fall-through
1163
- case 'text':
1164
- default:
1165
- $x += preg_match_all('/[\000-\010\013\014\016-\037\177-\377]/', $str, $matches);
1166
- break;
1167
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1168
 
1169
- if ($x == 0)
1170
- return ($str);
 
1171
 
1172
- $maxlen = 75 - 7 - strlen($this->CharSet);
1173
- // Try to select the encoding which should produce the shortest output
1174
- if (strlen($str)/3 < $x) {
1175
- $encoding = 'B';
 
 
 
 
 
1176
  $encoded = base64_encode($str);
1177
  $maxlen -= $maxlen % 4;
1178
  $encoded = trim(chunk_split($encoded, $maxlen, "\n"));
1179
- } else {
1180
- $encoding = 'Q';
1181
- $encoded = $this->EncodeQ($str, $position);
1182
- $encoded = $this->WrapText($encoded, $maxlen, true);
1183
- $encoded = str_replace("=".$this->LE, "\n", trim($encoded));
1184
  }
 
 
 
 
 
 
1185
 
1186
- $encoded = preg_replace('/^(.*)$/m', " =?".$this->CharSet."?$encoding?\\1?=", $encoded);
1187
- $encoded = trim(str_replace("\n", $this->LE, $encoded));
1188
-
1189
- return $encoded;
1190
- }
1191
-
1192
- /**
1193
- * Encode string to quoted-printable.
1194
- * @access private
1195
- * @return string
1196
- */
1197
- function EncodeQP ($str) {
1198
- $encoded = $this->FixEOL($str);
1199
- if (substr($encoded, -(strlen($this->LE))) != $this->LE)
1200
- $encoded .= $this->LE;
1201
-
1202
- // Replace every high ascii, control and = characters
1203
- $encoded = preg_replace('/([\000-\010\013\014\016-\037\075\177-\377])/e',
1204
- "'='.sprintf('%02X', ord('\\1'))", $encoded);
1205
- // Replace every spaces and tabs when it's the last character on a line
1206
- $encoded = preg_replace("/([\011\040])".$this->LE."/e",
1207
- "'='.sprintf('%02X', ord('\\1')).'".$this->LE."'", $encoded);
1208
-
1209
- // Maximum line length of 76 characters before CRLF (74 + space + '=')
1210
- $encoded = $this->WrapText($encoded, 74, true);
1211
-
1212
- return $encoded;
1213
- }
1214
-
1215
- /**
1216
- * Encode string to q encoding.
1217
- * @access private
1218
- * @return string
1219
- */
1220
- function EncodeQ ($str, $position = "text") {
1221
- // There should not be any EOL in the string
1222
- $encoded = preg_replace("[\r\n]", "", $str);
1223
-
1224
- switch (strtolower($position)) {
1225
- case "phrase":
1226
- $encoded = preg_replace("/([^A-Za-z0-9!*+\/ -])/e", "'='.sprintf('%02X', ord('\\1'))", $encoded);
1227
- break;
1228
- case "comment":
1229
- $encoded = preg_replace("/([\(\)\"])/e", "'='.sprintf('%02X', ord('\\1'))", $encoded);
1230
- case "text":
1231
- default:
1232
- // Replace every high ascii, control =, ? and _ characters
1233
- $encoded = preg_replace('/([\000-\011\013\014\016-\037\075\077\137\177-\377])/e',
1234
- "'='.sprintf('%02X', ord('\\1'))", $encoded);
1235
- break;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1236
  }
1237
-
1238
- // Replace every spaces to _ (more readable than =20)
1239
- $encoded = str_replace(" ", "_", $encoded);
1240
-
1241
- return $encoded;
1242
- }
1243
-
1244
- /**
1245
- * Adds a string or binary attachment (non-filesystem) to the list.
1246
- * This method can be used to attach ascii or binary data,
1247
- * such as a BLOB record from a database.
1248
- * @param string $string String attachment data.
1249
- * @param string $filename Name of the attachment.
1250
- * @param string $encoding File encoding (see $Encoding).
1251
- * @param string $type File extension (MIME) type.
1252
- * @return void
1253
- */
1254
- function AddStringAttachment($string, $filename, $encoding = "base64",
1255
- $type = "application/octet-stream") {
1256
- // Append to $attachment array
1257
- $cur = count($this->attachment);
1258
- $this->attachment[$cur][0] = $string;
1259
- $this->attachment[$cur][1] = $filename;
1260
- $this->attachment[$cur][2] = $filename;
1261
- $this->attachment[$cur][3] = $encoding;
1262
- $this->attachment[$cur][4] = $type;
1263
- $this->attachment[$cur][5] = true; // isString
1264
- $this->attachment[$cur][6] = "attachment";
1265
- $this->attachment[$cur][7] = 0;
1266
- }
1267
-
1268
- /**
1269
- * Adds an embedded attachment. This can include images, sounds, and
1270
- * just about any other document. Make sure to set the $type to an
1271
- * image type. For JPEG images use "image/jpeg" and for GIF images
1272
- * use "image/gif".
1273
- * @param string $path Path to the attachment.
1274
- * @param string $cid Content ID of the attachment. Use this to identify
1275
- * the Id for accessing the image in an HTML form.
1276
- * @param string $name Overrides the attachment name.
1277
- * @param string $encoding File encoding (see $Encoding).
1278
- * @param string $type File extension (MIME) type.
1279
- * @return bool
1280
- */
1281
- function AddEmbeddedImage($path, $cid, $name = "", $encoding = "base64",
1282
- $type = "application/octet-stream") {
1283
-
1284
- if(!@is_file($path))
1285
- {
1286
- $this->SetError($this->Lang("file_access") . $path);
1287
- return false;
1288
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1289
 
1290
- $filename = basename($path);
1291
- if($name == "")
1292
- $name = $filename;
1293
-
1294
- // Append to $attachment array
1295
- $cur = count($this->attachment);
1296
- $this->attachment[$cur][0] = $path;
1297
- $this->attachment[$cur][1] = $filename;
1298
- $this->attachment[$cur][2] = $name;
1299
- $this->attachment[$cur][3] = $encoding;
1300
- $this->attachment[$cur][4] = $type;
1301
- $this->attachment[$cur][5] = false; // isStringAttachment
1302
- $this->attachment[$cur][6] = "inline";
1303
- $this->attachment[$cur][7] = $cid;
1304
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1305
  return true;
 
1306
  }
1307
-
1308
- /**
1309
- * Returns true if an inline attachment is present.
1310
- * @access private
1311
- * @return bool
1312
- */
1313
- function InlineImageExists() {
1314
- $result = false;
1315
- for($i = 0; $i < count($this->attachment); $i++)
1316
- {
1317
- if($this->attachment[$i][6] == "inline")
1318
- {
1319
- $result = true;
1320
- break;
1321
- }
1322
- }
1323
-
1324
- return $result;
1325
- }
1326
-
1327
- /////////////////////////////////////////////////
1328
- // MESSAGE RESET METHODS
1329
- /////////////////////////////////////////////////
1330
-
1331
- /**
1332
- * Clears all recipients assigned in the TO array. Returns void.
1333
- * @return void
1334
- */
1335
- function ClearAddresses() {
1336
- $this->to = array();
1337
- }
1338
-
1339
- /**
1340
- * Clears all recipients assigned in the CC array. Returns void.
1341
- * @return void
1342
- */
1343
- function ClearCCs() {
1344
- $this->cc = array();
1345
- }
1346
-
1347
- /**
1348
- * Clears all recipients assigned in the BCC array. Returns void.
1349
- * @return void
1350
- */
1351
- function ClearBCCs() {
1352
- $this->bcc = array();
1353
- }
1354
-
1355
- /**
1356
- * Clears all recipients assigned in the ReplyTo array. Returns void.
1357
- * @return void
1358
- */
1359
- function ClearReplyTos() {
1360
- $this->ReplyTo = array();
1361
- }
1362
-
1363
- /**
1364
- * Clears all recipients assigned in the TO, CC and BCC
1365
- * array. Returns void.
1366
- * @return void
1367
- */
1368
- function ClearAllRecipients() {
1369
- $this->to = array();
1370
- $this->cc = array();
1371
- $this->bcc = array();
1372
- }
1373
-
1374
- /**
1375
- * Clears all previously set filesystem, string, and binary
1376
- * attachments. Returns void.
1377
- * @return void
1378
- */
1379
- function ClearAttachments() {
1380
- $this->attachment = array();
1381
- }
1382
-
1383
- /**
1384
- * Clears all custom headers. Returns void.
1385
- * @return void
1386
- */
1387
- function ClearCustomHeaders() {
1388
- $this->CustomHeader = array();
1389
- }
1390
-
1391
-
1392
- /////////////////////////////////////////////////
1393
- // MISCELLANEOUS METHODS
1394
- /////////////////////////////////////////////////
1395
-
1396
- /**
1397
- * Adds the error message to the error container.
1398
- * Returns void.
1399
- * @access private
1400
- * @return void
1401
- */
1402
- function SetError($msg) {
1403
- $this->error_count++;
1404
- $this->ErrorInfo = $msg;
1405
- }
1406
-
1407
- /**
1408
- * Returns the proper RFC 822 formatted date.
1409
- * @access private
1410
- * @return string
1411
- */
1412
- function RFCDate() {
1413
- $tz = date("Z");
1414
- $tzs = ($tz < 0) ? "-" : "+";
1415
- $tz = abs($tz);
1416
- $tz = ($tz/3600)*100 + ($tz%3600)/60;
1417
- $result = sprintf("%s %s%04d", date("D, j M Y H:i:s"), $tzs, $tz);
1418
-
1419
- return $result;
1420
- }
1421
-
1422
- /**
1423
- * Returns the appropriate server variable. Should work with both
1424
- * PHP 4.1.0+ as well as older versions. Returns an empty string
1425
- * if nothing is found.
1426
- * @access private
1427
- * @return mixed
1428
- */
1429
- function ServerVar($varName) {
1430
- global $HTTP_SERVER_VARS;
1431
- global $HTTP_ENV_VARS;
1432
-
1433
- if(!isset($_SERVER))
1434
- {
1435
- $_SERVER = $HTTP_SERVER_VARS;
1436
- if(!isset($_SERVER["REMOTE_ADDR"]))
1437
- $_SERVER = $HTTP_ENV_VARS; // must be Apache
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1438
  }
1439
-
1440
- if(isset($_SERVER[$varName]))
1441
- return $_SERVER[$varName];
1442
- else
1443
- return "";
1444
- }
1445
-
1446
- /**
1447
- * Returns the server hostname or 'localhost.localdomain' if unknown.
1448
- * @access private
1449
- * @return string
1450
- */
1451
- function ServerHostname() {
1452
- if ($this->Hostname != "")
1453
- $result = $this->Hostname;
1454
- elseif ($this->ServerVar('SERVER_NAME') != "")
1455
- $result = $this->ServerVar('SERVER_NAME');
1456
- else
1457
- $result = "localhost.localdomain";
1458
-
1459
- return $result;
1460
- }
1461
-
1462
- /**
1463
- * Returns a message in the appropriate language.
1464
- * @access private
1465
- * @return string
1466
- */
1467
- function Lang($key) {
1468
- if(count($this->language) < 1)
1469
- $this->SetLanguage("en"); // set the default language
1470
-
1471
- if(isset($this->language[$key]))
1472
- return $this->language[$key];
1473
- else
1474
- return "Language string failed to load: " . $key;
1475
- }
1476
-
1477
- /**
1478
- * Returns true if an error occurred.
1479
- * @return bool
1480
- */
1481
- function IsError() {
1482
- return ($this->error_count > 0);
1483
- }
1484
-
1485
- /**
1486
- * Changes every end of line from CR or LF to CRLF.
1487
- * @access private
1488
- * @return string
1489
- */
1490
- function FixEOL($str) {
1491
- $str = str_replace("\r\n", "\n", $str);
1492
- $str = str_replace("\r", "\n", $str);
1493
- $str = str_replace("\n", $this->LE, $str);
1494
- return $str;
1495
- }
1496
-
1497
- /**
1498
- * Adds a custom header.
1499
- * @return void
1500
- */
1501
- function AddCustomHeader($custom_header) {
1502
- $this->CustomHeader[] = explode(":", $custom_header, 2);
1503
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1504
  }
1505
 
 
 
 
 
 
 
1506
  ?>
1
  <?php
2
+ /*~ class.phpmailer.php
3
+ .---------------------------------------------------------------------------.
4
+ | Software: PHPMailer - PHP email class |
5
+ | Version: 5.2 |
6
+ | Site: https://code.google.com/a/apache-extras.org/p/phpmailer/ |
7
+ | ------------------------------------------------------------------------- |
8
+ | Admin: Jim Jagielski (project admininistrator) |
9
+ | Authors: Andy Prevost (codeworxtech) codeworxtech@users.sourceforge.net |
10
+ | : Marcus Bointon (coolbru) coolbru@users.sourceforge.net |
11
+ | : Jim Jagielski (jimjag) jimjag@gmail.com |
12
+ | Founder: Brent R. Matzelle (original founder) |
13
+ | Copyright (c) 2010-2011, Jim Jagielski. All Rights Reserved. |
14
+ | Copyright (c) 2004-2009, Andy Prevost. All Rights Reserved. |
15
+ | Copyright (c) 2001-2003, Brent R. Matzelle |
16
+ | ------------------------------------------------------------------------- |
17
+ | License: Distributed under the Lesser General Public License (LGPL) |
18
+ | http://www.gnu.org/copyleft/lesser.html |
19
+ | This program is distributed in the hope that it will be useful - WITHOUT |
20
+ | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
21
+ | FITNESS FOR A PARTICULAR PURPOSE. |
22
+ '---------------------------------------------------------------------------'
23
+ */
24
 
25
  /**
26
  * PHPMailer - PHP email transport class
27
+ * NOTE: Requires PHP version 5 or later
28
  * @package PHPMailer
29
+ * @author Andy Prevost
30
+ * @author Marcus Bointon
31
+ * @author Jim Jagielski
32
+ * @copyright 2010 - 2011 Jim Jagielski
33
+ * @copyright 2004 - 2009 Andy Prevost
34
+ * @version $Id: class.phpmailer.php 450 2010-06-23 16:46:33Z coolbru $
35
+ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
36
  */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37
 
38
+ if (version_compare(PHP_VERSION, '5.0.0', '<') ) exit("Sorry, this version of PHPMailer will only run on PHP version 5 or greater!\n");
39
+
40
+ class EM_PHPMailer {
41
+
42
+ /////////////////////////////////////////////////
43
+ // PROPERTIES, PUBLIC
44
+ /////////////////////////////////////////////////
45
+
46
+ /**
47
+ * Email priority (1 = High, 3 = Normal, 5 = low).
48
+ * @var int
49
+ */
50
+ public $Priority = 3;
51
+
52
+ /**
53
+ * Sets the CharSet of the message.
54
+ * @var string
55
+ */
56
+ public $CharSet = 'iso-8859-1';
57
+
58
+ /**
59
+ * Sets the Content-type of the message.
60
+ * @var string
61
+ */
62
+ public $ContentType = 'text/plain';
63
+
64
+ /**
65
+ * Sets the Encoding of the message. Options for this are
66
+ * "8bit", "7bit", "binary", "base64", and "quoted-printable".
67
+ * @var string
68
+ */
69
+ public $Encoding = '8bit';
70
+
71
+ /**
72
+ * Holds the most recent mailer error message.
73
+ * @var string
74
+ */
75
+ public $ErrorInfo = '';
76
+
77
+ /**
78
+ * Sets the From email address for the message.
79
+ * @var string
80
+ */
81
+ public $From = 'root@localhost';
82
+
83
+ /**
84
+ * Sets the From name of the message.
85
+ * @var string
86
+ */
87
+ public $FromName = 'Root User';
88
+
89
+ /**
90
+ * Sets the Sender email (Return-Path) of the message. If not empty,
91
+ * will be sent via -f to sendmail or as 'MAIL FROM' in smtp mode.
92
+ * @var string
93
+ */
94
+ public $Sender = '';
95
+
96
+ /**
97
+ * Sets the Subject of the message.
98
+ * @var string
99
+ */
100
+ public $Subject = '';
101
+
102
+ /**
103
+ * Sets the Body of the message. This can be either an HTML or text body.
104
+ * If HTML then run IsHTML(true).
105
+ * @var string
106
+ */
107
+ public $Body = '';
108
+
109
+ /**
110
+ * Sets the text-only body of the message. This automatically sets the
111
+ * email to multipart/alternative. This body can be read by mail
112
+ * clients that do not have HTML email capability such as mutt. Clients
113
+ * that can read HTML will view the normal Body.
114
+ * @var string
115
+ */
116
+ public $AltBody = '';
117
+
118
+ /**
119
+ * Stores the complete compiled MIME message body.
120
+ * @var string
121
+ * @access protected
122
+ */
123
+ protected $MIMEBody = '';
124
+
125
+ /**
126
+ * Stores the complete compiled MIME message headers.
127
+ * @var string
128
+ * @access protected
129
+ */
130
+ protected $MIMEHeader = '';
131
+
132
+ /**
133
+ * Sets word wrapping on the body of the message to a given number of
134
+ * characters.
135
+ * @var int
136
+ */
137
+ public $WordWrap = 0;
138
+
139
+ /**
140
+ * Method to send mail: ("mail", "sendmail", or "smtp").
141
+ * @var string
142
+ */
143
+ public $Mailer = 'mail';
144
+
145
+ /**
146
+ * Sets the path of the sendmail program.
147
+ * @var string
148
+ */
149
+ public $Sendmail = '/usr/sbin/sendmail';
150
+
151
+ /**
152
+ * Path to PHPMailer plugins. Useful if the SMTP class
153
+ * is in a different directory than the PHP include path.
154
+ * @var string
155
+ */
156
+ public $PluginDir = '';
157
+
158
+ /**
159
+ * Sets the email address that a reading confirmation will be sent.
160
+ * @var string
161
+ */
162
+ public $ConfirmReadingTo = '';
163
+
164
+ /**
165
+ * Sets the hostname to use in Message-Id and Received headers
166
+ * and as default HELO string. If empty, the value returned
167
+ * by SERVER_NAME is used or 'localhost.localdomain'.
168
+ * @var string
169
+ */
170
+ public $Hostname = '';
171
+
172
+ /**
173
+ * Sets the message ID to be used in the Message-Id header.
174
+ * If empty, a unique id will be generated.
175
+ * @var string
176
+ */
177
+ public $MessageID = '';
178
+
179
+ /////////////////////////////////////////////////
180
+ // PROPERTIES FOR SMTP
181
+ /////////////////////////////////////////////////
182
+
183
+ /**
184
+ * Sets the SMTP hosts. All hosts must be separated by a
185
+ * semicolon. You can also specify a different port
186
+ * for each host by using this format: [hostname:port]
187
+ * (e.g. "smtp1.example.com:25;smtp2.example.com").
188
+ * Hosts will be tried in order.
189
+ * @var string
190
+ */
191
+ public $Host = 'localhost';
192
+
193
+ /**
194
+ * Sets the default SMTP server port.
195
+ * @var int
196
+ */
197
+ public $Port = 25;
198
+
199
+ /**
200
+ * Sets the SMTP HELO of the message (Default is $Hostname).
201
+ * @var string
202
+ */
203
+ public $Helo = '';
204
+
205
+ /**
206
+ * Sets connection prefix.
207
+ * Options are "", "ssl" or "tls"
208
+ * @var string
209
+ */
210
+ public $SMTPSecure = '';
211
+
212
+ /**
213
+ * Sets SMTP authentication. Utilizes the Username and Password variables.
214
+ * @var bool
215
+ */
216
+ public $SMTPAuth = false;
217
+
218
+ /**
219
+ * Sets SMTP username.
220
+ * @var string
221
+ */
222
+ public $Username = '';
223
+
224
+ /**
225
+ * Sets SMTP password.
226
+ * @var string
227
+ */
228
+ public $Password = '';
229
+
230
+ /**
231
+ * Sets the SMTP server timeout in seconds.
232
+ * This function will not work with the win32 version.
233
+ * @var int
234
+ */
235
+ public $Timeout = 10;
236
+
237
+ /**
238
+ * Sets SMTP class debugging on or off.
239
+ * @var bool
240
+ */
241
+ public $SMTPDebug = false;
242
+
243
+ /**
244
+ * Prevents the SMTP connection from being closed after each mail
245
+ * sending. If this is set to true then to close the connection
246
+ * requires an explicit call to SmtpClose().
247
+ * @var bool
248
+ */
249
+ public $SMTPKeepAlive = false;
250
+
251
+ /**
252
+ * Provides the ability to have the TO field process individual
253
+ * emails, instead of sending to entire TO addresses
254
+ * @var bool
255
+ */
256
+ public $SingleTo = false;
257
+
258
+ /**
259
+ * If SingleTo is true, this provides the array to hold the email addresses
260
+ * @var bool
261
+ */
262
+ public $SingleToArray = array();
263
+
264
+ /**
265
+ * Provides the ability to change the line ending
266
+ * @var string
267
+ */
268
+ public $LE = "\n";
269
+
270
+ /**
271
+ * Used with DKIM DNS Resource Record
272
+ * @var string
273
+ */
274
+ public $DKIM_selector = 'phpmailer';
275
+
276
+ /**
277
+ * Used with DKIM DNS Resource Record
278
+ * optional, in format of email address 'you@yourdomain.com'
279
+ * @var string
280
+ */
281
+ public $DKIM_identity = '';
282
+
283
+ /**
284
+ * Used with DKIM DNS Resource Record
285
+ * @var string
286
+ */
287
+ public $DKIM_passphrase = '';
288
+
289
+ /**
290
+ * Used with DKIM DNS Resource Record
291
+ * optional, in format of email address 'you@yourdomain.com'
292
+ * @var string
293
+ */
294
+ public $DKIM_domain = '';
295
+
296
+ /**
297
+ * Used with DKIM DNS Resource Record
298
+ * optional, in format of email address 'you@yourdomain.com'
299
+ * @var string
300
+ */
301
+ public $DKIM_private = '';
302
+
303
+ /**
304
+ * Callback Action function name
305
+ * the function that handles the result of the send email action. Parameters:
306
+ * bool $result result of the send action
307
+ * string $to email address of the recipient
308
+ * string $cc cc email addresses
309
+ * string $bcc bcc email addresses
310
+ * string $subject the subject
311
+ * string $body the email body
312
+ * @var string
313
+ */
314
+ public $action_function = ''; //'callbackAction';
315
+
316
+ /**
317
+ * Sets the PHPMailer Version number
318
+ * @var string
319
+ */
320
+ public $Version = '5.2';
321
+
322
+ /**
323
+ * What to use in the X-Mailer header
324
+ * @var string
325
+ */
326
+ public $XMailer = '';
327
+
328
+ /////////////////////////////////////////////////
329
+ // PROPERTIES, PRIVATE AND PROTECTED
330
+ /////////////////////////////////////////////////
331
+
332
+ protected $smtp = NULL;
333
+ protected $to = array();
334
+ protected $cc = array();
335
+ protected $bcc = array();
336
+ protected $ReplyTo = array();
337
+ protected $all_recipients = array();
338
+ protected $attachment = array();
339
+ protected $CustomHeader = array();
340
+ protected $message_type = '';
341
+ protected $boundary = array();
342
+ protected $language = array();
343
+ protected $error_count = 0;
344
+ protected $sign_cert_file = '';
345
+ protected $sign_key_file = '';
346
+ protected $sign_key_pass = '';
347
+ protected $exceptions = false;
348
+
349
+ /////////////////////////////////////////////////
350
+ // CONSTANTS
351
+ /////////////////////////////////////////////////
352
+
353
+ const STOP_MESSAGE = 0; // message only, continue processing
354
+ const STOP_CONTINUE = 1; // message?, likely ok to continue processing
355
+ const STOP_CRITICAL = 2; // message, plus full stop, critical error reached
356
+
357
+ /////////////////////////////////////////////////
358
+ // METHODS, VARIABLES
359
+ /////////////////////////////////////////////////
360
+
361
+ /**
362
+ * Constructor
363
+ * @param boolean $exceptions Should we throw external exceptions?
364
+ */
365
+ public function __construct($exceptions = false) {
366
+ $this->exceptions = ($exceptions == true);
367
+ }
368
+
369
+ /**
370
+ * Sets message type to HTML.
371
+ * @param bool $ishtml
372
+ * @return void
373
+ */
374
+ public function IsHTML($ishtml = true) {
375
+ if ($ishtml) {
376
+ $this->ContentType = 'text/html';
377
+ } else {
378
+ $this->ContentType = 'text/plain';
379
+ }
380
+ }
381
+
382
+ /**
383
+ * Sets Mailer to send message using SMTP.
384
+ * @return void
385
+ */
386
+ public function IsSMTP() {
387
+ $this->Mailer = 'smtp';
388
+ }
389
+
390
+ /**
391
+ * Sets Mailer to send message using PHP mail() function.
392
+ * @return void
393
+ */
394
+ public function IsMail() {
395
+ $this->Mailer = 'mail';
396
+ }
397
+
398
+ /**
399
+ * Sets Mailer to send message using the $Sendmail program.
400
+ * @return void
401
+ */
402
+ public function IsSendmail() {
403
+ if (!stristr(ini_get('sendmail_path'), 'sendmail')) {
404
+ $this->Sendmail = '/var/qmail/bin/sendmail';
405
+ }
406
+ $this->Mailer = 'sendmail';
407
+ }
408
+
409
+ /**
410
+ * Sets Mailer to send message using the qmail MTA.
411
+ * @return void
412
+ */
413
+ public function IsQmail() {
414
+ if (stristr(ini_get('sendmail_path'), 'qmail')) {
415
+ $this->Sendmail = '/var/qmail/bin/sendmail';
416
+ }
417
+ $this->Mailer = 'sendmail';
418
+ }
419
+
420
+ /////////////////////////////////////////////////
421
+ // METHODS, RECIPIENTS
422
+ /////////////////////////////////////////////////
423
+
424
+ /**
425
+ * Adds a "To" address.
426
+ * @param string $address
427
+ * @param string $name
428
+ * @return boolean true on success, false if address already used
429
+ */
430
+ public function AddAddress($address, $name = '') {
431
+ return $this->AddAnAddress('to', $address, $name);
432
+ }
433
+
434
+ /**
435
+ * Adds a "Cc" address.
436
+ * Note: this function works with the SMTP mailer on win32, not with the "mail" mailer.
437
+ * @param string $address
438
+ * @param string $name
439
+ * @return boolean true on success, false if address already used
440
+ */
441
+ public function AddCC($address, $name = '') {
442
+ return $this->AddAnAddress('cc', $address, $name);
443
+ }
444
+
445
+ /**
446
+ * Adds a "Bcc" address.
447
+ * Note: this function works with the SMTP mailer on win32, not with the "mail" mailer.
448
+ * @param string $address
449
+ * @param string $name
450
+ * @return boolean true on success, false if address already used
451
+ */
452
+ public function AddBCC($address, $name = '') {
453
+ return $this->AddAnAddress('bcc', $address, $name);
454
+ }
455
+
456
+ /**
457
+ * Adds a "Reply-to" address.
458
+ * @param string $address
459
+ * @param string $name
460
+ * @return boolean
461
+ */
462
+ public function AddReplyTo($address, $name = '') {
463
+ return $this->AddAnAddress('ReplyTo', $address, $name);
464
+ }
465
+
466
+ /**
467
+ * Adds an address to one of the recipient arrays
468
+ * Addresses that have been added already return false, but do not throw exceptions
469
+ * @param string $kind One of 'to', 'cc', 'bcc', 'ReplyTo'
470
+ * @param string $address The email address to send to
471
+ * @param string $name
472
+ * @return boolean true on success, false if address already used or invalid in some way
473
+ * @access protected
474
+ */
475
+ protected function AddAnAddress($kind, $address, $name = '') {
476
+ if (!preg_match('/^(to|cc|bcc|ReplyTo)$/', $kind)) {
477
+ $this->SetError($this->Lang('Invalid recipient array').': '.$kind);
478
+ if ($this->exceptions) {
479
+ throw new EM_phpmailerException('Invalid recipient array: ' . $kind);
480
+ }
481
+ echo $this->Lang('Invalid recipient array').': '.$kind;
482
+ return false;
483
+ }
484
+ $address = trim($address);
485
+ $name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim
486
+ if (!self::ValidateAddress($address)) {
487
+ $this->SetError($this->Lang('invalid_address').': '. $address);
488
+ if ($this->exceptions) {
489
+ throw new EM_phpmailerException($this->Lang('invalid_address').': '.$address);
490
+ }
491
+ echo $this->Lang('invalid_address').': '.$address;
492
+ return false;
493
+ }
494
+ if ($kind != 'ReplyTo') {
495
+ if (!isset($this->all_recipients[strtolower($address)])) {
496
+ array_push($this->$kind, array($address, $name));
497
+ $this->all_recipients[strtolower($address)] = true;
498
+ return true;
499
+ }
500
+ } else {
501
+ if (!array_key_exists(strtolower($address), $this->ReplyTo)) {
502
+ $this->ReplyTo[strtolower($address)] = array($address, $name);
503
+ return true;
504
+ }
505
+ }
506
+ return false;
507
+ }
508
 
509
+ /**
510
+ * Set the From and FromName properties
511
+ * @param string $address
512
+ * @param string $name
513
+ * @return boolean
514
+ */
515
+ public function SetFrom($address, $name = '', $auto = 1) {
516
+ $address = trim($address);
517
+ $name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim
518
+ if (!self::ValidateAddress($address)) {
519
+ $this->SetError($this->Lang('invalid_address').': '. $address);
520
+ if ($this->exceptions) {
521
+ throw new EM_phpmailerException($this->Lang('invalid_address').': '.$address);
522
+ }
523
+ echo $this->Lang('invalid_address').': '.$address;
524
+ return false;
525
+ }
526
+ $this->From = $address;
527
+ $this->FromName = $name;
528
+ if ($auto) {
529
+ if (empty($this->ReplyTo)) {
530
+ $this->AddAnAddress('ReplyTo', $address, $name);
531
+ }
532
+ if (empty($this->Sender)) {
533
+ $this->Sender = $address;
534
+ }
535
+ }
536
+ return true;
537
+ }
538
+
539
+ /**
540
+ * Check that a string looks roughly like an email address should
541
+ * Static so it can be used without instantiation
542
+ * Tries to use PHP built-in validator in the filter extension (from PHP 5.2), falls back to a reasonably competent regex validator
543
+ * Conforms approximately to RFC2822
544
+ * @link http://www.hexillion.com/samples/#Regex Original pattern found here
545
+ * @param string $address The email address to check
546
+ * @return boolean
547
+ * @static
548
+ * @access public
549
+ */
550
+ public static function ValidateAddress($address) {
551
+ if (function_exists('filter_var')) { //Introduced in PHP 5.2
552
+ if(filter_var($address, FILTER_VALIDATE_EMAIL) === FALSE) {
553
+ return false;
554
+ } else {
555
+ return true;
556
+ }
557
+ } else {
558
+ return preg_match('/^(?:[\w\!\#\$\%\&\'\*\+\-\/\=\?\^\`\{\|\}\~]+\.)*[\w\!\#\$\%\&\'\*\+\-\/\=\?\^\`\{\|\}\~]+@(?:(?:(?:[a-zA-Z0-9_](?:[a-zA-Z0-9_\-](?!\.)){0,61}[a-zA-Z0-9_-]?\.)+[a-zA-Z0-9_](?:[a-zA-Z0-9_\-](?!$)){0,61}[a-zA-Z0-9_]?)|(?:\[(?:(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\.){3}(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\]))$/', $address);
559
+ }
560
+ }
561
+
562
+ /////////////////////////////////////////////////
563
+ // METHODS, MAIL SENDING
564
+ /////////////////////////////////////////////////
565
+
566
+ /**
567
+ * Creates message and assigns Mailer. If the message is
568
+ * not sent successfully then it returns false. Use the ErrorInfo
569
+ * variable to view description of the error.
570
+ * @return bool
571
+ */
572
+ public function Send() {
573
+ try {
574
+ if(!$this->PreSend()) return false;
575
+ return $this->PostSend();
576
+ } catch (EM_phpmailerException $e) {
577
+ $this->SetError($e->getMessage());
578
+ if ($this->exceptions) {
579
+ throw $e;
580
+ }
581
+ return false;
582
+ }
583
+ }
584
 
585
+ protected function PreSend() {
586
+ try {
587
+ if ((count($this->to) + count($this->cc) + count($this->bcc)) < 1) {
588
+ throw new EM_phpmailerException($this->Lang('provide_address'), self::STOP_CRITICAL);
589
+ }
590
+
591
+ // Set whether the message is multipart/alternative
592
+ if(!empty($this->AltBody)) {
593
+ $this->ContentType = 'multipart/alternative';
594
+ }
595
+
596
+ $this->error_count = 0; // reset errors
597
+ $this->SetMessageType();
598
+ //Refuse to send an empty message
599
+ if (empty($this->Body)) {
600
+ throw new EM_phpmailerException($this->Lang('empty_message'), self::STOP_CRITICAL);
601
+ }
602
+
603
+ $this->MIMEHeader = $this->CreateHeader();
604
+ $this->MIMEBody = $this->CreateBody();
605
+
606
+
607
+ // digitally sign with DKIM if enabled
608
+ if ($this->DKIM_domain && $this->DKIM_private) {
609
+ $header_dkim = $this->DKIM_Add($this->MIMEHeader, $this->EncodeHeader($this->SecureHeader($this->Subject)), $this->MIMEBody);
610
+ $this->MIMEHeader = str_replace("\r\n", "\n", $header_dkim) . $this->MIMEHeader;
611
+ }
612
+
613
+ return true;
614
+ } catch (EM_phpmailerException $e) {
615
+ $this->SetError($e->getMessage());
616
+ if ($this->exceptions) {
617
+ throw $e;
618
+ }
619
+ return false;
620
+ }
621
+ }
622
+
623
+ protected function PostSend() {
624
+ try {
625
+ // Choose the mailer and send through it
626
+ switch($this->Mailer) {
627
+ case 'sendmail':
628
+ return $this->SendmailSend($this->MIMEHeader, $this->MIMEBody);
629
+ case 'smtp':
630
+ return $this->SmtpSend($this->MIMEHeader, $this->MIMEBody);
631
+ default:
632
+ return $this->MailSend($this->MIMEHeader, $this->MIMEBody);
633
+ }
634
+
635
+ } catch (EM_phpmailerException $e) {
636
+ $this->SetError($e->getMessage());
637
+ if ($this->exceptions) {
638
+ throw $e;
639
+ }
640
+ echo $e->getMessage()."\n";
641
+ return false;
642
+ }
643
+ }
644
+
645
+ /**
646
+ * Sends mail using the $Sendmail program.
647
+ * @param string $header The message headers
648
+ * @param string $body The message body
649
+ * @access protected
650
+ * @return bool
651
+ */
652
+ protected function SendmailSend($header, $body) {
653
+ if ($this->Sender != '') {
654
+ $sendmail = sprintf("%s -oi -f %s -t", escapeshellcmd($this->Sendmail), escapeshellarg($this->Sender));
655
+ } else {
656
+ $sendmail = sprintf("%s -oi -t", escapeshellcmd($this->Sendmail));
657
+ }
658
+ if ($this->SingleTo === true) {
659
+ foreach ($this->SingleToArray as $key => $val) {
660
+ if(!@$mail = popen($sendmail, 'w')) {
661
+ throw new EM_phpmailerException($this->Lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
662
+ }
663
+ fputs($mail, "To: " . $val . "\n");
664
  fputs($mail, $header);
665
  fputs($mail, $body);
666
+ $result = pclose($mail);
667
+ // implement call back function if it exists
668
+ $isSent = ($result == 0) ? 1 : 0;
669
+ $this->doCallback($isSent, $val, $this->cc, $this->bcc, $this->Subject, $body);
670
+ if($result != 0) {
671
+ throw new EM_phpmailerException($this->Lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
672
  }
673
+ }
674
+ } else {
675
+ if(!@$mail = popen($sendmail, 'w')) {
676
+ throw new EM_phpmailerException($this->Lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
677
+ }
678
+ fputs($mail, $header);
679
+ fputs($mail, $body);
680
+ $result = pclose($mail);
681
+ // implement call back function if it exists
682
+ $isSent = ($result == 0) ? 1 : 0;
683
+ $this->doCallback($isSent, $this->to, $this->cc, $this->bcc, $this->Subject, $body);
684
+ if($result != 0) {
685
+ throw new EM_phpmailerException($this->Lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
686
+ }
687
+ }
688
+ return true;
689
+ }
690
+
691
+ /**
692
+ * Sends mail using the PHP mail() function.
693
+ * @param string $header The message headers
694
+ * @param string $body The message body
695
+ * @access protected
696
+ * @return bool
697
+ */
698
+ protected function MailSend($header, $body) {
699
+ $toArr = array();
700
+ foreach($this->to as $t) {
701
+ $toArr[] = $this->AddrFormat($t);
702
  }
703
+ $to = implode(', ', $toArr);
704
 
705
+ if (empty($this->Sender)) {
706
+ $params = "-oi -f %s";
707
+ } else {
708
+ $params = sprintf("-oi -f %s", $this->Sender);
709
+ }
710
+ if ($this->Sender != '' and !ini_get('safe_mode')) {
711
+ $old_from = ini_get('sendmail_from');
712
+ ini_set('sendmail_from', $this->Sender);
713
+ if ($this->SingleTo === true && count($toArr) > 1) {
714
+ foreach ($toArr as $key => $val) {
715
+ $rt = @mail($val, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header, $params);
716
+ // implement call back function if it exists
717
+ $isSent = ($rt == 1) ? 1 : 0;
718
+ $this->doCallback($isSent, $val, $this->cc, $this->bcc, $this->Subject, $body);
719
  }
720
+ } else {
721
+ $rt = @mail($to, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header, $params);
722
+ // implement call back function if it exists
723
+ $isSent = ($rt == 1) ? 1 : 0;
724
+ $this->doCallback($isSent, $to, $this->cc, $this->bcc, $this->Subject, $body);
725
+ }
726
+ } else {
727
+ if ($this->SingleTo === true && count($toArr) > 1) {
728
+ foreach ($toArr as $key => $val) {
729
+ $rt = @mail($val, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header, $params);
730
+ // implement call back function if it exists
731
+ $isSent = ($rt == 1) ? 1 : 0;
732
+ $this->doCallback($isSent, $val, $this->cc, $this->bcc, $this->Subject, $body);
733
  }
734
+ } else {
735
+ $rt = @mail($to, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header);
736
+ // implement call back function if it exists
737
+ $isSent = ($rt == 1) ? 1 : 0;
738
+ $this->doCallback($isSent, $to, $this->cc, $this->bcc, $this->Subject, $body);
739
+ }
740
+ }
741
+ if (isset($old_from)) {
742
+ ini_set('sendmail_from', $old_from);
743
+ }
744
+ if(!$rt) {
745
+ throw new EM_phpmailerException($this->Lang('instantiate'), self::STOP_CRITICAL);
746
+ }
747
+ return true;
748
+ }
749
+
750
+ /**
751
+ * Sends mail via SMTP using PhpSMTP
752
+ * Returns false if there is a bad MAIL FROM, RCPT, or DATA input.
753
+ * @param string $header The message headers
754
+ * @param string $body The message body
755
+ * @uses SMTP
756
+ * @access protected
757
+ * @return bool
758
+ */
759
+ protected function SmtpSend($header, $body) {
760
+ require_once $this->PluginDir . 'class.smtp.php';
761
+ $bad_rcpt = array();
762
+
763
+ if(!$this->SmtpConnect()) {
764
+ throw new EM_phpmailerException($this->Lang('smtp_connect_failed'), self::STOP_CRITICAL);
765
+ }
766
+ $smtp_from = ($this->Sender == '') ? $this->From : $this->Sender;
767
+ if(!$this->smtp->Mail($smtp_from)) {
768
+ throw new EM_phpmailerException($this->Lang('from_failed') . $smtp_from, self::STOP_CRITICAL);
769
+ }
770
 
771
+ // Attempt to send attach all recipients
772
+ foreach($this->to as $to) {
773
+ if (!$this->smtp->Recipient($to[0])) {
774
+ $bad_rcpt[] = $to[0];
775
+ // implement call back function if it exists
776
+ $isSent = 0;
777
+ $this->doCallback($isSent, $to[0], '', '', $this->Subject, $body);
778
+ } else {
779
+ // implement call back function if it exists
780
+ $isSent = 1;
781
+ $this->doCallback($isSent, $to[0], '', '', $this->Subject, $body);
782
+ }
783
+ }
784
+ foreach($this->cc as $cc) {
785
+ if (!$this->smtp->Recipient($cc[0])) {
786
+ $bad_rcpt[] = $cc[0];
787
+ // implement call back function if it exists
788
+ $isSent = 0;
789
+ $this->doCallback($isSent, '', $cc[0], '', $this->Subject, $body);
790
+ } else {
791
+ // implement call back function if it exists
792
+ $isSent = 1;
793
+ $this->doCallback($isSent, '', $cc[0], '', $this->Subject, $body);
794
+ }
795
+ }
796
+ foreach($this->bcc as $bcc) {
797
+ if (!$this->smtp->Recipient($bcc[0])) {
798
+ $bad_rcpt[] = $bcc[0];
799
+ // implement call back function if it exists
800
+ $isSent = 0;
801
+ $this->doCallback($isSent, '', '', $bcc[0], $this->Subject, $body);
802
+ } else {
803
+ // implement call back function if it exists
804
+ $isSent = 1;
805
+ $this->doCallback($isSent, '', '', $bcc[0], $this->Subject, $body);
806
+ }
807
+ }
808
 
 
 
 
 
 
809
 
810
+ if (count($bad_rcpt) > 0 ) { //Create error message for any bad addresses
811
+ $badaddresses = implode(', ', $bad_rcpt);
812
+ throw new EM_phpmailerException($this->Lang('recipients_failed') . $badaddresses);
813
+ }
814
+ if(!$this->smtp->Data($header . $body)) {
815
+ throw new EM_phpmailerException($this->Lang('data_not_accepted'), self::STOP_CRITICAL);
816
+ }
817
+ if($this->SMTPKeepAlive == true) {
818
+ $this->smtp->Reset();
819
+ }
820
+ return true;
821
+ }
822
+
823
+ /**
824
+ * Initiates a connection to an SMTP server.
825
+ * Returns false if the operation failed.
826
+ * @uses SMTP
827
+ * @access public
828
+ * @return bool
829
+ */
830
+ public function SmtpConnect() {
831
+ if(is_null($this->smtp)) {
832
+ $this->smtp = new EM_SMTP();
833
  }
834
 
835
+ $this->smtp->do_debug = $this->SMTPDebug;
836
+ $hosts = explode(';', $this->Host);
837
+ $index = 0;
838
+ $connection = $this->smtp->Connected();
839
+
840
+ // Retry while there is no connection
841
+ try {
842
+ while($index < count($hosts) && !$connection) {
843
+ $hostinfo = array();
844
+ if (preg_match('/^(.+):([0-9]+)$/', $hosts[$index], $hostinfo)) {
845
+ $host = $hostinfo[1];
846
+ $port = $hostinfo[2];
847
+ } else {
848
+ $host = $hosts[$index];
849
+ $port = $this->Port;
 
 
 
 
 
 
 
850
  }
851
 
852
+ $tls = ($this->SMTPSecure == 'tls');
853
+ $ssl = ($this->SMTPSecure == 'ssl');
854
+
855
+ if ($this->smtp->Connect(($ssl ? 'ssl://':'').$host, $port, $this->Timeout)) {
856
+
857
+ $hello = ($this->Helo != '' ? $this->Helo : $this->ServerHostname());
858
+ $this->smtp->Hello($hello);
 
 
 
 
 
 
 
 
 
859
 
860
+ if ($tls) {
861
+ if (!$this->smtp->StartTLS()) {
862
+ throw new EM_phpmailerException($this->Lang('tls'));
 
 
 
863
  }
 
 
 
 
 
864
 
865
+ //We must resend HELO after tls negotiation
866
+ $this->smtp->Hello($hello);
867
+ }
 
 
 
 
 
 
 
868
 
869
+ $connection = true;
870
+ if ($this->SMTPAuth) {
871
+ if (!$this->smtp->Authenticate($this->Username, $this->Password)) {
872
+ throw new EM_phpmailerException($this->Lang('authenticate'));
873
+ }
874
+ }
875
+ }
876
+ $index++;
877
+ if (!$connection) {
878
+ throw new EM_phpmailerException($this->Lang('connect_host'));
879
+ }
880
+ }
881
+ } catch (EM_phpmailerException $e) {
882
+ $this->smtp->Reset();
883
+ throw $e;
884
+ }
885
+ return true;
886
+ }
887
+
888
+ /**
889
+ * Closes the active SMTP session if one exists.
890
+ * @return void
891
+ */
892
+ public function SmtpClose() {
893
+ if(!is_null($this->smtp)) {
894
+ if($this->smtp->Connected()) {
895
+ $this->smtp->Quit();
896
+ $this->smtp->Close();
897
+ }
898
+ }
899
+ }
900
+
901
+ /**
902
+ * Sets the language for all class error messages.
903
+ * Returns false if it cannot load the language file. The default language is English.
904
+ * @param string $langcode ISO 639-1 2-character language code (e.g. Portuguese: "br")
905
+ * @param string $lang_path Path to the language file directory
906
+ * @access public
907
+ */
908
+ function SetLanguage($langcode = 'en', $lang_path = 'language/') {
909
+ //Define full set of translatable strings
910
+ $PHPMAILER_LANG = array(
911
+ 'provide_address' => 'You must provide at least one recipient email address.',
912
+ 'mailer_not_supported' => ' mailer is not supported.',
913
+ 'execute' => 'Could not execute: ',
914
+ 'instantiate' => 'Could not instantiate mail function.',
915
+ 'authenticate' => 'SMTP Error: Could not authenticate.',
916
+ 'from_failed' => 'The following From address failed: ',
917
+ 'recipients_failed' => 'SMTP Error: The following recipients failed: ',
918
+ 'data_not_accepted' => 'SMTP Error: Data not accepted.',
919
+ 'connect_host' => 'SMTP Error: Could not connect to SMTP host.',
920
+ 'file_access' => 'Could not access file: ',
921
+ 'file_open' => 'File Error: Could not open file: ',
922
+ 'encoding' => 'Unknown encoding: ',
923
+ 'signing' => 'Signing Error: ',
924
+ 'smtp_error' => 'SMTP server error: ',
925
+ 'empty_message' => 'Message body empty',
926
+ 'invalid_address' => 'Invalid address',
927
+ 'variable_set' => 'Cannot set or reset variable: '
928
+ );
929
+ //Overwrite language-specific strings. This way we'll never have missing translations - no more "language string failed to load"!
930
+ $l = true;
931
+ if ($langcode != 'en') { //There is no English translation file
932
+ $l = @include $lang_path.'phpmailer.lang-'.$langcode.'.php';
933
+ }
934
+ $this->language = $PHPMAILER_LANG;
935
+ return ($l == true); //Returns false if language not found
936
+ }
937
+
938
+ /**
939
+ * Return the current array of language strings
940
+ * @return array
941
+ */
942
+ public function GetTranslations() {
943
+ return $this->language;
944
+ }
945
+
946
+ /////////////////////////////////////////////////
947
+ // METHODS, MESSAGE CREATION
948
+ /////////////////////////////////////////////////
949
+
950
+ /**
951
+ * Creates recipient headers.
952
+ * @access public
953
+ * @return string
954
+ */
955
+ public function AddrAppend($type, $addr) {
956
+ $addr_str = $type . ': ';
957
+ $addresses = array();
958
+ foreach ($addr as $a) {
959
+ $addresses[] = $this->AddrFormat($a);
960
+ }
961
+ $addr_str .= implode(', ', $addresses);
962
+ $addr_str .= $this->LE;
963
+
964
+ return $addr_str;
965
+ }
966
+
967
+ /**
968
+ * Formats an address correctly.
969
+ * @access public
970
+ * @return string
971
+ */
972
+ public function AddrFormat($addr) {
973
+ if (empty($addr[1])) {
974
+ return $this->SecureHeader($addr[0]);
975
+ } else {
976
+ return $this->EncodeHeader($this->SecureHeader($addr[1]), 'phrase') . " <" . $this->SecureHeader($addr[0]) . ">";
977
+ }
978
+ }
979
+
980
+ /**
981
+ * Wraps message for use with mailers that do not
982
+ * automatically perform wrapping and for quoted-printable.
983
+ * Original written by philippe.
984
+ * @param string $message The message to wrap
985
+ * @param integer $length The line length to wrap to
986
+ * @param boolean $qp_mode Whether to run in Quoted-Printable mode
987
+ * @access public
988
+ * @return string
989
+ */
990
+ public function WrapText($message, $length, $qp_mode = false) {
991
+ $soft_break = ($qp_mode) ? sprintf(" =%s", $this->LE) : $this->LE;
992
+ // If utf-8 encoding is used, we will need to make sure we don't
993
+ // split multibyte characters when we wrap
994
+ $is_utf8 = (strtolower($this->CharSet) == "utf-8");
995
+
996
+ $message = $this->FixEOL($message);
997
+ if (substr($message, -1) == $this->LE) {
998
+ $message = substr($message, 0, -1);
999
  }
1000
 
1001
+ $line = explode($this->LE, $message);
1002
+ $message = '';
1003
+ for ($i = 0 ;$i < count($line); $i++) {
1004
+ $line_part = explode(' ', $line[$i]);
1005
+ $buf = '';
1006
+ for ($e = 0; $e<count($line_part); $e++) {
1007
+ $word = $line_part[$e];
1008
+ if ($qp_mode and (strlen($word) > $length)) {
1009
+ $space_left = $length - strlen($buf) - 1;
1010
+ if ($e != 0) {
1011
+ if ($space_left > 20) {
1012
+ $len = $space_left;
1013
+ if ($is_utf8) {
1014
+ $len = $this->UTF8CharBoundary($word, $len);
1015
+ } elseif (substr($word, $len - 1, 1) == "=") {
1016
+ $len--;
1017
+ } elseif (substr($word, $len - 2, 1) == "=") {
1018
+ $len -= 2;
1019
+ }
1020
+ $part = substr($word, 0, $len);
1021
+ $word = substr($word, $len);
1022
+ $buf .= ' ' . $part;
1023
+ $message .= $buf . sprintf("=%s", $this->LE);
1024
+ } else {
1025
+ $message .= $buf . $soft_break;
1026
  }
1027
+ $buf = '';
1028
+ }
1029
+ while (strlen($word) > 0) {
1030
+ $len = $length;
1031
+ if ($is_utf8) {
1032
+ $len = $this->UTF8CharBoundary($word, $len);
1033
+ } elseif (substr($word, $len - 1, 1) == "=") {
1034
+ $len--;
1035
+ } elseif (substr($word, $len - 2, 1) == "=") {
1036
+ $len -= 2;
1037
  }
1038
+ $part = substr($word, 0, $len);
1039
+ $word = substr($word, $len);
1040
 
1041
+ if (strlen($word) > 0) {
1042
+ $message .= $part . sprintf("=%s", $this->LE);
1043
+ } else {
1044
+ $buf = $part;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1045
  }
1046
+ }
1047
+ } else {
1048
+ $buf_o = $buf;
1049
+ $buf .= ($e == 0) ? $word : (' ' . $word);
1050
+
1051
+ if (strlen($buf) > $length and $buf_o != '') {
1052
+ $message .= $buf_o . $soft_break;
1053
+ $buf = $word;
1054
+ }
1055
  }
1056
+ }
1057
+ $message .= $buf . $this->LE;
1058
  }
1059
 
1060
+ return $message;
1061
+ }
1062
+
1063
+ /**
1064
+ * Finds last character boundary prior to maxLength in a utf-8
1065
+ * quoted (printable) encoded string.
1066
+ * Original written by Colin Brown.
1067
+ * @access public
1068
+ * @param string $encodedText utf-8 QP text
1069
+ * @param int $maxLength find last character boundary prior to this length
1070
+ * @return int
1071
+ */
1072
+ public function UTF8CharBoundary($encodedText, $maxLength) {
1073
+ $foundSplitPos = false;
1074
+ $lookBack = 3;
1075
+ while (!$foundSplitPos) {
1076
+ $lastChunk = substr($encodedText, $maxLength - $lookBack, $lookBack);
1077
+ $encodedCharPos = strpos($lastChunk, "=");
1078
+ if ($encodedCharPos !== false) {
1079
+ // Found start of encoded character byte within $lookBack block.
1080
+ // Check the encoded byte value (the 2 chars after the '=')
1081
+ $hex = substr($encodedText, $maxLength - $lookBack + $encodedCharPos + 1, 2);
1082
+ $dec = hexdec($hex);
1083
+ if ($dec < 128) { // Single byte character.
1084
+ // If the encoded char was found at pos 0, it will fit
1085
+ // otherwise reduce maxLength to start of the encoded char
1086
+ $maxLength = ($encodedCharPos == 0) ? $maxLength :
1087
+ $maxLength - ($lookBack - $encodedCharPos);
1088
+ $foundSplitPos = true;
1089
+ } elseif ($dec >= 192) { // First byte of a multi byte character
1090
+ // Reduce maxLength to split at start of character
1091
+ $maxLength = $maxLength - ($lookBack - $encodedCharPos);
1092
+ $foundSplitPos = true;
1093
+ } elseif ($dec < 192) { // Middle byte of a multi byte character, look further back
1094
+ $lookBack += 3;
1095
  }
1096
+ } else {
1097
+ // No encoded character found
1098
+ $foundSplitPos = true;
1099
+ }
1100
+ }
1101
+ return $maxLength;
1102
+ }
1103
+
1104
+
1105
+ /**
1106
+ * Set the body wrapping.
1107
+ * @access public
1108
+ * @return void
1109
+ */
1110
+ public function SetWordWrap() {
1111
+ if($this->WordWrap < 1) {
1112
+ return;
1113
+ }
1114
+
1115
+ switch($this->message_type) {
1116
+ case 'alt':
1117
+ case 'alt_inline':
1118
+ case 'alt_attach':
1119
+ case 'alt_inline_attach':
1120
+ $this->AltBody = $this->WrapText($this->AltBody, $this->WordWrap);
1121
+ break;
1122
+ default:
1123
+ $this->Body = $this->WrapText($this->Body, $this->WordWrap);
1124
+ break;
1125
+ }
1126
+ }
1127
+
1128
+ /**
1129
+ * Assembles message header.
1130
+ * @access public
1131
+ * @return string The assembled header
1132
+ */
1133
+ public function CreateHeader() {
1134
+ $result = '';
1135
+
1136
+ // Set the boundaries
1137
+ $uniq_id = md5(uniqid(time()));
1138
+ $this->boundary[1] = 'b1_' . $uniq_id;
1139
+ $this->boundary[2] = 'b2_' . $uniq_id;
1140
+ $this->boundary[3] = 'b3_' . $uniq_id;
1141
+
1142
+ $result .= $this->HeaderLine('Date', self::RFCDate());
1143
+ if($this->Sender == '') {
1144
+ $result .= $this->HeaderLine('Return-Path', trim($this->From));
1145
+ } else {
1146
+ $result .= $this->HeaderLine('Return-Path', trim($this->Sender));
1147
  }
1148
 
1149
+ // To be created automatically by mail()
1150
+ if($this->Mailer != 'mail') {
1151
+ if ($this->SingleTo === true) {
1152
+ foreach($this->to as $t) {
1153
+ $this->SingleToArray[] = $this->AddrFormat($t);
 
 
 
 
 
 
 
 
 
 
 
1154
  }
1155
+ } else {
1156
+ if(count($this->to) > 0) {
1157
+ $result .= $this->AddrAppend('To', $this->to);
1158
+ } elseif (count($this->cc) == 0) {
1159
+ $result .= $this->HeaderLine('To', 'undisclosed-recipients:;');
 
 
 
 
 
 
 
 
 
 
 
 
1160
  }
1161
+ }
1162
+ }
1163
 
1164
+ $from = array();
1165
+ $from[0][0] = trim($this->From);
1166
+ $from[0][1] = $this->FromName;
1167
+ $result .= $this->AddrAppend('From', $from);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1168
 
1169
+ // sendmail and mail() extract Cc from the header before sending
1170
+ if(count($this->cc) > 0) {
1171
+ $result .= $this->AddrAppend('Cc', $this->cc);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1172
  }
1173
 
1174
+ // sendmail and mail() extract Bcc from the header before sending
1175
+ if((($this->Mailer == 'sendmail') || ($this->Mailer == 'mail')) && (count($this->bcc) > 0)) {
1176
+ $result .= $this->AddrAppend('Bcc', $this->bcc);
1177
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1178
 
1179
+ if(count($this->ReplyTo) > 0) {
1180
+ $result .= $this->AddrAppend('Reply-to', $this->ReplyTo);
1181
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1182
 
1183
+ // mail() sets the subject itself
1184
+ if($this->Mailer != 'mail') {
1185
+ $result .= $this->HeaderLine('Subject', $this->EncodeHeader($this->SecureHeader($this->Subject)));
1186
+ }
1187
+
1188
+ if($this->MessageID != '') {
1189
+ $result .= $this->HeaderLine('Message-ID', $this->MessageID);
1190
+ } else {
1191
+ $result .= sprintf("Message-ID: <%s@%s>%s", $uniq_id, $this->ServerHostname(), $this->LE);
1192
+ }
1193
+ $result .= $this->HeaderLine('X-Priority', $this->Priority);
1194
+ if($this->XMailer) {
1195
+ $result .= $this->HeaderLine('X-Mailer', $this->XMailer);
1196
+ } else {
1197
+ $result .= $this->HeaderLine('X-Mailer', 'PHPMailer '.$this->Version.' (http://code.google.com/a/apache-extras.org/p/phpmailer/)');
1198
+ }
1199
+
1200
+ if($this->ConfirmReadingTo != '') {
1201
+ $result .= $this->HeaderLine('Disposition-Notification-To', '<' . trim($this->ConfirmReadingTo) . '>');
1202
+ }
1203
+
1204
+ // Add custom headers
1205
+ for($index = 0; $index < count($this->CustomHeader); $index++) {
1206
+ $result .= $this->HeaderLine(trim($this->CustomHeader[$index][0]), $this->EncodeHeader(trim($this->CustomHeader[$index][1])));
1207
+ }
1208
+ if (!$this->sign_key_file) {
1209
+ $result .= $this->HeaderLine('MIME-Version', '1.0');
1210
+ $result .= $this->GetMailMIME();
1211
+ }
1212
+
1213
+ return $result;
1214
+ }
1215
+
1216
+ /**
1217
+ * Returns the message MIME.
1218
+ * @access public
1219
+ * @return string
1220
+ */
1221
+ public function GetMailMIME() {
1222
+ $result = '';
1223
+ switch($this->message_type) {
1224
+ case 'plain':
1225
+ $result .= $this->HeaderLine('Content-Transfer-Encoding', $this->Encoding);
1226
+ $result .= $this->TextLine('Content-Type: '.$this->ContentType.'; charset="'.$this->CharSet.'"');
1227
+ break;
1228
+ case 'inline':
1229
+ $result .= $this->HeaderLine('Content-Type', 'multipart/related;');
1230
+ $result .= $this->TextLine("\tboundary=\"" . $this->boundary[1] . '"');
1231
+ break;
1232
+ case 'attach':
1233
+ case 'inline_attach':
1234
+ case 'alt_attach':
1235
+ case 'alt_inline_attach':
1236
+ $result .= $this->HeaderLine('Content-Type', 'multipart/mixed;');
1237
+ $result .= $this->TextLine("\tboundary=\"" . $this->boundary[1] . '"');
1238
+ break;
1239
+ case 'alt':
1240
+ case 'alt_inline':
1241
+ $result .= $this->HeaderLine('Content-Type', 'multipart/alternative;');
1242
+ $result .= $this->TextLine("\tboundary=\"" . $this->boundary[1] . '"');
1243
+ break;
1244
+ }
1245
+
1246
+ if($this->Mailer != 'mail') {
1247
+ $result .= $this->LE.$this->LE;
1248
+ }
1249
+
1250
+ return $result;
1251
+ }
1252
+
1253
+ /**
1254
+ * Assembles the message body. Returns an empty string on failure.
1255
+ * @access public
1256
+ * @return string The assembled message body
1257
+ */
1258
+ public function CreateBody() {
1259
+ $body = '';
1260
 
1261
+ if ($this->sign_key_file) {
1262
+ $body .= $this->GetMailMIME();
1263
+ }
1264
+
1265
+ $this->SetWordWrap();
1266
+
1267
+ switch($this->message_type) {
1268
+ case 'plain':
1269
+ $body .= $this->EncodeString($this->Body, $this->Encoding);
1270
+ break;
1271
+ case 'inline':
1272
+ $body .= $this->GetBoundary($this->boundary[1], '', '', '');
1273
+ $body .= $this->EncodeString($this->Body, $this->Encoding);
1274
+ $body .= $this->LE.$this->LE;
1275
+ $body .= $this->AttachAll("inline", $this->boundary[1]);
1276
+ break;
1277
+ case 'attach':
1278
+ $body .= $this->GetBoundary($this->boundary[1], '', '', '');
1279
+ $body .= $this->EncodeString($this->Body, $this->Encoding);
1280
+ $body .= $this->LE.$this->LE;
1281
+ $body .= $this->AttachAll("attachment", $this->boundary[1]);
1282
+ break;
1283
+ case 'inline_attach':
1284
+ $body .= $this->TextLine("--" . $this->boundary[1]);
1285
+ $body .= $this->HeaderLine('Content-Type', 'multipart/related;');
1286
+ $body .= $this->TextLine("\tboundary=\"" . $this->boundary[2] . '"');
1287
+ $body .= $this->LE;
1288
+ $body .= $this->GetBoundary($this->boundary[2], '', '', '');
1289
+ $body .= $this->EncodeString($this->Body, $this->Encoding);
1290
+ $body .= $this->LE.$this->LE;
1291
+ $body .= $this->AttachAll("inline", $this->boundary[2]);
1292
+ $body .= $this->LE;
1293
+ $body .= $this->AttachAll("attachment", $this->boundary[1]);
1294
+ break;
1295
+ case 'alt':
1296
+ $body .= $this->GetBoundary($this->boundary[1], '', 'text/plain', '');
1297
+ $body .= $this->EncodeString($this->AltBody, $this->Encoding);
1298
+ $body .= $this->LE.$this->LE;
1299
+ $body .= $this->GetBoundary($this->boundary[1], '', 'text/html', '');
1300
+ $body .= $this->EncodeString($this->Body, $this->Encoding);
1301
+ $body .= $this->LE.$this->LE;
1302
+ $body .= $this->EndBoundary($this->boundary[1]);
1303
+ break;
1304
+ case 'alt_inline':
1305
+ $body .= $this->GetBoundary($this->boundary[1], '', 'text/plain', '');
1306
+ $body .= $this->EncodeString($this->AltBody, $this->Encoding);
1307
+ $body .= $this->LE.$this->LE;
1308
+ $body .= $this->TextLine("--" . $this->boundary[1]);
1309
+ $body .= $this->HeaderLine('Content-Type', 'multipart/related;');
1310
+ $body .= $this->TextLine("\tboundary=\"" . $this->boundary[2] . '"');
1311
+ $body .= $this->LE;
1312
+ $body .= $this->GetBoundary($this->boundary[2], '', 'text/html', '');
1313
+ $body .= $this->EncodeString($this->Body, $this->Encoding);
1314
+ $body .= $this->LE.$this->LE;
1315
+ $body .= $this->AttachAll("inline", $this->boundary[2]);
1316
+ $body .= $this->LE;
1317
+ $body .= $this->EndBoundary($this->boundary[1]);
1318
+ break;
1319
+ case 'alt_attach':
1320
+ $body .= $this->TextLine("--" . $this->boundary[1]);
1321
+ $body .= $this->HeaderLine('Content-Type', 'multipart/alternative;');
1322
+ $body .= $this->TextLine("\tboundary=\"" . $this->boundary[2] . '"');
1323
+ $body .= $this->LE;
1324
+ $body .= $this->GetBoundary($this->boundary[2], '', 'text/plain', '');
1325
+ $body .= $this->EncodeString($this->AltBody, $this->Encoding);
1326
+ $body .= $this->LE.$this->LE;
1327
+ $body .= $this->GetBoundary($this->boundary[2], '', 'text/html', '');
1328
+ $body .= $this->EncodeString($this->Body, $this->Encoding);
1329
+ $body .= $this->LE.$this->LE;
1330
+ $body .= $this->EndBoundary($this->boundary[2]);
1331
+ $body .= $this->LE;
1332
+ $body .= $this->AttachAll("attachment", $this->boundary[1]);
1333
+ break;
1334
+ case 'alt_inline_attach':
1335
+ $body .= $this->TextLine("--" . $this->boundary[1]);
1336
+ $body .= $this->HeaderLine('Content-Type', 'multipart/alternative;');
1337
+ $body .= $this->TextLine("\tboundary=\"" . $this->boundary[2] . '"');
1338
+ $body .= $this->LE;
1339
+ $body .= $this->GetBoundary($this->boundary[2], '', 'text/plain', '');
1340
+ $body .= $this->EncodeString($this->AltBody, $this->Encoding);
1341
+ $body .= $this->LE.$this->LE;
1342
+ $body .= $this->TextLine("--" . $this->boundary[2]);
1343
+ $body .= $this->HeaderLine('Content-Type', 'multipart/related;');
1344
+ $body .= $this->TextLine("\tboundary=\"" . $this->boundary[3] . '"');
1345
+ $body .= $this->LE;
1346
+ $body .= $this->GetBoundary($this->boundary[3], '', 'text/html', '');
1347
+ $body .= $this->EncodeString($this->Body, $this->Encoding);
1348
+ $body .= $this->LE.$this->LE;
1349
+ $body .= $this->AttachAll("inline", $this->boundary[3]);
1350
+ $body .= $this->LE;
1351
+ $body .= $this->EndBoundary($this->boundary[2]);
1352
+ $body .= $this->LE;
1353
+ $body .= $this->AttachAll("attachment", $this->boundary[1]);
1354
+ break;
1355
+ }
1356
+
1357
+ if ($this->IsError()) {
1358
+ $body = '';
1359
+ } elseif ($this->sign_key_file) {
1360
+ try {
1361
+ $file = tempnam('', 'mail');
1362
+ file_put_contents($file, $body); //TODO check this worked
1363
+ $signed = tempnam("", "signed");
1364
+ if (@openssl_pkcs7_sign($file, $signed, "file://".$this->sign_cert_file, array("file://".$this->sign_key_file, $this->sign_key_pass), NULL)) {
1365
+ @unlink($file);
1366
+ @unlink($signed);
1367
+ $body = file_get_contents($signed);
1368
+ } else {
1369
+ @unlink($file);
1370
+ @unlink($signed);
1371
+ throw new EM_phpmailerException($this->Lang("signing").openssl_error_string());
1372
  }
1373
+ } catch (EM_phpmailerException $e) {
1374
+ $body = '';
1375
+ if ($this->exceptions) {
1376
+ throw $e;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1377
  }
1378
+ }
1379
  }
1380
 
1381
+ return $body;
1382
+ }
1383
+
1384
+ /**
1385
+ * Returns the start of a message boundary.
1386
+ * @access protected
1387
+ * @return string
1388
+ */
1389
+ protected function GetBoundary($boundary, $charSet, $contentType, $encoding) {
1390
+ $result = '';
1391
+ if($charSet == '') {
1392
+ $charSet = $this->CharSet;
1393
+ }
1394
+ if($contentType == '') {
1395
+ $contentType = $this->ContentType;
1396
+ }
1397
+ if($encoding == '') {
1398
+ $encoding = $this->Encoding;
1399
+ }
1400
+ $result .= $this->TextLine('--' . $boundary);
1401
+ $result .= sprintf("Content-Type: %s; charset=\"%s\"", $contentType, $charSet);
1402
+ $result .= $this->LE;
1403
+ $result .= $this->HeaderLine('Content-Transfer-Encoding', $encoding);
1404
+ $result .= $this->LE;
1405
+
1406
+ return $result;
1407
+ }
1408
+
1409
+ /**
1410
+ * Returns the end of a message boundary.
1411
+ * @access protected
1412
+ * @return string
1413
+ */
1414
+ protected function EndBoundary($boundary) {
1415
+ return $this->LE . '--' . $boundary . '--' . $this->LE;
1416
+ }
1417
+
1418
+ /**
1419
+ * Sets the message type.
1420
+ * @access protected
1421
+ * @return void
1422
+ */
1423
+ protected function SetMessageType() {
1424
+ $this->message_type = array();
1425
+ if($this->AlternativeExists()) $this->message_type[] = "alt";
1426
+ if($this->InlineImageExists()) $this->message_type[] = "inline";
1427
+ if($this->AttachmentExists()) $this->message_type[] = "attach";
1428
+ $this->message_type = implode("_", $this->message_type);
1429
+ if($this->message_type == "") $this->message_type = "plain";
1430
+ }
1431
+
1432
+ /**
1433
+ * Returns a formatted header line.
1434
+ * @access public
1435
+ * @return string
1436
+ */
1437
+ public function HeaderLine($name, $value) {
1438
+ return $name . ': ' . $value . $this->LE;
1439
+ }
1440
+
1441
+ /**
1442
+ * Returns a formatted mail line.
1443
+ * @access public
1444
+ * @return string
1445
+ */
1446
+ public function TextLine($value) {
1447
+ return $value . $this->LE;
1448
+ }
1449
+
1450
+ /////////////////////////////////////////////////
1451
+ // CLASS METHODS, ATTACHMENTS
1452
+ /////////////////////////////////////////////////
1453
+
1454
+ /**
1455
+ * Adds an attachment from a path on the filesystem.
1456
+ * Returns false if the file could not be found
1457
+ * or accessed.
1458
+ * @param string $path Path to the attachment.
1459
+ * @param string $name Overrides the attachment name.
1460
+ * @param string $encoding File encoding (see $Encoding).
1461
+ * @param string $type File extension (MIME) type.
1462
+ * @return bool
1463
+ */
1464
+ public function AddAttachment($path, $name = '', $encoding = 'base64', $type = 'application/octet-stream') {
1465
+ try {
1466
+ if ( !@is_file($path) ) {
1467
+ throw new EM_phpmailerException($this->Lang('file_access') . $path, self::STOP_CONTINUE);
1468
+ }
1469
+ $filename = basename($path);
1470
+ if ( $name == '' ) {
1471
+ $name = $filename;
1472
+ }
1473
 
1474
+ $this->attachment[] = array(
1475
+ 0 => $path,
1476
+ 1 => $filename,
1477
+ 2 => $name,
1478
+ 3 => $encoding,
1479
+ 4 => $type,
1480
+ 5 => false, // isStringAttachment
1481
+ 6 => 'attachment',
1482
+ 7 => 0
1483
+ );
1484
+
1485
+ } catch (EM_phpmailerException $e) {
1486
+ $this->SetError($e->getMessage());
1487
+ if ($this->exceptions) {
1488
+ throw $e;
1489
+ }
1490
+ echo $e->getMessage()."\n";
1491
+ if ( $e->getCode() == self::STOP_CRITICAL ) {
1492
+ return false;
1493
+ }
1494
+ }
1495
+ return true;
1496
+ }
1497
+
1498
+ /**
1499
+ * Return the current array of attachments
1500
+ * @return array
1501
+ */
1502
+ public function GetAttachments() {
1503
+ return $this->attachment;
1504
+ }
1505
+
1506
+ /**
1507
+ * Attaches all fs, string, and binary attachments to the message.
1508
+ * Returns an empty string on failure.
1509
+ * @access protected
1510
+ * @return string
1511
+ */
1512
+ protected function AttachAll($disposition_type, $boundary) {
1513
+ // Return text of body
1514
+ $mime = array();
1515
+ $cidUniq = array();
1516
+ $incl = array();
1517
+
1518
+ // Add all attachments
1519
+ foreach ($this->attachment as $attachment) {
1520
+ // CHECK IF IT IS A VALID DISPOSITION_FILTER
1521
+ if($attachment[6] == $disposition_type) {
1522
+ // Check for string attachment
1523
+ $bString = $attachment[5];
1524
+ if ($bString) {
1525
+ $string = $attachment[0];
1526
+ } else {
1527
+ $path = $attachment[0];
1528
+ }
1529
 
1530
+ $inclhash = md5(serialize($attachment));
1531
+ if (in_array($inclhash, $incl)) { continue; }
1532
+ $incl[] = $inclhash;
1533
+ $filename = $attachment[1];
1534
+ $name = $attachment[2];
1535
+ $encoding = $attachment[3];
1536
+ $type = $attachment[4];
1537
+ $disposition = $attachment[6];
1538
+ $cid = $attachment[7];
1539
+ if ( $disposition == 'inline' && isset($cidUniq[$cid]) ) { continue; }
1540
+ $cidUniq[$cid] = true;
1541
+
1542
+ $mime[] = sprintf("--%s%s", $boundary, $this->LE);
1543
+ $mime[] = sprintf("Content-Type: %s; name=\"%s\"%s", $type, $this->EncodeHeader($this->SecureHeader($name)), $this->LE);
1544
+ $mime[] = sprintf("Content-Transfer-Encoding: %s%s", $encoding, $this->LE);
1545
+
1546
+ if($disposition == 'inline') {
1547
+ $mime[] = sprintf("Content-ID: <%s>%s", $cid, $this->LE);
1548
+ }
1549
 
1550
+ $mime[] = sprintf("Content-Disposition: %s; filename=\"%s\"%s", $disposition, $this->EncodeHeader($this->SecureHeader($name)), $this->LE.$this->LE);
 
1551
 
1552
+ // Encode as string attachment
1553
+ if($bString) {
1554
+ $mime[] = $this->EncodeString($string, $encoding);
1555
+ if($this->IsError()) {
1556
+ return '';
1557
+ }
1558
+ $mime[] = $this->LE.$this->LE;
1559
+ } else {
1560
+ $mime[] = $this->EncodeFile($path, $encoding);
1561
+ if($this->IsError()) {
1562
+ return '';
1563
+ }
1564
+ $mime[] = $this->LE.$this->LE;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1565
  }
1566
+ }
1567
+ }
1568
 
1569
+ $mime[] = sprintf("--%s--%s", $boundary, $this->LE);
1570
+
1571
+ return implode("", $mime);
1572
+ }
1573
+
1574
+ /**
1575
+ * Encodes attachment in requested format.
1576
+ * Returns an empty string on failure.
1577
+ * @param string $path The full path to the file
1578
+ * @param string $encoding The encoding to use; one of 'base64', '7bit', '8bit', 'binary', 'quoted-printable'
1579
+ * @see EncodeFile()
1580
+ * @access protected
1581
+ * @return string
1582
+ */
1583
+ protected function EncodeFile($path, $encoding = 'base64') {
1584
+ try {
1585
+ if (!is_readable($path)) {
1586
+ throw new EM_phpmailerException($this->Lang('file_open') . $path, self::STOP_CONTINUE);
1587
+ }
1588
+ if (function_exists('get_magic_quotes')) {
1589
+ function get_magic_quotes() {
1590
+ return false;
1591
  }
1592
+ }
1593
+ if (version_compare(PHP_VERSION, '5.3.0', '<')) {
1594
  $magic_quotes = get_magic_quotes_runtime();
1595
  set_magic_quotes_runtime(0);
1596
+ }
1597
+ $file_buffer = file_get_contents($path);
1598
+ $file_buffer = $this->EncodeString($file_buffer, $encoding);
1599
+ if (version_compare(PHP_VERSION, '5.3.0', '<')) {
1600
  set_magic_quotes_runtime($magic_quotes);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1601
  }
1602
+ return $file_buffer;
1603
+ } catch (Exception $e) {
1604
+ $this->SetError($e->getMessage());
1605
+ return '';
1606
+ }
1607
+ }
1608
+
1609
+ /**
1610
+ * Encodes string to requested format.
1611
+ * Returns an empty string on failure.
1612
+ * @param string $str The text to encode
1613
+ * @param string $encoding The encoding to use; one of 'base64', '7bit', '8bit', 'binary', 'quoted-printable'
1614
+ * @access public
1615
+ * @return string
1616
+ */
1617
+ public function EncodeString($str, $encoding = 'base64') {
1618
+ $encoded = '';
1619
+ switch(strtolower($encoding)) {
1620
+ case 'base64':
1621
+ $encoded = chunk_split(base64_encode($str), 76, $this->LE);
1622
+ break;
1623
+ case '7bit':
1624
+ case '8bit':
1625
+ $encoded = $this->FixEOL($str);
1626
+ //Make sure it ends with a line break
1627
+ if (substr($encoded, -(strlen($this->LE))) != $this->LE)
1628
+ $encoded .= $this->LE;
1629
+ break;
1630
+ case 'binary':
1631
+ $encoded = $str;
1632
+ break;
1633
+ case 'quoted-printable':
1634
+ $encoded = $this->EncodeQP($str);
1635
+ break;
1636
+ default:
1637
+ $this->SetError($this->Lang('encoding') . $encoding);
1638
+ break;
1639
+ }
1640
+ return $encoded;
1641
+ }
1642
+
1643
+ /**
1644
+ * Encode a header string to best (shortest) of Q, B, quoted or none.
1645
+ * @access public
1646
+ * @return string
1647
+ */
1648
+ public function EncodeHeader($str, $position = 'text') {
1649
+ $x = 0;
1650
+
1651
+ switch (strtolower($position)) {
1652
+ case 'phrase':
1653
+ if (!preg_match('/[\200-\377]/', $str)) {
1654
+ // Can't use addslashes as we don't know what value has magic_quotes_sybase
1655
+ $encoded = addcslashes($str, "\0..\37\177\\\"");
1656
+ if (($str == $encoded) && !preg_match('/[^A-Za-z0-9!#$%&\'*+\/=?^_`{|}~ -]/', $str)) {
1657
+ return ($encoded);
1658
+ } else {
1659
+ return ("\"$encoded\"");
1660
+ }
1661
+ }
1662
+ $x = preg_match_all('/[^\040\041\043-\133\135-\176]/', $str, $matches);
1663
+ break;
1664
+ case 'comment':
1665
+ $x = preg_match_all('/[()"]/', $str, $matches);
1666
+ // Fall-through
1667
+ case 'text':
1668
+ default:
1669
+ $x += preg_match_all('/[\000-\010\013\014\016-\037\177-\377]/', $str, $matches);
1670
+ break;
1671
+ }
1672
 
1673
+ if ($x == 0) {
1674
+ return ($str);
1675
+ }
1676
 
1677
+ $maxlen = 75 - 7 - strlen($this->CharSet);
1678
+ // Try to select the encoding which should produce the shortest output
1679
+ if (strlen($str)/3 < $x) {
1680
+ $encoding = 'B';
1681
+ if (function_exists('mb_strlen') && $this->HasMultiBytes($str)) {
1682
+ // Use a custom function which correctly encodes and wraps long
1683
+ // multibyte strings without breaking lines within a character
1684
+ $encoded = $this->Base64EncodeWrapMB($str);
1685
+ } else {
1686
  $encoded = base64_encode($str);
1687
  $maxlen -= $maxlen % 4;
1688
  $encoded = trim(chunk_split($encoded, $maxlen, "\n"));
 
 
 
 
 
1689
  }
1690
+ } else {
1691
+ $encoding = 'Q';
1692
+ $encoded = $this->EncodeQ($str, $position);
1693
+ $encoded = $this->WrapText($encoded, $maxlen, true);
1694
+ $encoded = str_replace('='.$this->LE, "\n", trim($encoded));
1695
+ }
1696
 
1697
+ $encoded = preg_replace('/^(.*)$/m', " =?".$this->CharSet."?$encoding?\\1?=", $encoded);
1698
+ $encoded = trim(str_replace("\n", $this->LE, $encoded));
1699
+
1700
+ return $encoded;
1701
+ }
1702
+
1703
+ /**
1704
+ * Checks if a string contains multibyte characters.
1705
+ * @access public
1706
+ * @param string $str multi-byte text to wrap encode
1707
+ * @return bool
1708
+ */
1709
+ public function HasMultiBytes($str) {
1710
+ if (function_exists('mb_strlen')) {
1711
+ return (strlen($str) > mb_strlen($str, $this->CharSet));
1712
+ } else { // Assume no multibytes (we can't handle without mbstring functions anyway)
1713
+ return false;
1714
+ }
1715
+ }
1716
+
1717
+ /**
1718
+ * Correctly encodes and wraps long multibyte strings for mail headers
1719
+ * without breaking lines within a character.
1720
+ * Adapted from a function by paravoid at http://uk.php.net/manual/en/function.mb-encode-mimeheader.php
1721
+ * @access public
1722
+ * @param string $str multi-byte text to wrap encode
1723
+ * @return string
1724
+ */
1725
+ public function Base64EncodeWrapMB($str) {
1726
+ $start = "=?".$this->CharSet."?B?";
1727
+ $end = "?=";
1728
+ $encoded = "";
1729
+
1730
+ $mb_length = mb_strlen($str, $this->CharSet);
1731
+ // Each line must have length <= 75, including $start and $end
1732
+ $length = 75 - strlen($start) - strlen($end);
1733
+ // Average multi-byte ratio
1734
+ $ratio = $mb_length / strlen($str);
1735
+ // Base64 has a 4:3 ratio
1736
+ $offset = $avgLength = floor($length * $ratio * .75);
1737
+
1738
+ for ($i = 0; $i < $mb_length; $i += $offset) {
1739
+ $lookBack = 0;
1740
+
1741
+ do {
1742
+ $offset = $avgLength - $lookBack;
1743
+ $chunk = mb_substr($str, $i, $offset, $this->CharSet);
1744
+ $chunk = base64_encode($chunk);
1745
+ $lookBack++;
1746
+ }
1747
+ while (strlen($chunk) > $length);
1748
+
1749
+ $encoded .= $chunk . $this->LE;
1750
+ }
1751
+
1752
+ // Chomp the last linefeed
1753
+ $encoded = substr($encoded, 0, -strlen($this->LE));
1754
+ return $encoded;
1755
+ }
1756
+
1757
+ /**
1758
+ * Encode string to quoted-printable.
1759
+ * Only uses standard PHP, slow, but will always work
1760
+ * @access public
1761
+ * @param string $string the text to encode
1762
+ * @param integer $line_max Number of chars allowed on a line before wrapping
1763
+ * @return string
1764
+ */
1765
+ public function EncodeQPphp( $input = '', $line_max = 76, $space_conv = false) {
1766
+ $hex = array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F');
1767
+ $lines = preg_split('/(?:\r\n|\r|\n)/', $input);
1768
+ $eol = "\r\n";
1769
+ $escape = '=';
1770
+ $output = '';
1771
+ while( list(, $line) = each($lines) ) {
1772
+ $linlen = strlen($line);
1773
+ $newline = '';
1774
+ for($i = 0; $i < $linlen; $i++) {
1775
+ $c = substr( $line, $i, 1 );
1776
+ $dec = ord( $c );
1777
+ if ( ( $i == 0 ) && ( $dec == 46 ) ) { // convert first point in the line into =2E
1778
+ $c = '=2E';
1779
+ }
1780
+ if ( $dec == 32 ) {
1781
+ if ( $i == ( $linlen - 1 ) ) { // convert space at eol only
1782
+ $c = '=20';
1783
+ } else if ( $space_conv ) {
1784
+ $c = '=20';
1785
+ }
1786
+ } elseif ( ($dec == 61) || ($dec < 32 ) || ($dec > 126) ) { // always encode "\t", which is *not* required
1787
+ $h2 = floor($dec/16);
1788
+ $h1 = floor($dec%16);
1789
+ $c = $escape.$hex[$h2].$hex[$h1];
1790
  }
1791
+ if ( (strlen($newline) + strlen($c)) >= $line_max ) { // CRLF is not counted
1792
+ $output .= $newline.$escape.$eol; // soft line break; " =\r\n" is okay
1793
+ $newline = '';
1794
+ // check if newline first character will be point or not
1795
+ if ( $dec == 46 ) {
1796
+ $c = '=2E';
1797
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1798
  }
1799
+ $newline .= $c;
1800
+ } // end of for
1801
+ $output .= $newline.$eol;
1802
+ } // end of while
1803
+ return $output;
1804
+ }
1805
+
1806
+ /**
1807
+ * Encode string to RFC2045 (6.7) quoted-printable format
1808
+ * Uses a PHP5 stream filter to do the encoding about 64x faster than the old version
1809
+ * Also results in same content as you started with after decoding
1810
+ * @see EncodeQPphp()
1811
+ * @access public
1812
+ * @param string $string the text to encode
1813
+ * @param integer $line_max Number of chars allowed on a line before wrapping
1814
+ * @param boolean $space_conv Dummy param for compatibility with existing EncodeQP function
1815
+ * @return string
1816
+ * @author Marcus Bointon
1817
+ */
1818
+ public function EncodeQP($string, $line_max = 76, $space_conv = false) {
1819
+ if (function_exists('quoted_printable_encode')) { //Use native function if it's available (>= PHP5.3)
1820
+ return quoted_printable_encode($string);
1821
+ }
1822
+ $filters = stream_get_filters();
1823
+ if (!in_array('convert.*', $filters)) { //Got convert stream filter?
1824
+ return $this->EncodeQPphp($string, $line_max, $space_conv); //Fall back to old implementation
1825
+ }
1826
+ $fp = fopen('php://temp/', 'r+');
1827
+ $string = preg_replace('/\r\n?/', $this->LE, $string); //Normalise line breaks
1828
+ $params = array('line-length' => $line_max, 'line-break-chars' => $this->LE);
1829
+ $s = stream_filter_append($fp, 'convert.quoted-printable-encode', STREAM_FILTER_READ, $params);
1830
+ fputs($fp, $string);
1831
+ rewind($fp);
1832
+ $out = stream_get_contents($fp);
1833
+ stream_filter_remove($s);
1834
+ $out = preg_replace('/^\./m', '=2E', $out); //Encode . if it is first char on a line, workaround for bug in Exchange
1835
+ fclose($fp);
1836
+ return $out;
1837
+ }
1838
+
1839
+ /**
1840
+ * Encode string to q encoding.
1841
+ * @link http://tools.ietf.org/html/rfc2047
1842
+ * @param string $str the text to encode
1843
+ * @param string $position Where the text is going to be used, see the RFC for what that means
1844
+ * @access public
1845
+ * @return string
1846
+ */
1847
+ public function EncodeQ($str, $position = 'text') {
1848
+ // There should not be any EOL in the string
1849
+ $encoded = preg_replace('/[\r\n]*/', '', $str);
1850
+
1851
+ switch (strtolower($position)) {
1852
+ case 'phrase':
1853
+ $encoded = preg_replace("/([^A-Za-z0-9!*+\/ -])/e", "'='.sprintf('%02X', ord('\\1'))", $encoded);
1854
+ break;
1855
+ case 'comment':
1856
+ $encoded = preg_replace("/([\(\)\"])/e", "'='.sprintf('%02X', ord('\\1'))", $encoded);
1857
+ case 'text':
1858
+ default:
1859
+ // Replace every high ascii, control =, ? and _ characters
1860
+ //TODO using /e (equivalent to eval()) is probably not a good idea
1861
+ $encoded = preg_replace('/([\000-\011\013\014\016-\037\075\077\137\177-\377])/e',
1862
+ "'='.sprintf('%02X', ord(stripslashes('\\1')))", $encoded);
1863
+ break;
1864
+ }
1865
+
1866
+ // Replace every spaces to _ (more readable than =20)
1867
+ $encoded = str_replace(' ', '_', $encoded);
1868
+
1869
+ return $encoded;
1870
+ }
1871
+
1872
+ /**
1873
+ * Adds a string or binary attachment (non-filesystem) to the list.
1874
+ * This method can be used to attach ascii or binary data,
1875
+ * such as a BLOB record from a database.
1876
+ * @param string $string String attachment data.
1877
+ * @param string $filename Name of the attachment.
1878
+ * @param string $encoding File encoding (see $Encoding).
1879
+ * @param string $type File extension (MIME) type.
1880
+ * @return void
1881
+ */
1882
+ public function AddStringAttachment($string, $filename, $encoding = 'base64', $type = 'application/octet-stream') {
1883
+ // Append to $attachment array
1884
+ $this->attachment[] = array(
1885
+ 0 => $string,
1886
+ 1 => $filename,
1887
+ 2 => basename($filename),
1888
+ 3 => $encoding,
1889
+ 4 => $type,
1890
+ 5 => true, // isStringAttachment
1891
+ 6 => 'attachment',
1892
+ 7 => 0
1893
+ );
1894
+ }
1895
+
1896
+ /**
1897
+ * Adds an embedded attachment. This can include images, sounds, and
1898
+ * just about any other document. Make sure to set the $type to an
1899
+ * image type. For JPEG images use "image/jpeg" and for GIF images
1900
+ * use "image/gif".
1901
+ * @param string $path Path to the attachment.
1902
+ * @param string $cid Content ID of the attachment. Use this to identify
1903
+ * the Id for accessing the image in an HTML form.
1904
+ * @param string $name Overrides the attachment name.
1905
+ * @param string $encoding File encoding (see $Encoding).
1906
+ * @param string $type File extension (MIME) type.
1907
+ * @return bool
1908
+ */
1909
+ public function AddEmbeddedImage($path, $cid, $name = '', $encoding = 'base64', $type = 'application/octet-stream') {
1910
+
1911
+ if ( !@is_file($path) ) {
1912
+ $this->SetError($this->Lang('file_access') . $path);
1913
+ return false;
1914
+ }
1915
+
1916
+ $filename = basename($path);
1917
+ if ( $name == '' ) {
1918
+ $name = $filename;
1919
+ }
1920
 
1921
+ // Append to $attachment array
1922
+ $this->attachment[] = array(
1923
+ 0 => $path,
1924
+ 1 => $filename,
1925
+ 2 => $name,
1926
+ 3 => $encoding,
1927
+ 4 => $type,
1928
+ 5 => false, // isStringAttachment
1929
+ 6 => 'inline',
1930
+ 7 => $cid
1931
+ );
1932
+
1933
+ return true;
1934
+ }
1935
+
1936
+ public function AddStringEmbeddedImage($string, $cid, $filename = '', $encoding = 'base64', $type = 'application/octet-stream') {
1937
+ // Append to $attachment array
1938
+ $this->attachment[] = array(
1939
+ 0 => $string,
1940
+ 1 => $filename,
1941
+ 2 => basename($filename),
1942
+ 3 => $encoding,
1943
+ 4 => $type,
1944
+ 5 => true, // isStringAttachment
1945
+ 6 => 'inline',
1946
+ 7 => $cid
1947
+ );
1948
+ }
1949
+
1950
+ /**
1951
+ * Returns true if an inline attachment is present.
1952
+ * @access public
1953
+ * @return bool
1954
+ */
1955
+ public function InlineImageExists() {
1956
+ foreach($this->attachment as $attachment) {
1957
+ if ($attachment[6] == 'inline') {
1958
  return true;
1959
+ }
1960
  }
1961
+ return false;
1962
+ }
1963
+
1964
+ public function AttachmentExists() {
1965
+ foreach($this->attachment as $attachment) {
1966
+ if ($attachment[6] == 'attachment') {
1967
+ return true;
1968
+ }
1969
+ }
1970
+ return false;
1971
+ }
1972
+
1973
+ public function AlternativeExists() {
1974
+ return strlen($this->AltBody)>0;
1975
+ }
1976
+
1977
+ /////////////////////////////////////////////////
1978
+ // CLASS METHODS, MESSAGE RESET
1979
+ /////////////////////////////////////////////////
1980
+
1981
+ /**
1982
+ * Clears all recipients assigned in the TO array. Returns void.
1983
+ * @return void
1984
+ */
1985
+ public function ClearAddresses() {
1986
+ foreach($this->to as $to) {
1987
+ unset($this->all_recipients[strtolower($to[0])]);
1988
+ }
1989
+ $this->to = array();
1990
+ }
1991
+
1992
+ /**
1993
+ * Clears all recipients assigned in the CC array. Returns void.
1994
+ * @return void
1995
+ */
1996
+ public function ClearCCs() {
1997
+ foreach($this->cc as $cc) {
1998
+ unset($this->all_recipients[strtolower($cc[0])]);
1999
+ }
2000
+ $this->cc = array();
2001
+ }
2002
+
2003
+ /**
2004
+ * Clears all recipients assigned in the BCC array. Returns void.
2005
+ * @return void
2006
+ */
2007
+ public function ClearBCCs() {
2008
+ foreach($this->bcc as $bcc) {
2009
+ unset($this->all_recipients[strtolower($bcc[0])]);
2010
+ }
2011
+ $this->bcc = array();
2012
+ }
2013
+
2014
+ /**
2015
+ * Clears all recipients assigned in the ReplyTo array. Returns void.
2016
+ * @return void
2017
+ */
2018
+ public function ClearReplyTos() {
2019
+ $this->ReplyTo = array();
2020
+ }
2021
+
2022
+ /**
2023
+ * Clears all recipients assigned in the TO, CC and BCC
2024
+ * array. Returns void.
2025
+ * @return void
2026
+ */
2027
+ public function ClearAllRecipients() {
2028
+ $this->to = array();
2029
+ $this->cc = array();
2030
+ $this->bcc = array();
2031
+ $this->all_recipients = array();
2032
+ }
2033
+
2034
+ /**
2035
+ * Clears all previously set filesystem, string, and binary
2036
+ * attachments. Returns void.
2037
+ * @return void
2038
+ */
2039
+ public function ClearAttachments() {
2040
+ $this->attachment = array();
2041
+ }
2042
+
2043
+ /**
2044
+ * Clears all custom headers. Returns void.
2045
+ * @return void
2046
+ */
2047
+ public function ClearCustomHeaders() {
2048
+ $this->CustomHeader = array();
2049
+ }
2050
+
2051
+ /////////////////////////////////////////////////
2052
+ // CLASS METHODS, MISCELLANEOUS
2053
+ /////////////////////////////////////////////////
2054
+
2055
+ /**
2056
+ * Adds the error message to the error container.
2057
+ * @access protected
2058
+ * @return void
2059
+ */
2060
+ protected function SetError($msg) {
2061
+ $this->error_count++;
2062
+ if ($this->Mailer == 'smtp' and !is_null($this->smtp)) {
2063
+ $lasterror = $this->smtp->getError();
2064
+ if (!empty($lasterror) and array_key_exists('smtp_msg', $lasterror)) {
2065
+ $msg .= '<p>' . $this->Lang('smtp_error') . $lasterror['smtp_msg'] . "</p>\n";
2066
+ }
2067
+ }
2068
+ $this->ErrorInfo = $msg;
2069
+ }
2070
+
2071
+ /**
2072
+ * Returns the proper RFC 822 formatted date.
2073
+ * @access public
2074
+ * @return string
2075
+ * @static
2076
+ */
2077
+ public static function RFCDate() {
2078
+ $tz = date('Z');
2079
+ $tzs = ($tz < 0) ? '-' : '+';
2080
+ $tz = abs($tz);
2081
+ $tz = (int)($tz/3600)*100 + ($tz%3600)/60;
2082
+ $result = sprintf("%s %s%04d", date('D, j M Y H:i:s'), $tzs, $tz);
2083
+
2084
+ return $result;
2085
+ }
2086
+
2087
+ /**
2088
+ * Returns the server hostname or 'localhost.localdomain' if unknown.
2089
+ * @access protected
2090
+ * @return string
2091
+ */
2092
+ protected function ServerHostname() {
2093
+ if (!empty($this->Hostname)) {
2094
+ $result = $this->Hostname;
2095
+ } elseif (isset($_SERVER['SERVER_NAME'])) {
2096
+ $result = $_SERVER['SERVER_NAME'];
2097
+ } else {
2098
+ $result = 'localhost.localdomain';
2099
+ }
2100
+
2101
+ return $result;
2102
+ }
2103
+
2104
+ /**
2105
+ * Returns a message in the appropriate language.
2106
+ * @access protected
2107
+ * @return string
2108
+ */
2109
+ protected function Lang($key) {
2110
+ if(count($this->language) < 1) {
2111
+ $this->SetLanguage('en'); // set the default language
2112
+ }
2113
+
2114
+ if(isset($this->language[$key])) {
2115
+ return $this->language[$key];
2116
+ } else {
2117
+ return 'Language string failed to load: ' . $key;
2118
+ }
2119
+ }
2120
+
2121
+ /**
2122
+ * Returns true if an error occurred.
2123
+ * @access public
2124
+ * @return bool
2125
+ */
2126
+ public function IsError() {
2127
+ return ($this->error_count > 0);
2128
+ }
2129
+
2130
+ /**
2131
+ * Changes every end of line from CR or LF to CRLF.
2132
+ * @access public
2133
+ * @return string
2134
+ */
2135
+ public function FixEOL($str) {
2136
+ $str = str_replace("\r\n", "\n", $str);
2137
+ $str = str_replace("\r", "\n", $str);
2138
+ $str = str_replace("\n", $this->LE, $str);
2139
+ return $str;
2140
+ }
2141
+
2142
+ /**
2143
+ * Adds a custom header.
2144
+ * @access public
2145
+ * @return void
2146
+ */
2147
+ public function AddCustomHeader($custom_header) {
2148
+ $this->CustomHeader[] = explode(':', $custom_header, 2);
2149
+ }
2150
+
2151
+ /**
2152
+ * Evaluates the message and returns modifications for inline images and backgrounds
2153
+ * @access public
2154
+ * @return $message
2155
+ */
2156
+ public function MsgHTML($message, $basedir = '') {
2157
+ preg_match_all("/(src|background)=\"(.*)\"/Ui", $message, $images);
2158
+ if(isset($images[2])) {
2159
+ foreach($images[2] as $i => $url) {
2160
+ // do not change urls for absolute images (thanks to corvuscorax)
2161
+ if (!preg_match('#^[A-z]+://#', $url)) {
2162
+ $filename = basename($url);
2163
+ $directory = dirname($url);
2164
+ ($directory == '.') ? $directory='': '';
2165
+ $cid = 'cid:' . md5($filename);
2166
+ $ext = pathinfo($filename, PATHINFO_EXTENSION);
2167
+ $mimeType = self::_mime_types($ext);
2168
+ if ( strlen($basedir) > 1 && substr($basedir, -1) != '/') { $basedir .= '/'; }
2169
+ if ( strlen($directory) > 1 && substr($directory, -1) != '/') { $directory .= '/'; }
2170
+ if ( $this->AddEmbeddedImage($basedir.$directory.$filename, md5($filename), $filename, 'base64', $mimeType) ) {
2171
+ $message = preg_replace("/".$images[1][$i]."=\"".preg_quote($url, '/')."\"/Ui", $images[1][$i]."=\"".$cid."\"", $message);
2172
+ }
2173
  }
2174
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2175
  }
2176
+ $this->IsHTML(true);
2177
+ $this->Body = $message;
2178
+ $textMsg = trim(strip_tags(preg_replace('/<(head|title|style|script)[^>]*>.*?<\/\\1>/s', '', $message)));
2179
+ if (!empty($textMsg) && empty($this->AltBody)) {
2180
+ $this->AltBody = html_entity_decode($textMsg);
2181
+ }
2182
+ if (empty($this->AltBody)) {
2183
+ $this->AltBody = 'To view this email message, open it in a program that understands HTML!' . "\n\n";
2184
+ }
2185
+ }
2186
+
2187
+ /**
2188
+ * Gets the MIME type of the embedded or inline image
2189
+ * @param string File extension
2190
+ * @access public
2191
+ * @return string MIME type of ext
2192
+ * @static
2193
+ */
2194
+ public static function _mime_types($ext = '') {
2195
+ $mimes = array(
2196
+ 'hqx' => 'application/mac-binhex40',
2197
+ 'cpt' => 'application/mac-compactpro',
2198
+ 'doc' => 'application/msword',
2199
+ 'bin' => 'application/macbinary',
2200
+ 'dms' => 'application/octet-stream',
2201
+ 'lha' => 'application/octet-stream',
2202
+ 'lzh' => 'application/octet-stream',
2203
+ 'exe' => 'application/octet-stream',
2204
+ 'class' => 'application/octet-stream',
2205
+ 'psd' => 'application/octet-stream',
2206
+ 'so' => 'application/octet-stream',
2207
+ 'sea' => 'application/octet-stream',
2208
+ 'dll' => 'application/octet-stream',
2209
+ 'oda' => 'application/oda',
2210
+ 'pdf' => 'application/pdf',
2211
+ 'ai' => 'application/postscript',
2212
+ 'eps' => 'application/postscript',
2213
+ 'ps' => 'application/postscript',
2214
+ 'smi' => 'application/smil',
2215
+ 'smil' => 'application/smil',
2216
+ 'mif' => 'application/vnd.mif',
2217
+ 'xls' => 'application/vnd.ms-excel',
2218
+ 'ppt' => 'application/vnd.ms-powerpoint',
2219
+ 'wbxml' => 'application/vnd.wap.wbxml',
2220
+ 'wmlc' => 'application/vnd.wap.wmlc',
2221
+ 'dcr' => 'application/x-director',
2222
+ 'dir' => 'application/x-director',
2223
+ 'dxr' => 'application/x-director',
2224
+ 'dvi' => 'application/x-dvi',
2225
+ 'gtar' => 'application/x-gtar',
2226
+ 'php' => 'application/x-httpd-php',
2227
+ 'php4' => 'application/x-httpd-php',
2228
+ 'php3' => 'application/x-httpd-php',
2229
+ 'phtml' => 'application/x-httpd-php',
2230
+ 'phps' => 'application/x-httpd-php-source',
2231
+ 'js' => 'application/x-javascript',
2232
+ 'swf' => 'application/x-shockwave-flash',
2233
+ 'sit' => 'application/x-stuffit',
2234
+ 'tar' => 'application/x-tar',
2235
+ 'tgz' => 'application/x-tar',
2236
+ 'xhtml' => 'application/xhtml+xml',
2237
+ 'xht' => 'application/xhtml+xml',
2238
+ 'zip' => 'application/zip',
2239
+ 'mid' => 'audio/midi',
2240
+ 'midi' => 'audio/midi',
2241
+ 'mpga' => 'audio/mpeg',
2242
+ 'mp2' => 'audio/mpeg',
2243
+ 'mp3' => 'audio/mpeg',
2244
+ 'aif' => 'audio/x-aiff',
2245
+ 'aiff' => 'audio/x-aiff',
2246
+ 'aifc' => 'audio/x-aiff',
2247
+ 'ram' => 'audio/x-pn-realaudio',
2248
+ 'rm' => 'audio/x-pn-realaudio',
2249
+ 'rpm' => 'audio/x-pn-realaudio-plugin',
2250
+ 'ra' => 'audio/x-realaudio',
2251
+ 'rv' => 'video/vnd.rn-realvideo',
2252
+ 'wav' => 'audio/x-wav',
2253
+ 'bmp' => 'image/bmp',
2254
+ 'gif' => 'image/gif',
2255
+ 'jpeg' => 'image/jpeg',
2256
+ 'jpg' => 'image/jpeg',
2257
+ 'jpe' => 'image/jpeg',
2258
+ 'png' => 'image/png',
2259
+ 'tiff' => 'image/tiff',
2260
+ 'tif' => 'image/tiff',
2261
+ 'css' => 'text/css',
2262
+ 'html' => 'text/html',
2263
+ 'htm' => 'text/html',
2264
+ 'shtml' => 'text/html',
2265
+ 'txt' => 'text/plain',
2266
+ 'text' => 'text/plain',
2267
+ 'log' => 'text/plain',
2268
+ 'rtx' => 'text/richtext',
2269
+ 'rtf' => 'text/rtf',
2270
+ 'xml' => 'text/xml',
2271
+ 'xsl' => 'text/xml',
2272
+ 'mpeg' => 'video/mpeg',
2273
+ 'mpg' => 'video/mpeg',
2274
+ 'mpe' => 'video/mpeg',
2275
+ 'qt' => 'video/quicktime',
2276
+ 'mov' => 'video/quicktime',
2277
+ 'avi' => 'video/x-msvideo',
2278
+ 'movie' => 'video/x-sgi-movie',
2279
+ 'doc' => 'application/msword',
2280
+ 'word' => 'application/msword',
2281
+ 'xl' => 'application/excel',
2282
+ 'eml' => 'message/rfc822'
2283
+ );
2284
+ return (!isset($mimes[strtolower($ext)])) ? 'application/octet-stream' : $mimes[strtolower($ext)];
2285
+ }
2286
+
2287
+ /**
2288
+ * Set (or reset) Class Objects (variables)
2289
+ *
2290
+ * Usage Example:
2291
+ * $page->set('X-Priority', '3');
2292
+ *
2293
+ * @access public
2294
+ * @param string $name Parameter Name
2295
+ * @param mixed $value Parameter Value
2296
+ * NOTE: will not work with arrays, there are no arrays to set/reset
2297
+ * @todo Should this not be using __set() magic function?
2298
+ */
2299
+ public function set($name, $value = '') {
2300
+ try {
2301
+ if (isset($this->$name) ) {
2302
+ $this->$name = $value;
2303
+ } else {
2304
+ throw new EM_phpmailerException($this->Lang('variable_set') . $name, self::STOP_CRITICAL);
2305
+ }
2306
+ } catch (Exception $e) {
2307
+ $this->SetError($e->getMessage());
2308
+ if ($e->getCode() == self::STOP_CRITICAL) {
2309
+ return false;
2310
+ }
2311
+ }
2312
+ return true;
2313
+ }
2314
+
2315
+ /**
2316
+ * Strips newlines to prevent header injection.
2317
+ * @access public
2318
+ * @param string $str String
2319
+ * @return string
2320
+ */
2321
+ public function SecureHeader($str) {
2322
+ $str = str_replace("\r", '', $str);
2323
+ $str = str_replace("\n", '', $str);
2324
+ return trim($str);
2325
+ }
2326
+
2327
+ /**
2328
+ * Set the private key file and password to sign the message.
2329
+ *
2330
+ * @access public
2331
+ * @param string $key_filename Parameter File Name
2332
+ * @param string $key_pass Password for private key
2333
+ */
2334
+ public function Sign($cert_filename, $key_filename, $key_pass) {
2335
+ $this->sign_cert_file = $cert_filename;
2336
+ $this->sign_key_file = $key_filename;
2337
+ $this->sign_key_pass = $key_pass;
2338
+ }
2339
+
2340
+ /**
2341
+ * Set the private key file and password to sign the message.
2342
+ *
2343
+ * @access public
2344
+ * @param string $key_filename Parameter File Name
2345
+ * @param string $key_pass Password for private key
2346
+ */
2347
+ public function DKIM_QP($txt) {
2348
+ $tmp = '';
2349
+ $line = '';
2350
+ for ($i = 0; $i < strlen($txt); $i++) {
2351
+ $ord = ord($txt[$i]);
2352
+ if ( ((0x21 <= $ord) && ($ord <= 0x3A)) || $ord == 0x3C || ((0x3E <= $ord) && ($ord <= 0x7E)) ) {
2353
+ $line .= $txt[$i];
2354
+ } else {
2355
+ $line .= "=".sprintf("%02X", $ord);
2356
+ }
2357
+ }
2358
+ return $line;
2359
+ }
2360
+
2361
+ /**
2362
+ * Generate DKIM signature
2363
+ *
2364
+ * @access public
2365
+ * @param string $s Header
2366
+ */
2367
+ public function DKIM_Sign($s) {
2368
+ $privKeyStr = file_get_contents($this->DKIM_private);
2369
+ if ($this->DKIM_passphrase != '') {
2370
+ $privKey = openssl_pkey_get_private($privKeyStr, $this->DKIM_passphrase);
2371
+ } else {
2372
+ $privKey = $privKeyStr;
2373
+ }
2374
+ if (openssl_sign($s, $signature, $privKey)) {
2375
+ return base64_encode($signature);
2376
+ }
2377
+ }
2378
+
2379
+ /**
2380
+ * Generate DKIM Canonicalization Header
2381
+ *
2382
+ * @access public
2383
+ * @param string $s Header
2384
+ */
2385
+ public function DKIM_HeaderC($s) {
2386
+ $s = preg_replace("/\r\n\s+/", " ", $s);
2387
+ $lines = explode("\r\n", $s);
2388
+ foreach ($lines as $key => $line) {
2389
+ list($heading, $value) = explode(":", $line, 2);
2390
+ $heading = strtolower($heading);
2391
+ $value = preg_replace("/\s+/", " ", $value) ; // Compress useless spaces
2392
+ $lines[$key] = $heading.":".trim($value) ; // Don't forget to remove WSP around the value
2393
+ }
2394
+ $s = implode("\r\n", $lines);
2395
+ return $s;
2396
+ }
2397
+
2398
+ /**
2399
+ * Generate DKIM Canonicalization Body
2400
+ *
2401
+ * @access public
2402
+ * @param string $body Message Body
2403
+ */
2404
+ public function DKIM_BodyC($body) {
2405
+ if ($body == '') return "\r\n";
2406
+ // stabilize line endings
2407
+ $body = str_replace("\r\n", "\n", $body);
2408
+ $body = str_replace("\n", "\r\n", $body);
2409
+ // END stabilize line endings
2410
+ while (substr($body, strlen($body) - 4, 4) == "\r\n\r\n") {
2411
+ $body = substr($body, 0, strlen($body) - 2);
2412
+ }
2413
+ return $body;
2414
+ }
2415
+
2416
+ /**
2417
+ * Create the DKIM header, body, as new header
2418
+ *
2419
+ * @access public
2420
+ * @param string $headers_line Header lines
2421
+ * @param string $subject Subject
2422
+ * @param string $body Body
2423
+ */
2424
+ public function DKIM_Add($headers_line, $subject, $body) {
2425
+ $DKIMsignatureType = 'rsa-sha1'; // Signature & hash algorithms
2426
+ $DKIMcanonicalization = 'relaxed/simple'; // Canonicalization of header/body
2427
+ $DKIMquery = 'dns/txt'; // Query method
2428
+ $DKIMtime = time() ; // Signature Timestamp = seconds since 00:00:00 - Jan 1, 1970 (UTC time zone)
2429
+ $subject_header = "Subject: $subject";
2430
+ $headers = explode($this->LE, $headers_line);
2431
+ foreach($headers as $header) {
2432
+ if (strpos($header, 'From:') === 0) {
2433
+ $from_header = $header;
2434
+ } elseif (strpos($header, 'To:') === 0) {
2435
+ $to_header = $header;
2436
+ }
2437
+ }
2438
+ $from = str_replace('|', '=7C', $this->DKIM_QP($from_header));
2439
+ $to = str_replace('|', '=7C', $this->DKIM_QP($to_header));
2440
+ $subject = str_replace('|', '=7C', $this->DKIM_QP($subject_header)) ; // Copied header fields (dkim-quoted-printable
2441
+ $body = $this->DKIM_BodyC($body);
2442
+ $DKIMlen = strlen($body) ; // Length of body
2443
+ $DKIMb64 = base64_encode(pack("H*", sha1($body))) ; // Base64 of packed binary SHA-1 hash of body
2444
+ $ident = ($this->DKIM_identity == '')? '' : " i=" . $this->DKIM_identity . ";";
2445
+ $dkimhdrs = "DKIM-Signature: v=1; a=" . $DKIMsignatureType . "; q=" . $DKIMquery . "; l=" . $DKIMlen . "; s=" . $this->DKIM_selector . ";\r\n".
2446
+ "\tt=" . $DKIMtime . "; c=" . $DKIMcanonicalization . ";\r\n".
2447
+ "\th=From:To:Subject;\r\n".
2448
+ "\td=" . $this->DKIM_domain . ";" . $ident . "\r\n".
2449
+ "\tz=$from\r\n".
2450
+ "\t|$to\r\n".
2451
+ "\t|$subject;\r\n".
2452
+ "\tbh=" . $DKIMb64 . ";\r\n".
2453
+ "\tb=";
2454
+ $toSign = $this->DKIM_HeaderC($from_header . "\r\n" . $to_header . "\r\n" . $subject_header . "\r\n" . $dkimhdrs);
2455
+ $signed = $this->DKIM_Sign($toSign);
2456
+ return "X-PHPMAILER-DKIM: phpmailer.worxware.com\r\n".$dkimhdrs.$signed."\r\n";
2457
+ }
2458
+
2459
+ protected function doCallback($isSent, $to, $cc, $bcc, $subject, $body) {
2460
+ if (!empty($this->action_function) && function_exists($this->action_function)) {
2461
+ $params = array($isSent, $to, $cc, $bcc, $subject, $body);
2462
+ call_user_func_array($this->action_function, $params);
2463
+ }
2464
+ }
2465
  }
2466
 
2467
+ class EM_phpmailerException extends Exception {
2468
+ public function errorMessage() {
2469
+ $errorMsg = '<strong>' . $this->getMessage() . "</strong><br />\n";
2470
+ return $errorMsg;
2471
+ }
2472
+ }
2473
  ?>
classes/phpmailer/class.smtp.php CHANGED
@@ -1,1045 +1,817 @@
1
  <?php
2
- ////////////////////////////////////////////////////
3
- // SMTP - PHP SMTP class
4
- //
5
- // Version 1.02
6
- //
7
- // Define an SMTP class that can be used to connect
8
- // and communicate with any SMTP server. It implements
9
- // all the SMTP functions defined in RFC821 except TURN.
10
- //
11
- // Author: Chris Ryan
12
- //
13
- // License: LGPL, see LICENSE
14
- ////////////////////////////////////////////////////
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
 
16
  /**
17
  * SMTP is rfc 821 compliant and implements all the rfc 821 SMTP
18
  * commands except TURN which will always return a not implemented
19
  * error. SMTP also provides some utility methods for sending mail
20
  * to an SMTP server.
21
- * @package PHPMailer
22
- * @author Chris Ryan
23
  */
24
- class EM_SMTP
25
- {
26
- /**
27
- * SMTP server port
28
- * @var int
29
- */
30
- var $SMTP_PORT = 25;
31
-
32
- /**
33
- * SMTP reply line ending
34
- * @var string
35
- */
36
- var $CRLF = "\r\n";
37
-
38
- /**
39
- * Sets whether debugging is turned on
40
- * @var bool
41
- */
42
- var $do_debug; # the level of debug to perform
43
-
44
- /**#@+
45
- * @access private
46
- */
47
- var $smtp_conn; # the socket to the server
48
- var $error; # error if any on the last call
49
- var $helo_rply; # the reply the server sent to us for HELO
50
- /**#@-*/
51
-
52
- /**
53
- * Initialize the class so that the data is in a known state.
54
- * @access public
55
- * @return void
56
- */
57
- function EM_SMTP() {
58
- $this->smtp_conn = 0;
59
- $this->error = null;
60
- $this->helo_rply = null;
61
 
62
- $this->do_debug = 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
63
  }
64
 
65
- /*************************************************************
66
- * CONNECTION FUNCTIONS *
67
- ***********************************************************/
68
-
69
- /**
70
- * Connect to the server specified on the port specified.
71
- * If the port is not specified use the default SMTP_PORT.
72
- * If tval is specified then a connection will try and be
73
- * established with the server for that number of seconds.
74
- * If tval is not specified the default is 30 seconds to
75
- * try on the connection.
76
- *
77
- * SMTP CODE SUCCESS: 220
78
- * SMTP CODE FAILURE: 421
79
- * @access public
80
- * @return bool
81
- */
82
- function Connect($host,$port=0,$tval=30) {
83
- # set the error val to null so there is no confusion
84
- $this->error = null;
85
-
86
- # make sure we are __not__ connected
87
- if($this->connected()) {
88
- # ok we are connected! what should we do?
89
- # for now we will just give an error saying we
90
- # are already connected
91
- $this->error =
92
- array("error" => "Already connected to a server");
93
- return false;
94
- }
95
-
96
- if(empty($port)) {
97
- $port = $this->SMTP_PORT;
98
- }
99
-
100
- #connect to the smtp server
101
- $this->smtp_conn = fsockopen($host, # the host of the server
102
- $port, # the port to use
103
- $errno, # error number if any
104
- $errstr, # error message if any
105
- $tval); # give up after ? secs
106
- # verify we connected properly
107
- if(empty($this->smtp_conn)) {
108
- $this->error = array("error" => "Failed to connect to server",
109
- "errno" => $errno,
110
- "errstr" => $errstr);
111
- if($this->do_debug >= 1) {
112
- echo "SMTP -> ERROR: " . $this->error["error"] .
113
- ": $errstr ($errno)" . $this->CRLF;
114
- }
115
- return false;
116
- }
117
 
118
- # sometimes the SMTP server takes a little longer to respond
119
- # so we will give it a longer timeout for the first read
120
- // Windows still does not have support for this timeout function
121
- if(substr(PHP_OS, 0, 3) != "WIN")
122
- socket_set_timeout($this->smtp_conn, $tval, 0);
 
 
 
 
 
 
 
 
 
 
 
123
 
124
- # get any announcement stuff
125
- $announce = $this->get_lines();
 
 
126
 
127
- # set the timeout of any socket functions at 1/10 of a second
128
- //if(function_exists("socket_set_timeout"))
129
- // socket_set_timeout($this->smtp_conn, 0, 100000);
130
 
131
- if($this->do_debug >= 2) {
132
- echo "SMTP -> FROM SERVER:" . $this->CRLF . $announce;
133
- }
134
-
135
- return true;
136
  }
137
 
138
- /**
139
- * Performs SMTP authentication. Must be run after running the
140
- * Hello() method. Returns true if successfully authenticated.
141
- * @access public
142
- * @return bool
143
- */
144
- function Authenticate($username, $password) {
145
- // Start authentication
146
- fputs($this->smtp_conn,"AUTH LOGIN" . $this->CRLF);
147
-
148
- $rply = $this->get_lines();
149
- $code = substr($rply,0,3);
150
-
151
- if($code != 334) {
152
- $this->error =
153
- array("error" => "AUTH not accepted from server",
154
- "smtp_code" => $code,
155
- "smtp_msg" => substr($rply,4));
156
- if($this->do_debug >= 1) {
157
- echo "SMTP -> ERROR: " . $this->error["error"] .
158
- ": " . $rply . $this->CRLF;
159
- }
160
- return false;
161
- }
162
 
163
- // Send encoded username
164
- fputs($this->smtp_conn, base64_encode($username) . $this->CRLF);
165
-
166
- $rply = $this->get_lines();
167
- $code = substr($rply,0,3);
168
-
169
- if($code != 334) {
170
- $this->error =
171
- array("error" => "Username not accepted from server",
172
- "smtp_code" => $code,
173
- "smtp_msg" => substr($rply,4));
174
- if($this->do_debug >= 1) {
175
- echo "SMTP -> ERROR: " . $this->error["error"] .
176
- ": " . $rply . $this->CRLF;
177
- }
178
- return false;
179
- }
180
 
181
- // Send encoded password
182
- fputs($this->smtp_conn, base64_encode($password) . $this->CRLF);
183
-
184
- $rply = $this->get_lines();
185
- $code = substr($rply,0,3);
186
-
187
- if($code != 235) {
188
- $this->error =
189
- array("error" => "Password not accepted from server",
190
- "smtp_code" => $code,
191
- "smtp_msg" => substr($rply,4));
192
- if($this->do_debug >= 1) {
193
- echo "SMTP -> ERROR: " . $this->error["error"] .
194
- ": " . $rply . $this->CRLF;
195
- }
196
- return false;
197
- }
198
 
199
- return true;
 
200
  }
201
 
202
- /**
203
- * Returns true if connected to a server otherwise false
204
- * @access private
205
- * @return bool
206
- */
207
- function Connected() {
208
- if(!empty($this->smtp_conn)) {
209
- $sock_status = socket_get_status($this->smtp_conn);
210
- if($sock_status["eof"]) {
211
- # hmm this is an odd situation... the socket is
212
- # valid but we aren't connected anymore
213
- if($this->do_debug >= 1) {
214
- echo "SMTP -> NOTICE:" . $this->CRLF .
215
- "EOF caught while checking if connected";
216
- }
217
- $this->Close();
218
- return false;
219
- }
220
- return true; # everything looks good
221
- }
222
- return false;
223
  }
224
 
225
- /**
226
- * Closes the socket and cleans up the state of the class.
227
- * It is not considered good to use this function without
228
- * first trying to use QUIT.
229
- * @access public
230
- * @return void
231
- */
232
- function Close() {
233
- $this->error = null; # so there is no confusion
234
- $this->helo_rply = null;
235
- if(!empty($this->smtp_conn)) {
236
- # close the connection and cleanup
237
- fclose($this->smtp_conn);
238
- $this->smtp_conn = 0;
239
- }
240
  }
241
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
242
 
243
- /***************************************************************
244
- * SMTP COMMANDS *
245
- *************************************************************/
246
-
247
- /**
248
- * Issues a data command and sends the msg_data to the server
249
- * finializing the mail transaction. $msg_data is the message
250
- * that is to be send with the headers. Each header needs to be
251
- * on a single line followed by a <CRLF> with the message headers
252
- * and the message body being seperated by and additional <CRLF>.
253
- *
254
- * Implements rfc 821: DATA <CRLF>
255
- *
256
- * SMTP CODE INTERMEDIATE: 354
257
- * [data]
258
- * <CRLF>.<CRLF>
259
- * SMTP CODE SUCCESS: 250
260
- * SMTP CODE FAILURE: 552,554,451,452
261
- * SMTP CODE FAILURE: 451,554
262
- * SMTP CODE ERROR : 500,501,503,421
263
- * @access public
264
- * @return bool
265
- */
266
- function Data($msg_data) {
267
- $this->error = null; # so no confusion is caused
268
-
269
- if(!$this->connected()) {
270
- $this->error = array(
271
- "error" => "Called Data() without being connected");
272
- return false;
273
- }
274
-
275
- fputs($this->smtp_conn,"DATA" . $this->CRLF);
276
-
277
- $rply = $this->get_lines();
278
- $code = substr($rply,0,3);
279
-
280
- if($this->do_debug >= 2) {
281
- echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
282
- }
283
-
284
- if($code != 354) {
285
- $this->error =
286
- array("error" => "DATA command not accepted from server",
287
- "smtp_code" => $code,
288
- "smtp_msg" => substr($rply,4));
289
- if($this->do_debug >= 1) {
290
- echo "SMTP -> ERROR: " . $this->error["error"] .
291
- ": " . $rply . $this->CRLF;
292
- }
293
- return false;
294
- }
295
 
296
- # the server is ready to accept data!
297
- # according to rfc 821 we should not send more than 1000
298
- # including the CRLF
299
- # characters on a single line so we will break the data up
300
- # into lines by \r and/or \n then if needed we will break
301
- # each of those into smaller lines to fit within the limit.
302
- # in addition we will be looking for lines that start with
303
- # a period '.' and append and additional period '.' to that
304
- # line. NOTE: this does not count towards are limit.
305
-
306
- # normalize the line breaks so we know the explode works
307
- $msg_data = str_replace("\r\n","\n",$msg_data);
308
- $msg_data = str_replace("\r","\n",$msg_data);
309
- $lines = explode("\n",$msg_data);
310
-
311
- # we need to find a good way to determine is headers are
312
- # in the msg_data or if it is a straight msg body
313
- # currently I'm assuming rfc 822 definitions of msg headers
314
- # and if the first field of the first line (':' sperated)
315
- # does not contain a space then it _should_ be a header
316
- # and we can process all lines before a blank "" line as
317
- # headers.
318
- $field = substr($lines[0],0,strpos($lines[0],":"));
319
- $in_headers = false;
320
- if(!empty($field) && !strstr($field," ")) {
321
- $in_headers = true;
322
- }
323
 
324
- $max_line_length = 998; # used below; set here for ease in change
325
-
326
- while(list(,$line) = @each($lines)) {
327
- $lines_out = null;
328
- if($line == "" && $in_headers) {
329
- $in_headers = false;
330
- }
331
- # ok we need to break this line up into several
332
- # smaller lines
333
- while(strlen($line) > $max_line_length) {
334
- $pos = strrpos(substr($line,0,$max_line_length)," ");
335
-
336
- # Patch to fix DOS attack
337
- if(!$pos) {
338
- $pos = $max_line_length - 1;
339
- }
340
-
341
- $lines_out[] = substr($line,0,$pos);
342
- $line = substr($line,$pos + 1);
343
- # if we are processing headers we need to
344
- # add a LWSP-char to the front of the new line
345
- # rfc 822 on long msg headers
346
- if($in_headers) {
347
- $line = "\t" . $line;
348
- }
349
- }
350
- $lines_out[] = $line;
351
-
352
- # now send the lines to the server
353
- while(list(,$line_out) = @each($lines_out)) {
354
- if(strlen($line_out) > 0)
355
- {
356
- if(substr($line_out, 0, 1) == ".") {
357
- $line_out = "." . $line_out;
358
- }
359
- }
360
- fputs($this->smtp_conn,$line_out . $this->CRLF);
361
- }
362
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
363
 
364
- # ok all the message data has been sent so lets get this
365
- # over with aleady
366
- fputs($this->smtp_conn, $this->CRLF . "." . $this->CRLF);
367
 
368
- $rply = $this->get_lines();
369
- $code = substr($rply,0,3);
370
 
371
- if($this->do_debug >= 2) {
372
- echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
373
- }
374
 
375
- if($code != 250) {
376
- $this->error =
377
- array("error" => "DATA not accepted from server",
378
- "smtp_code" => $code,
379
- "smtp_msg" => substr($rply,4));
380
- if($this->do_debug >= 1) {
381
- echo "SMTP -> ERROR: " . $this->error["error"] .
382
- ": " . $rply . $this->CRLF;
383
- }
384
- return false;
385
- }
386
- return true;
387
  }
388
 
389
- /**
390
- * Expand takes the name and asks the server to list all the
391
- * people who are members of the _list_. Expand will return
392
- * back and array of the result or false if an error occurs.
393
- * Each value in the array returned has the format of:
394
- * [ <full-name> <sp> ] <path>
395
- * The definition of <path> is defined in rfc 821
396
- *
397
- * Implements rfc 821: EXPN <SP> <string> <CRLF>
398
- *
399
- * SMTP CODE SUCCESS: 250
400
- * SMTP CODE FAILURE: 550
401
- * SMTP CODE ERROR : 500,501,502,504,421
402
- * @access public
403
- * @return string array
404
  */
405
- function Expand($name) {
406
- $this->error = null; # so no confusion is caused
407
-
408
- if(!$this->connected()) {
409
- $this->error = array(
410
- "error" => "Called Expand() without being connected");
411
- return false;
412
- }
413
-
414
- fputs($this->smtp_conn,"EXPN " . $name . $this->CRLF);
415
-
416
- $rply = $this->get_lines();
417
- $code = substr($rply,0,3);
418
-
419
- if($this->do_debug >= 2) {
420
- echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
421
- }
422
-
423
- if($code != 250) {
424
- $this->error =
425
- array("error" => "EXPN not accepted from server",
426
- "smtp_code" => $code,
427
- "smtp_msg" => substr($rply,4));
428
- if($this->do_debug >= 1) {
429
- echo "SMTP -> ERROR: " . $this->error["error"] .
430
- ": " . $rply . $this->CRLF;
431
- }
432
- return false;
433
- }
434
-
435
- # parse the reply and place in our array to return to user
436
- $entries = explode($this->CRLF,$rply);
437
- while(list(,$l) = @each($entries)) {
438
- $list[] = substr($l,4);
439
- }
440
-
441
- return $list;
442
- }
443
 
444
- /**
445
- * Sends the HELO command to the smtp server.
446
- * This makes sure that we and the server are in
447
- * the same known state.
448
- *
449
- * Implements from rfc 821: HELO <SP> <domain> <CRLF>
450
- *
451
- * SMTP CODE SUCCESS: 250
452
- * SMTP CODE ERROR : 500, 501, 504, 421
453
- * @access public
454
- * @return bool
 
455
  */
456
- function Hello($host="") {
457
- $this->error = null; # so no confusion is caused
458
 
459
- if(!$this->connected()) {
460
- $this->error = array(
461
- "error" => "Called Hello() without being connected");
462
- return false;
463
- }
464
 
465
- # if a hostname for the HELO wasn't specified determine
466
- # a suitable one to send
467
- if(empty($host)) {
468
- # we need to determine some sort of appopiate default
469
- # to send to the server
470
- $host = "localhost";
471
- }
472
 
473
- // Send extended hello first (RFC 2821)
474
- if(!$this->SendHello("EHLO", $host))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
475
  {
476
- if(!$this->SendHello("HELO", $host))
477
- return false;
 
478
  }
479
-
480
- return true;
481
  }
482
 
483
- /**
484
- * Sends a HELO/EHLO command.
485
- * @access private
486
- * @return bool
487
- */
488
- function SendHello($hello, $host) {
489
- fputs($this->smtp_conn, $hello . " " . $host . $this->CRLF);
490
 
491
- $rply = $this->get_lines();
492
- $code = substr($rply,0,3);
493
 
494
- if($this->do_debug >= 2) {
495
- echo "SMTP -> FROM SERVER: " . $this->CRLF . $rply;
496
- }
497
-
498
- if($code != 250) {
499
- $this->error =
500
- array("error" => $hello . " not accepted from server",
501
- "smtp_code" => $code,
502
- "smtp_msg" => substr($rply,4));
503
- if($this->do_debug >= 1) {
504
- echo "SMTP -> ERROR: " . $this->error["error"] .
505
- ": " . $rply . $this->CRLF;
506
- }
507
- return false;
508
- }
509
-
510
- $this->helo_rply = $rply;
511
-
512
- return true;
513
  }
514
 
515
- /**
516
- * Gets help information on the keyword specified. If the keyword
517
- * is not specified then returns generic help, ussually contianing
518
- * A list of keywords that help is available on. This function
519
- * returns the results back to the user. It is up to the user to
520
- * handle the returned data. If an error occurs then false is
521
- * returned with $this->error set appropiately.
522
- *
523
- * Implements rfc 821: HELP [ <SP> <string> ] <CRLF>
524
- *
525
- * SMTP CODE SUCCESS: 211,214
526
- * SMTP CODE ERROR : 500,501,502,504,421
527
- * @access public
528
- * @return string
529
- */
530
- function Help($keyword="") {
531
- $this->error = null; # to avoid confusion
532
-
533
- if(!$this->connected()) {
534
- $this->error = array(
535
- "error" => "Called Help() without being connected");
536
- return false;
537
- }
538
-
539
- $extra = "";
540
- if(!empty($keyword)) {
541
- $extra = " " . $keyword;
542
- }
543
-
544
- fputs($this->smtp_conn,"HELP" . $extra . $this->CRLF);
545
-
546
- $rply = $this->get_lines();
547
- $code = substr($rply,0,3);
548
-
549
- if($this->do_debug >= 2) {
550
- echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
551
- }
552
-
553
- if($code != 211 && $code != 214) {
554
- $this->error =
555
- array("error" => "HELP not accepted from server",
556
- "smtp_code" => $code,
557
- "smtp_msg" => substr($rply,4));
558
- if($this->do_debug >= 1) {
559
- echo "SMTP -> ERROR: " . $this->error["error"] .
560
- ": " . $rply . $this->CRLF;
561
- }
562
- return false;
563
- }
564
-
565
- return $rply;
566
  }
567
-
568
- /**
569
- * Starts a mail transaction from the email address specified in
570
- * $from. Returns true if successful or false otherwise. If True
571
- * the mail transaction is started and then one or more Recipient
572
- * commands may be called followed by a Data command.
573
- *
574
- * Implements rfc 821: MAIL <SP> FROM:<reverse-path> <CRLF>
575
- *
576
- * SMTP CODE SUCCESS: 250
577
- * SMTP CODE SUCCESS: 552,451,452
578
- * SMTP CODE SUCCESS: 500,501,421
579
- * @access public
580
- * @return bool
581
- */
582
- function Mail($from) {
583
- $this->error = null; # so no confusion is caused
584
-
585
- if(!$this->connected()) {
586
- $this->error = array(
587
- "error" => "Called Mail() without being connected");
588
- return false;
589
- }
590
-
591
- fputs($this->smtp_conn,"MAIL FROM:<" . $from . ">" . $this->CRLF);
592
-
593
- $rply = $this->get_lines();
594
- $code = substr($rply,0,3);
595
-
596
- if($this->do_debug >= 2) {
597
- echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
598
- }
599
-
600
- if($code != 250) {
601
- $this->error =
602
- array("error" => "MAIL not accepted from server",
603
- "smtp_code" => $code,
604
- "smtp_msg" => substr($rply,4));
605
- if($this->do_debug >= 1) {
606
- echo "SMTP -> ERROR: " . $this->error["error"] .
607
- ": " . $rply . $this->CRLF;
608
- }
609
- return false;
610
- }
611
- return true;
612
  }
613
 
614
- /**
615
- * Sends the command NOOP to the SMTP server.
616
- *
617
- * Implements from rfc 821: NOOP <CRLF>
618
- *
619
- * SMTP CODE SUCCESS: 250
620
- * SMTP CODE ERROR : 500, 421
621
- * @access public
622
- * @return bool
623
- */
624
- function Noop() {
625
- $this->error = null; # so no confusion is caused
626
-
627
- if(!$this->connected()) {
628
- $this->error = array(
629
- "error" => "Called Noop() without being connected");
630
- return false;
631
- }
632
-
633
- fputs($this->smtp_conn,"NOOP" . $this->CRLF);
634
-
635
- $rply = $this->get_lines();
636
- $code = substr($rply,0,3);
637
-
638
- if($this->do_debug >= 2) {
639
- echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
640
- }
641
-
642
- if($code != 250) {
643
- $this->error =
644
- array("error" => "NOOP not accepted from server",
645
- "smtp_code" => $code,
646
- "smtp_msg" => substr($rply,4));
647
- if($this->do_debug >= 1) {
648
- echo "SMTP -> ERROR: " . $this->error["error"] .
649
- ": " . $rply . $this->CRLF;
650
- }
651
- return false;
652
- }
653
- return true;
654
  }
655
 
656
- /**
657
- * Sends the quit command to the server and then closes the socket
658
- * if there is no error or the $close_on_error argument is true.
659
- *
660
- * Implements from rfc 821: QUIT <CRLF>
661
- *
662
- * SMTP CODE SUCCESS: 221
663
- * SMTP CODE ERROR : 500
664
- * @access public
665
- * @return bool
666
- */
667
- function Quit($close_on_error=true) {
668
- $this->error = null; # so there is no confusion
669
-
670
- if(!$this->connected()) {
671
- $this->error = array(
672
- "error" => "Called Quit() without being connected");
673
- return false;
674
- }
675
-
676
- # send the quit command to the server
677
- fputs($this->smtp_conn,"quit" . $this->CRLF);
678
-
679
- # get any good-bye messages
680
- $byemsg = $this->get_lines();
681
-
682
- if($this->do_debug >= 2) {
683
- echo "SMTP -> FROM SERVER:" . $this->CRLF . $byemsg;
684
- }
685
-
686
- $rval = true;
687
- $e = null;
688
-
689
- $code = substr($byemsg,0,3);
690
- if($code != 221) {
691
- # use e as a tmp var cause Close will overwrite $this->error
692
- $e = array("error" => "SMTP server rejected quit command",
693
- "smtp_code" => $code,
694
- "smtp_rply" => substr($byemsg,4));
695
- $rval = false;
696
- if($this->do_debug >= 1) {
697
- echo "SMTP -> ERROR: " . $e["error"] . ": " .
698
- $byemsg . $this->CRLF;
699
- }
700
- }
701
-
702
- if(empty($e) || $close_on_error) {
703
- $this->Close();
704
- }
705
-
706
- return $rval;
707
  }
708
 
709
- /**
710
- * Sends the command RCPT to the SMTP server with the TO: argument of $to.
711
- * Returns true if the recipient was accepted false if it was rejected.
712
- *
713
- * Implements from rfc 821: RCPT <SP> TO:<forward-path> <CRLF>
714
- *
715
- * SMTP CODE SUCCESS: 250,251
716
- * SMTP CODE FAILURE: 550,551,552,553,450,451,452
717
- * SMTP CODE ERROR : 500,501,503,421
718
- * @access public
719
- * @return bool
720
- */
721
- function Recipient($to) {
722
- $this->error = null; # so no confusion is caused
723
-
724
- if(!$this->connected()) {
725
- $this->error = array(
726
- "error" => "Called Recipient() without being connected");
727
- return false;
728
- }
729
 
730
- fputs($this->smtp_conn,"RCPT TO:<" . $to . ">" . $this->CRLF);
 
 
 
 
 
 
731
 
732
- $rply = $this->get_lines();
733
- $code = substr($rply,0,3);
734
-
735
- if($this->do_debug >= 2) {
736
- echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
737
- }
738
 
739
- if($code != 250 && $code != 251) {
740
- $this->error =
741
- array("error" => "RCPT not accepted from server",
742
- "smtp_code" => $code,
743
- "smtp_msg" => substr($rply,4));
744
- if($this->do_debug >= 1) {
745
- echo "SMTP -> ERROR: " . $this->error["error"] .
746
- ": " . $rply . $this->CRLF;
747
- }
748
- return false;
749
- }
750
- return true;
751
  }
752
 
753
- /**
754
- * Sends the RSET command to abort and transaction that is
755
- * currently in progress. Returns true if successful false
756
- * otherwise.
757
- *
758
- * Implements rfc 821: RSET <CRLF>
759
- *
760
- * SMTP CODE SUCCESS: 250
761
- * SMTP CODE ERROR : 500,501,504,421
762
- * @access public
763
- * @return bool
764
- */
765
- function Reset() {
766
- $this->error = null; # so no confusion is caused
767
-
768
- if(!$this->connected()) {
769
- $this->error = array(
770
- "error" => "Called Reset() without being connected");
771
- return false;
772
- }
773
-
774
- fputs($this->smtp_conn,"RSET" . $this->CRLF);
775
 
776
- $rply = $this->get_lines();
777
- $code = substr($rply,0,3);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
778
 
779
- if($this->do_debug >= 2) {
780
- echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
781
- }
782
 
783
- if($code != 250) {
784
- $this->error =
785
- array("error" => "RSET failed",
786
- "smtp_code" => $code,
787
- "smtp_msg" => substr($rply,4));
788
- if($this->do_debug >= 1) {
789
- echo "SMTP -> ERROR: " . $this->error["error"] .
790
- ": " . $rply . $this->CRLF;
791
- }
792
- return false;
793
- }
794
 
795
- return true;
 
796
  }
797
 
798
- /**
799
- * Starts a mail transaction from the email address specified in
800
- * $from. Returns true if successful or false otherwise. If True
801
- * the mail transaction is started and then one or more Recipient
802
- * commands may be called followed by a Data command. This command
803
- * will send the message to the users terminal if they are logged
804
- * in.
805
- *
806
- * Implements rfc 821: SEND <SP> FROM:<reverse-path> <CRLF>
807
- *
808
- * SMTP CODE SUCCESS: 250
809
- * SMTP CODE SUCCESS: 552,451,452
810
- * SMTP CODE SUCCESS: 500,501,502,421
811
- * @access public
812
- * @return bool
813
- */
814
- function Send($from) {
815
- $this->error = null; # so no confusion is caused
816
-
817
- if(!$this->connected()) {
818
- $this->error = array(
819
- "error" => "Called Send() without being connected");
820
- return false;
821
- }
822
-
823
- fputs($this->smtp_conn,"SEND FROM:" . $from . $this->CRLF);
 
 
 
 
 
 
824
 
825
- $rply = $this->get_lines();
826
- $code = substr($rply,0,3);
827
 
828
- if($this->do_debug >= 2) {
829
- echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
830
- }
831
 
832
- if($code != 250) {
833
- $this->error =
834
- array("error" => "SEND not accepted from server",
835
- "smtp_code" => $code,
836
- "smtp_msg" => substr($rply,4));
837
- if($this->do_debug >= 1) {
838
- echo "SMTP -> ERROR: " . $this->error["error"] .
839
- ": " . $rply . $this->CRLF;
840
- }
841
- return false;
842
- }
843
- return true;
844
  }
845
 
846
- /**
847
- * Starts a mail transaction from the email address specified in
848
- * $from. Returns true if successful or false otherwise. If True
849
- * the mail transaction is started and then one or more Recipient
850
- * commands may be called followed by a Data command. This command
851
- * will send the message to the users terminal if they are logged
852
- * in and send them an email.
853
- *
854
- * Implements rfc 821: SAML <SP> FROM:<reverse-path> <CRLF>
855
- *
856
- * SMTP CODE SUCCESS: 250
857
- * SMTP CODE SUCCESS: 552,451,452
858
- * SMTP CODE SUCCESS: 500,501,502,421
859
- * @access public
860
- * @return bool
861
- */
862
- function SendAndMail($from) {
863
- $this->error = null; # so no confusion is caused
864
 
865
- if(!$this->connected()) {
866
- $this->error = array(
867
- "error" => "Called SendAndMail() without being connected");
868
- return false;
869
- }
870
 
871
- fputs($this->smtp_conn,"SAML FROM:" . $from . $this->CRLF);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
872
 
873
- $rply = $this->get_lines();
874
- $code = substr($rply,0,3);
875
 
876
- if($this->do_debug >= 2) {
877
- echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
878
- }
879
 
880
- if($code != 250) {
881
- $this->error =
882
- array("error" => "SAML not accepted from server",
883
- "smtp_code" => $code,
884
- "smtp_msg" => substr($rply,4));
885
- if($this->do_debug >= 1) {
886
- echo "SMTP -> ERROR: " . $this->error["error"] .
887
- ": " . $rply . $this->CRLF;
888
- }
889
- return false;
890
- }
891
- return true;
892
  }
893
 
894
- /**
895
- * Starts a mail transaction from the email address specified in
896
- * $from. Returns true if successful or false otherwise. If True
897
- * the mail transaction is started and then one or more Recipient
898
- * commands may be called followed by a Data command. This command
899
- * will send the message to the users terminal if they are logged
900
- * in or mail it to them if they are not.
901
- *
902
- * Implements rfc 821: SOML <SP> FROM:<reverse-path> <CRLF>
903
- *
904
- * SMTP CODE SUCCESS: 250
905
- * SMTP CODE SUCCESS: 552,451,452
906
- * SMTP CODE SUCCESS: 500,501,502,421
907
- * @access public
908
- * @return bool
909
- */
910
- function SendOrMail($from) {
911
- $this->error = null; # so no confusion is caused
912
-
913
- if(!$this->connected()) {
914
- $this->error = array(
915
- "error" => "Called SendOrMail() without being connected");
916
- return false;
917
- }
918
-
919
- fputs($this->smtp_conn,"SOML FROM:" . $from . $this->CRLF);
 
 
 
 
 
 
 
920
 
921
- $rply = $this->get_lines();
922
- $code = substr($rply,0,3);
923
 
924
- if($this->do_debug >= 2) {
925
- echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
926
- }
927
 
928
- if($code != 250) {
929
- $this->error =
930
- array("error" => "SOML not accepted from server",
931
- "smtp_code" => $code,
932
- "smtp_msg" => substr($rply,4));
933
- if($this->do_debug >= 1) {
934
- echo "SMTP -> ERROR: " . $this->error["error"] .
935
- ": " . $rply . $this->CRLF;
936
- }
937
- return false;
938
- }
939
- return true;
940
  }
941
 
942
- /**
943
- * This is an optional command for SMTP that this class does not
944
- * support. This method is here to make the RFC821 Definition
945
- * complete for this class and __may__ be implimented in the future
946
- *
947
- * Implements from rfc 821: TURN <CRLF>
948
- *
949
- * SMTP CODE SUCCESS: 250
950
- * SMTP CODE FAILURE: 502
951
- * SMTP CODE ERROR : 500, 503
952
- * @access public
953
- * @return bool
954
- */
955
- function Turn() {
956
- $this->error = array("error" => "This method, TURN, of the SMTP ".
957
- "is not implemented");
958
- if($this->do_debug >= 1) {
959
- echo "SMTP -> NOTICE: " . $this->error["error"] . $this->CRLF;
960
- }
961
- return false;
962
  }
963
 
964
- /**
965
- * Verifies that the name is recognized by the server.
966
- * Returns false if the name could not be verified otherwise
967
- * the response from the server is returned.
968
- *
969
- * Implements rfc 821: VRFY <SP> <string> <CRLF>
970
- *
971
- * SMTP CODE SUCCESS: 250,251
972
- * SMTP CODE FAILURE: 550,551,553
973
- * SMTP CODE ERROR : 500,501,502,421
974
- * @access public
975
- * @return int
976
- */
977
- function Verify($name) {
978
- $this->error = null; # so no confusion is caused
979
-
980
- if(!$this->connected()) {
981
- $this->error = array(
982
- "error" => "Called Verify() without being connected");
983
- return false;
984
- }
 
 
 
 
 
 
985
 
986
- fputs($this->smtp_conn,"VRFY " . $name . $this->CRLF);
987
 
988
- $rply = $this->get_lines();
989
- $code = substr($rply,0,3);
990
 
991
- if($this->do_debug >= 2) {
992
- echo "SMTP -> FROM SERVER:" . $this->CRLF . $rply;
993
- }
994
-
995
- if($code != 250 && $code != 251) {
996
- $this->error =
997
- array("error" => "VRFY failed on name '$name'",
998
- "smtp_code" => $code,
999
- "smtp_msg" => substr($rply,4));
1000
- if($this->do_debug >= 1) {
1001
- echo "SMTP -> ERROR: " . $this->error["error"] .
1002
- ": " . $rply . $this->CRLF;
1003
- }
1004
- return false;
1005
- }
1006
- return $rply;
1007
  }
1008
 
1009
- /*******************************************************************
1010
- * INTERNAL FUNCTIONS *
1011
- ******************************************************************/
1012
-
1013
- /**
1014
- * Read in as many lines as possible
1015
- * either before eof or socket timeout occurs on the operation.
1016
- * With SMTP we can tell if we have more lines to read if the
1017
- * 4th character is '-' symbol. If it is a space then we don't
1018
- * need to read anything else.
1019
- * @access private
1020
- * @return string
1021
- */
1022
- function get_lines() {
1023
- $data = "";
1024
- while($str = fgets($this->smtp_conn,515)) {
1025
- if($this->do_debug >= 4) {
1026
- echo "SMTP -> get_lines(): \$data was \"$data\"" .
1027
- $this->CRLF;
1028
- echo "SMTP -> get_lines(): \$str is \"$str\"" .
1029
- $this->CRLF;
1030
- }
1031
- $data .= $str;
1032
- if($this->do_debug >= 4) {
1033
- echo "SMTP -> get_lines(): \$data is \"$data\"" . $this->CRLF;
1034
- }
1035
- # if the 4th character is a space then we are done reading
1036
- # so just break the loop
1037
- if(substr($str,3,1) == " ") { break; }
1038
- }
1039
- return $data;
1040
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1041
 
1042
  }
1043
 
1044
-
1045
- ?>
1
  <?php
2
+ /*~ class.smtp.php
3
+ .---------------------------------------------------------------------------.
4
+ | Software: PHPMailer - PHP email class |
5
+ | Version: 5.2 |
6
+ | Site: https://code.google.com/a/apache-extras.org/p/phpmailer/ |
7
+ | ------------------------------------------------------------------------- |
8
+ | Admin: Jim Jagielski (project admininistrator) |
9
+ | Authors: Andy Prevost (codeworxtech) codeworxtech@users.sourceforge.net |
10
+ | : Marcus Bointon (coolbru) coolbru@users.sourceforge.net |
11
+ | : Jim Jagielski (jimjag) jimjag@gmail.com |
12
+ | Founder: Brent R. Matzelle (original founder) |
13
+ | Copyright (c) 2010-2011, Jim Jagielski. All Rights Reserved. |
14
+ | Copyright (c) 2004-2009, Andy Prevost. All Rights Reserved. |
15
+ | Copyright (c) 2001-2003, Brent R. Matzelle |
16
+ | ------------------------------------------------------------------------- |
17
+ | License: Distributed under the Lesser General Public License (LGPL) |
18
+ | http://www.gnu.org/copyleft/lesser.html |
19
+ | This program is distributed in the hope that it will be useful - WITHOUT |
20
+ | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
21
+ | FITNESS FOR A PARTICULAR PURPOSE. |
22
+ '---------------------------------------------------------------------------'
23
+ */
24
+
25
+ /**
26
+ * PHPMailer - PHP SMTP email transport class
27
+ * NOTE: Designed for use with PHP version 5 and up
28
+ * @package PHPMailer
29
+ * @author Andy Prevost
30
+ * @author Marcus Bointon
31
+ * @copyright 2004 - 2008 Andy Prevost
32
+ * @author Jim Jagielski
33
+ * @copyright 2010 - 2011 Jim Jagielski
34
+ * @license http://www.gnu.org/copyleft/lesser.html Distributed under the Lesser General Public License (LGPL)
35
+ * @version $Id: class.smtp.php 450 2010-06-23 16:46:33Z coolbru $
36
+ */
37
 
38
  /**
39
  * SMTP is rfc 821 compliant and implements all the rfc 821 SMTP
40
  * commands except TURN which will always return a not implemented
41
  * error. SMTP also provides some utility methods for sending mail
42
  * to an SMTP server.
43
+ * original author: Chris Ryan
 
44
  */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
 
46
+ class EM_SMTP {
47
+ /**
48
+ * SMTP server port
49
+ * @var int
50
+ */
51
+ public $SMTP_PORT = 25;
52
+
53
+ /**
54
+ * SMTP reply line ending
55
+ * @var string
56
+ */
57
+ public $CRLF = "\r\n";
58
+
59
+ /**
60
+ * Sets whether debugging is turned on
61
+ * @var bool
62
+ */
63
+ public $do_debug; // the level of debug to perform
64
+
65
+ /**
66
+ * Sets VERP use on/off (default is off)
67
+ * @var bool
68
+ */
69
+ public $do_verp = false;
70
+
71
+ /**
72
+ * Sets the SMTP PHPMailer Version number
73
+ * @var string
74
+ */
75
+ public $Version = '5.2';
76
+
77
+ /////////////////////////////////////////////////
78
+ // PROPERTIES, PRIVATE AND PROTECTED
79
+ /////////////////////////////////////////////////
80
+
81
+ private $smtp_conn; // the socket to the server
82
+ private $error; // error if any on the last call
83
+ private $helo_rply; // the reply the server sent to us for HELO
84
+
85
+ /**
86
+ * Initialize the class so that the data is in a known state.
87
+ * @access public
88
+ * @return void
89
+ */
90
+ public function __construct() {
91
+ $this->smtp_conn = 0;
92
+ $this->error = null;
93
+ $this->helo_rply = null;
94
+
95
+ $this->do_debug = 0;
96
+ }
97
+
98
+ /////////////////////////////////////////////////
99
+ // CONNECTION FUNCTIONS
100
+ /////////////////////////////////////////////////
101
+
102
+ /**
103
+ * Connect to the server specified on the port specified.
104
+ * If the port is not specified use the default SMTP_PORT.
105
+ * If tval is specified then a connection will try and be
106
+ * established with the server for that number of seconds.
107
+ * If tval is not specified the default is 30 seconds to
108
+ * try on the connection.
109
+ *
110
+ * SMTP CODE SUCCESS: 220
111
+ * SMTP CODE FAILURE: 421
112
+ * @access public
113
+ * @return bool
114
+ */
115
+ public function Connect($host, $port = 0, $tval = 30) {
116
+ // set the error val to null so there is no confusion
117
+ $this->error = null;
118
+
119
+ // make sure we are __not__ connected
120
+ if($this->connected()) {
121
+ // already connected, generate error
122
+ $this->error = array("error" => "Already connected to a server");
123
+ return false;
124
  }
125
 
126
+ if(empty($port)) {
127
+ $port = $this->SMTP_PORT;
128
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
129
 
130
+ // connect to the smtp server
131
+ $this->smtp_conn = @fsockopen($host, // the host of the server
132
+ $port, // the port to use
133
+ $errno, // error number if any
134
+ $errstr, // error message if any
135
+ $tval); // give up after ? secs
136
+ // verify we connected properly
137
+ if(empty($this->smtp_conn)) {
138
+ $this->error = array("error" => "Failed to connect to server",
139
+ "errno" => $errno,
140
+ "errstr" => $errstr);
141
+ if($this->do_debug >= 1) {
142
+ echo "SMTP -> ERROR: " . $this->error["error"] . ": $errstr ($errno)" . $this->CRLF . '<br />';
143
+ }
144
+ return false;
145
+ }
146
 
147
+ // SMTP server can take longer to respond, give longer timeout for first read
148
+ // Windows does not have support for this timeout function
149
+ if(substr(PHP_OS, 0, 3) != "WIN")
150
+ socket_set_timeout($this->smtp_conn, $tval, 0);
151
 
152
+ // get any announcement
153
+ $announce = $this->get_lines();
 
154
 
155
+ if($this->do_debug >= 2) {
156
+ echo "SMTP -> FROM SERVER:" . $announce . $this->CRLF . '<br />';
 
 
 
157
  }
158
 
159
+ return true;
160
+ }
161
+
162
+ /**
163
+ * Initiate a TLS communication with the server.
164
+ *
165
+ * SMTP CODE 220 Ready to start TLS
166
+ * SMTP CODE 501 Syntax error (no parameters allowed)
167
+ * SMTP CODE 454 TLS not available due to temporary reason
168
+ * @access public
169
+ * @return bool success
170
+ */
171
+ public function StartTLS() {
172
+ $this->error = null; # to avoid confusion
173
+
174
+ if(!$this->connected()) {
175
+ $this->error = array("error" => "Called StartTLS() without being connected");
176
+ return false;
177
+ }
 
 
 
 
 
178
 
179
+ fputs($this->smtp_conn,"STARTTLS" . $this->CRLF);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
180
 
181
+ $rply = $this->get_lines();
182
+ $code = substr($rply,0,3);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
183
 
184
+ if($this->do_debug >= 2) {
185
+ echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />';
186
  }
187
 
188
+ if($code != 220) {
189
+ $this->error =
190
+ array("error" => "STARTTLS not accepted from server",
191
+ "smtp_code" => $code,
192
+ "smtp_msg" => substr($rply,4));
193
+ if($this->do_debug >= 1) {
194
+ echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
195
+ }
196
+ return false;
 
 
 
 
 
 
 
 
 
 
 
 
197
  }
198
 
199
+ // Begin encrypted connection
200
+ if(!stream_socket_enable_crypto($this->smtp_conn, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)) {
201
+ return false;
 
 
 
 
 
 
 
 
 
 
 
 
202
  }
203
 
204
+ return true;
205
+ }
206
+
207
+ /**
208
+ * Performs SMTP authentication. Must be run after running the
209
+ * Hello() method. Returns true if successfully authenticated.
210
+ * @access public
211
+ * @return bool
212
+ */
213
+ public function Authenticate($username, $password) {
214
+ // Start authentication
215
+ fputs($this->smtp_conn,"AUTH LOGIN" . $this->CRLF);
216
+
217
+ $rply = $this->get_lines();
218
+ $code = substr($rply,0,3);
219
+
220
+ if($code != 334) {
221
+ $this->error =
222
+ array("error" => "AUTH not accepted from server",
223
+ "smtp_code" => $code,
224
+ "smtp_msg" => substr($rply,4));
225
+ if($this->do_debug >= 1) {
226
+ echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
227
+ }
228
+ return false;
229
+ }
230
 
231
+ // Send encoded username
232
+ fputs($this->smtp_conn, base64_encode($username) . $this->CRLF);
233
+
234
+ $rply = $this->get_lines();
235
+ $code = substr($rply,0,3);
236
+
237
+ if($code != 334) {
238
+ $this->error =
239
+ array("error" => "Username not accepted from server",
240
+ "smtp_code" => $code,
241
+ "smtp_msg" => substr($rply,4));
242
+ if($this->do_debug >= 1) {
243
+ echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
244
+ }
245
+ return false;
246
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
247
 
248
+ // Send encoded password
249
+ fputs($this->smtp_conn, base64_encode($password) . $this->CRLF);
250
+
251
+ $rply = $this->get_lines();
252
+ $code = substr($rply,0,3);
253
+
254
+ if($code != 235) {
255
+ $this->error =
256
+ array("error" => "Password not accepted from server",
257
+ "smtp_code" => $code,
258
+ "smtp_msg" => substr($rply,4));
259
+ if($this->do_debug >= 1) {
260
+ echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
261
+ }
262
+ return false;
263
+ }
 
 
 
 
 
 
 
 
 
 
 
264
 
265
+ return true;
266
+ }
267
+
268
+ /**
269
+ * Returns true if connected to a server otherwise false
270
+ * @access public
271
+ * @return bool
272
+ */
273
+ public function Connected() {
274
+ if(!empty($this->smtp_conn)) {
275
+ $sock_status = socket_get_status($this->smtp_conn);
276
+ if($sock_status["eof"]) {
277
+ // the socket is valid but we are not connected
278
+ if($this->do_debug >= 1) {
279
+ echo "SMTP -> NOTICE:" . $this->CRLF . "EOF caught while checking if connected";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
280
  }
281
+ $this->Close();
282
+ return false;
283
+ }
284
+ return true; // everything looks good
285
+ }
286
+ return false;
287
+ }
288
+
289
+ /**
290
+ * Closes the socket and cleans up the state of the class.
291
+ * It is not considered good to use this function without
292
+ * first trying to use QUIT.
293
+ * @access public
294
+ * @return void
295
+ */
296
+ public function Close() {
297
+ $this->error = null; // so there is no confusion
298
+ $this->helo_rply = null;
299
+ if(!empty($this->smtp_conn)) {
300
+ // close the connection and cleanup
301
+ fclose($this->smtp_conn);
302
+ $this->smtp_conn = 0;
303
+ }
304
+ }
305
+
306
+ /////////////////////////////////////////////////
307
+ // SMTP COMMANDS
308
+ /////////////////////////////////////////////////
309
+
310
+ /**
311
+ * Issues a data command and sends the msg_data to the server
312
+ * finializing the mail transaction. $msg_data is the message
313
+ * that is to be send with the headers. Each header needs to be
314
+ * on a single line followed by a <CRLF> with the message headers
315
+ * and the message body being seperated by and additional <CRLF>.
316
+ *
317
+ * Implements rfc 821: DATA <CRLF>
318
+ *
319
+ * SMTP CODE INTERMEDIATE: 354
320
+ * [data]
321
+ * <CRLF>.<CRLF>
322
+ * SMTP CODE SUCCESS: 250
323
+ * SMTP CODE FAILURE: 552,554,451,452
324
+ * SMTP CODE FAILURE: 451,554
325
+ * SMTP CODE ERROR : 500,501,503,421
326
+ * @access public
327
+ * @return bool
328
+ */
329
+ public function Data($msg_data) {
330
+ $this->error = null; // so no confusion is caused
331
+
332
+ if(!$this->connected()) {
333
+ $this->error = array(
334
+ "error" => "Called Data() without being connected");
335
+ return false;
336
+ }
337
 
338
+ fputs($this->smtp_conn,"DATA" . $this->CRLF);
 
 
339
 
340
+ $rply = $this->get_lines();
341
+ $code = substr($rply,0,3);
342
 
343
+ if($this->do_debug >= 2) {
344
+ echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />';
345
+ }
346
 
347
+ if($code != 354) {
348
+ $this->error =
349
+ array("error" => "DATA command not accepted from server",
350
+ "smtp_code" => $code,
351
+ "smtp_msg" => substr($rply,4));
352
+ if($this->do_debug >= 1) {
353
+ echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
354
+ }
355
+ return false;
 
 
 
356
  }
357
 
358
+ /* the server is ready to accept data!
359
+ * according to rfc 821 we should not send more than 1000
360
+ * including the CRLF
361
+ * characters on a single line so we will break the data up
362
+ * into lines by \r and/or \n then if needed we will break
363
+ * each of those into smaller lines to fit within the limit.
364
+ * in addition we will be looking for lines that start with
365
+ * a period '.' and append and additional period '.' to that
366
+ * line. NOTE: this does not count towards limit.
 
 
 
 
 
 
367
  */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
368
 
369
+ // normalize the line breaks so we know the explode works
370
+ $msg_data = str_replace("\r\n","\n",$msg_data);
371
+ $msg_data = str_replace("\r","\n",$msg_data);
372
+ $lines = explode("\n",$msg_data);
373
+
374
+ /* we need to find a good way to determine is headers are
375
+ * in the msg_data or if it is a straight msg body
376
+ * currently I am assuming rfc 822 definitions of msg headers
377
+ * and if the first field of the first line (':' sperated)
378
+ * does not contain a space then it _should_ be a header
379
+ * and we can process all lines before a blank "" line as
380
+ * headers.
381
  */
 
 
382
 
383
+ $field = substr($lines[0],0,strpos($lines[0],":"));
384
+ $in_headers = false;
385
+ if(!empty($field) && !strstr($field," ")) {
386
+ $in_headers = true;
387
+ }
388
 
389
+ $max_line_length = 998; // used below; set here for ease in change
 
 
 
 
 
 
390
 
391
+ while(list(,$line) = @each($lines)) {
392
+ $lines_out = null;
393
+ if($line == "" && $in_headers) {
394
+ $in_headers = false;
395
+ }
396
+ // ok we need to break this line up into several smaller lines
397
+ while(strlen($line) > $max_line_length) {
398
+ $pos = strrpos(substr($line,0,$max_line_length)," ");
399
+
400
+ // Patch to fix DOS attack
401
+ if(!$pos) {
402
+ $pos = $max_line_length - 1;
403
+ $lines_out[] = substr($line,0,$pos);
404
+ $line = substr($line,$pos);
405
+ } else {
406
+ $lines_out[] = substr($line,0,$pos);
407
+ $line = substr($line,$pos + 1);
408
+ }
409
+
410
+ /* if processing headers add a LWSP-char to the front of new line
411
+ * rfc 822 on long msg headers
412
+ */
413
+ if($in_headers) {
414
+ $line = "\t" . $line;
415
+ }
416
+ }
417
+ $lines_out[] = $line;
418
+
419
+ // send the lines to the server
420
+ while(list(,$line_out) = @each($lines_out)) {
421
+ if(strlen($line_out) > 0)
422
  {
423
+ if(substr($line_out, 0, 1) == ".") {
424
+ $line_out = "." . $line_out;
425
+ }
426
  }
427
+ fputs($this->smtp_conn,$line_out . $this->CRLF);
428
+ }
429
  }
430
 
431
+ // message data has been sent
432
+ fputs($this->smtp_conn, $this->CRLF . "." . $this->CRLF);
 
 
 
 
 
433
 
434
+ $rply = $this->get_lines();
435
+ $code = substr($rply,0,3);
436
 
437
+ if($this->do_debug >= 2) {
438
+ echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
439
  }
440
 
441
+ if($code != 250) {
442
+ $this->error =
443
+ array("error" => "DATA not accepted from server",
444
+ "smtp_code" => $code,
445
+ "smtp_msg" => substr($rply,4));
446
+ if($this->do_debug >= 1) {
447
+ echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
448
+ }
449
+ return false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
450
  }
451
+ return true;
452
+ }
453
+
454
+ /**
455
+ * Sends the HELO command to the smtp server.
456
+ * This makes sure that we and the server are in
457
+ * the same known state.
458
+ *
459
+ * Implements from rfc 821: HELO <SP> <domain> <CRLF>
460
+ *
461
+ * SMTP CODE SUCCESS: 250
462
+ * SMTP CODE ERROR : 500, 501, 504, 421
463
+ * @access public
464
+ * @return bool
465
+ */
466
+ public function Hello($host = '') {
467
+ $this->error = null; // so no confusion is caused
468
+
469
+ if(!$this->connected()) {
470
+ $this->error = array(
471
+ "error" => "Called Hello() without being connected");
472
+ return false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
473
  }
474
 
475
+ // if hostname for HELO was not specified send default
476
+ if(empty($host)) {
477
+ // determine appropriate default to send to server
478
+ $host = "localhost";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
479
  }
480
 
481
+ // Send extended hello first (RFC 2821)
482
+ if(!$this->SendHello("EHLO", $host)) {
483
+ if(!$this->SendHello("HELO", $host)) {
484
+ return false;
485
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
486
  }
487
 
488
+ return true;
489
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
490
 
491
+ /**
492
+ * Sends a HELO/EHLO command.
493
+ * @access private
494
+ * @return bool
495
+ */
496
+ private function SendHello($hello, $host) {
497
+ fputs($this->smtp_conn, $hello . " " . $host . $this->CRLF);
498
 
499
+ $rply = $this->get_lines();
500
+ $code = substr($rply,0,3);
 
 
 
 
501
 
502
+ if($this->do_debug >= 2) {
503
+ echo "SMTP -> FROM SERVER: " . $rply . $this->CRLF . '<br />';
 
 
 
 
 
 
 
 
 
 
504
  }
505
 
506
+ if($code != 250) {
507
+ $this->error =
508
+ array("error" => $hello . " not accepted from server",
509
+ "smtp_code" => $code,
510
+ "smtp_msg" => substr($rply,4));
511
+ if($this->do_debug >= 1) {
512
+ echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
513
+ }
514
+ return false;
515
+ }
 
 
 
 
 
 
 
 
 
 
 
 
516
 
517
+ $this->helo_rply = $rply;
518
+
519
+ return true;
520
+ }
521
+
522
+ /**
523
+ * Starts a mail transaction from the email address specified in
524
+ * $from. Returns true if successful or false otherwise. If True
525
+ * the mail transaction is started and then one or more Recipient
526
+ * commands may be called followed by a Data command.
527
+ *
528
+ * Implements rfc 821: MAIL <SP> FROM:<reverse-path> <CRLF>
529
+ *
530
+ * SMTP CODE SUCCESS: 250
531
+ * SMTP CODE SUCCESS: 552,451,452
532
+ * SMTP CODE SUCCESS: 500,501,421
533
+ * @access public
534
+ * @return bool
535
+ */
536
+ public function Mail($from) {
537
+ $this->error = null; // so no confusion is caused
538
+
539
+ if(!$this->connected()) {
540
+ $this->error = array(
541
+ "error" => "Called Mail() without being connected");
542
+ return false;
543
+ }
544
 
545
+ $useVerp = ($this->do_verp ? "XVERP" : "");
546
+ fputs($this->smtp_conn,"MAIL FROM:<" . $from . ">" . $useVerp . $this->CRLF);
 
547
 
548
+ $rply = $this->get_lines();
549
+ $code = substr($rply,0,3);
 
 
 
 
 
 
 
 
 
550
 
551
+ if($this->do_debug >= 2) {
552
+ echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />';
553
  }
554
 
555
+ if($code != 250) {
556
+ $this->error =
557
+ array("error" => "MAIL not accepted from server",
558
+ "smtp_code" => $code,
559
+ "smtp_msg" => substr($rply,4));
560
+ if($this->do_debug >= 1) {
561
+ echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
562
+ }
563
+ return false;
564
+ }
565
+ return true;
566
+ }
567
+
568
+ /**
569
+ * Sends the quit command to the server and then closes the socket
570
+ * if there is no error or the $close_on_error argument is true.
571
+ *
572
+ * Implements from rfc 821: QUIT <CRLF>
573
+ *
574
+ * SMTP CODE SUCCESS: 221
575
+ * SMTP CODE ERROR : 500
576
+ * @access public
577
+ * @return bool
578
+ */
579
+ public function Quit($close_on_error = true) {
580
+ $this->error = null; // so there is no confusion
581
+
582
+ if(!$this->connected()) {
583
+ $this->error = array(
584
+ "error" => "Called Quit() without being connected");
585
+ return false;
586
+ }
587
 
588
+ // send the quit command to the server
589
+ fputs($this->smtp_conn,"quit" . $this->CRLF);
590
 
591
+ // get any good-bye messages
592
+ $byemsg = $this->get_lines();
 
593
 
594
+ if($this->do_debug >= 2) {
595
+ echo "SMTP -> FROM SERVER:" . $byemsg . $this->CRLF . '<br />';
 
 
 
 
 
 
 
 
 
 
596
  }
597
 
598
+ $rval = true;
599
+ $e = null;
600
+
601
+ $code = substr($byemsg,0,3);
602
+ if($code != 221) {
603
+ // use e as a tmp var cause Close will overwrite $this->error
604
+ $e = array("error" => "SMTP server rejected quit command",
605
+ "smtp_code" => $code,
606
+ "smtp_rply" => substr($byemsg,4));
607
+ $rval = false;
608
+ if($this->do_debug >= 1) {
609
+ echo "SMTP -> ERROR: " . $e["error"] . ": " . $byemsg . $this->CRLF . '<br />';
610
+ }
611
+ }
 
 
 
 
612
 
613
+ if(empty($e) || $close_on_error) {
614
+ $this->Close();
615
+ }
 
 
616
 
617
+ return $rval;
618
+ }
619
+
620
+ /**
621
+ * Sends the command RCPT to the SMTP server with the TO: argument of $to.
622
+ * Returns true if the recipient was accepted false if it was rejected.
623
+ *
624
+ * Implements from rfc 821: RCPT <SP> TO:<forward-path> <CRLF>
625
+ *
626
+ * SMTP CODE SUCCESS: 250,251
627
+ * SMTP CODE FAILURE: 550,551,552,553,450,451,452
628
+ * SMTP CODE ERROR : 500,501,503,421
629
+ * @access public
630
+ * @return bool
631
+ */
632
+ public function Recipient($to) {
633
+ $this->error = null; // so no confusion is caused
634
+
635
+ if(!$this->connected()) {
636
+ $this->error = array(
637
+ "error" => "Called Recipient() without being connected");
638
+ return false;
639
+ }
640
 
641
+ fputs($this->smtp_conn,"RCPT TO:<" . $to . ">" . $this->CRLF);
 
642
 
643
+ $rply = $this->get_lines();
644
+ $code = substr($rply,0,3);
 
645
 
646
+ if($this->do_debug >= 2) {
647
+ echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />';
 
 
 
 
 
 
 
 
 
 
648
  }
649
 
650
+ if($code != 250 && $code != 251) {
651
+ $this->error =
652
+ array("error" => "RCPT not accepted from server",
653
+ "smtp_code" => $code,
654
+ "smtp_msg" => substr($rply,4));
655
+ if($this->do_debug >= 1) {
656
+ echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
657
+ }
658
+ return false;
659
+ }
660
+ return true;
661
+ }
662
+
663
+ /**
664
+ * Sends the RSET command to abort and transaction that is
665
+ * currently in progress. Returns true if successful false
666
+ * otherwise.
667
+ *
668
+ * Implements rfc 821: RSET <CRLF>
669
+ *
670
+ * SMTP CODE SUCCESS: 250
671
+ * SMTP CODE ERROR : 500,501,504,421
672
+ * @access public
673
+ * @return bool
674
+ */
675
+ public function Reset() {
676
+ $this->error = null; // so no confusion is caused
677
+
678
+ if(!$this->connected()) {
679
+ $this->error = array(
680
+ "error" => "Called Reset() without being connected");
681
+ return false;
682
+ }
683
 
684
+ fputs($this->smtp_conn,"RSET" . $this->CRLF);
 
685
 
686
+ $rply = $this->get_lines();
687
+ $code = substr($rply,0,3);
 
688
 
689
+ if($this->do_debug >= 2) {
690
+ echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />';
 
 
 
 
 
 
 
 
 
 
691
  }
692
 
693
+ if($code != 250) {
694
+ $this->error =
695
+ array("error" => "RSET failed",
696
+ "smtp_code" => $code,
697
+ "smtp_msg" => substr($rply,4));
698
+ if($this->do_debug >= 1) {
699
+ echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
700
+ }
701
+ return false;
 
 
 
 
 
 
 
 
 
 
 
702
  }
703
 
704
+ return true;
705
+ }
706
+
707
+ /**
708
+ * Starts a mail transaction from the email address specified in
709
+ * $from. Returns true if successful or false otherwise. If True
710
+ * the mail transaction is started and then one or more Recipient
711
+ * commands may be called followed by a Data command. This command
712
+ * will send the message to the users terminal if they are logged
713
+ * in and send them an email.
714
+ *
715
+ * Implements rfc 821: SAML <SP> FROM:<reverse-path> <CRLF>
716
+ *
717
+ * SMTP CODE SUCCESS: 250
718
+ * SMTP CODE SUCCESS: 552,451,452
719
+ * SMTP CODE SUCCESS: 500,501,502,421
720
+ * @access public
721
+ * @return bool
722
+ */
723
+ public function SendAndMail($from) {
724
+ $this->error = null; // so no confusion is caused
725
+
726
+ if(!$this->connected()) {
727
+ $this->error = array(
728
+ "error" => "Called SendAndMail() without being connected");
729
+ return false;
730
+ }
731
 
732
+ fputs($this->smtp_conn,"SAML FROM:" . $from . $this->CRLF);
733
 
734
+ $rply = $this->get_lines();
735
+ $code = substr($rply,0,3);
736
 
737
+ if($this->do_debug >= 2) {
738
+ echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '<br />';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
739
  }
740
 
741
+ if($code != 250) {
742
+ $this->error =
743
+ array("error" => "SAML not accepted from server",
744
+ "smtp_code" => $code,
745
+ "smtp_msg" => substr($rply,4));
746
+ if($this->do_debug >= 1) {
747
+ echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '<br />';
748
+ }
749
+ return false;
750
+ }
751
+ return true;
752
+ }
753
+
754
+ /**
755
+ * This is an optional command for SMTP that this class does not
756
+ * support. This method is here to make the RFC821 Definition
757
+ * complete for this class and __may__ be implimented in the future
758
+ *
759
+ * Implements from rfc 821: TURN <CRLF>
760
+ *
761
+ * SMTP CODE SUCCESS: 250
762
+ * SMTP CODE FAILURE: 502
763
+ * SMTP CODE ERROR : 500, 503
764
+ * @access public
765
+ * @return bool
766
+ */
767
+ public function Turn() {
768
+ $this->error = array("error" => "This method, TURN, of the SMTP ".
769
+ "is not implemented");
770
+ if($this->do_debug >= 1) {
771
+ echo "SMTP -> NOTICE: " . $this->error["error"] . $this->CRLF . '<br />';
772
  }
773
+ return false;
774
+ }
775
+
776
+ /**
777
+ * Get the current error
778
+ * @access public
779
+ * @return array
780
+ */
781
+ public function getError() {
782
+ return $this->error;
783
+ }
784
+
785
+ /////////////////////////////////////////////////
786
+ // INTERNAL FUNCTIONS
787
+ /////////////////////////////////////////////////
788
+
789
+ /**
790
+ * Read in as many lines as possible
791
+ * either before eof or socket timeout occurs on the operation.
792
+ * With SMTP we can tell if we have more lines to read if the
793
+ * 4th character is '-' symbol. If it is a space then we don't
794
+ * need to read anything else.
795
+ * @access private
796
+ * @return string
797
+ */
798
+ private function get_lines() {
799
+ $data = "";
800
+ while($str = @fgets($this->smtp_conn,515)) {
801
+ if($this->do_debug >= 4) {
802
+ echo "SMTP -> get_lines(): \$data was \"$data\"" . $this->CRLF . '<br />';
803
+ echo "SMTP -> get_lines(): \$str is \"$str\"" . $this->CRLF . '<br />';
804
+ }
805
+ $data .= $str;
806
+ if($this->do_debug >= 4) {
807
+ echo "SMTP -> get_lines(): \$data is \"$data\"" . $this->CRLF . '<br />';
808
+ }
809
+ // if 4th character is a space, we are done reading, break the loop
810
+ if(substr($str,3,1) == " ") { break; }
811
+ }
812
+ return $data;
813
+ }
814
 
815
  }
816
 
817
+ ?>
 
classes/phpmailer/language/phpmailer.lang-ar.php ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * PHPMailer language file: refer to English translation for definitive list
4
+ * Arabic Version, UTF-8
5
+ * by : bahjat al mostafa <bahjat983@hotmail.com>
6
+ */
7
+
8
+ $PHPMAILER_LANG['authenticate'] = 'SMTP Error: لم نستطع تأكيد الهوية.';
9
+ $PHPMAILER_LANG['connect_host'] = 'SMTP Error: لم نستطع الاتصال بمخدم SMTP.';
10
+ $PHPMAILER_LANG['data_not_accepted'] = 'SMTP Error: لم يتم قبول المعلومات .';
11
+ //$PHPMAILER_LANG['empty_message'] = 'Message body empty';
12
+ $PHPMAILER_LANG['encoding'] = 'ترميز غير معروف: ';
13
+ $PHPMAILER_LANG['execute'] = 'لم أستطع تنفيذ : ';
14
+ $PHPMAILER_LANG['file_access'] = 'لم نستطع الوصول للملف: ';
15
+ $PHPMAILER_LANG['file_open'] = 'File Error: لم نستطع فتح الملف: ';
16
+ $PHPMAILER_LANG['from_failed'] = 'البريد التالي لم نستطع ارسال البريد له : ';
17
+ $PHPMAILER_LANG['instantiate'] = 'لم نستطع توفير خدمة البريد.';
18
+ //$PHPMAILER_LANG['invalid_email'] = 'Not sending, email address is invalid: ';
19
+ $PHPMAILER_LANG['mailer_not_supported'] = ' mailer غير مدعوم.';
20
+ //$PHPMAILER_LANG['provide_address'] = 'You must provide at least one recipient email address.';
21
+ $PHPMAILER_LANG['recipients_failed'] = 'SMTP Error: الأخطاء التالية ' .
22
+ 'فشل في الارسال لكل من : ';
23
+ $PHPMAILER_LANG['signing'] = 'خطأ في التوقيع: ';
24
+ //$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() failed.';
25
+ //$PHPMAILER_LANG['smtp_error'] = 'SMTP server error: ';
26
+ //$PHPMAILER_LANG['variable_set'] = 'Cannot set or reset variable: ';
27
+ ?>
classes/phpmailer/language/phpmailer.lang-br.php CHANGED
@@ -1,21 +1,26 @@
1
  <?php
2
  /**
3
- * PHPMailer language file.
4
- * Portuguese Version
5
- * By Paulo Henrique Garcia - paulo@controllerweb.com.br
6
- */
7
 
8
- $PHPMAILER_LANG = array();
9
- $PHPMAILER_LANG["provide_address"] = 'Voc� deve fornecer pelo menos um endere�o de destinat�rio de email.';
10
- $PHPMAILER_LANG["mailer_not_supported"] = ' mailer n�o suportado.';
11
- $PHPMAILER_LANG["execute"] = 'N�o foi poss�vel executar: ';
12
- $PHPMAILER_LANG["instantiate"] = 'N�o foi poss�vel instanciar a fun��o mail.';
13
- $PHPMAILER_LANG["authenticate"] = 'Erro de SMTP: N�o foi poss�vel autenticar.';
14
- $PHPMAILER_LANG["from_failed"] = 'Os endere�os de rementente a seguir falharam: ';
15
- $PHPMAILER_LANG["recipients_failed"] = 'Erro de SMTP: Os endere�os de destinat�rio a seguir falharam: ';
16
- $PHPMAILER_LANG["data_not_accepted"] = 'Erro de SMTP: Dados n�o aceitos.';
17
- $PHPMAILER_LANG["connect_host"] = 'Erro de SMTP: N�o foi poss�vel conectar com o servidor SMTP.';
18
- $PHPMAILER_LANG["file_access"] = 'N�o foi poss�vel acessar o arquivo: ';
19
- $PHPMAILER_LANG["file_open"] = 'Erro de Arquivo: N�o foi poss�vel abrir o arquivo: ';
20
- $PHPMAILER_LANG["encoding"] = 'Codifica��o desconhecida: ';
21
- ?>
 
 
 
 
 
1
  <?php
2
  /**
3
+ * PHPMailer language file: refer to English translation for definitive list
4
+ * Portuguese Version
5
+ * By Paulo Henrique Garcia - paulo@controllerweb.com.br
6
+ */
7
 
8
+ $PHPMAILER_LANG['authenticate'] = 'Erro de SMTP: Não foi possível autenticar.';
9
+ $PHPMAILER_LANG['connect_host'] = 'Erro de SMTP: Não foi possível conectar com o servidor SMTP.';
10
+ $PHPMAILER_LANG['data_not_accepted'] = 'Erro de SMTP: Dados não aceitos.';
11
+ //$PHPMAILER_LANG['empty_message'] = 'Message body empty';
12
+ $PHPMAILER_LANG['encoding'] = 'Codificação desconhecida: ';
13
+ $PHPMAILER_LANG['execute'] = 'Não foi possível executar: ';
14
+ $PHPMAILER_LANG['file_access'] = 'Não foi possível acessar o arquivo: ';
15
+ $PHPMAILER_LANG['file_open'] = 'Erro de Arquivo: Não foi possível abrir o arquivo: ';
16
+ $PHPMAILER_LANG['from_failed'] = 'Os endereços de rementente a seguir falharam: ';
17
+ $PHPMAILER_LANG['instantiate'] = 'Não foi possível instanciar a função mail.';
18
+ //$PHPMAILER_LANG['invalid_email'] = 'Not sending, email address is invalid: ';
19
+ $PHPMAILER_LANG['mailer_not_supported'] = ' mailer não suportado.';
20
+ $PHPMAILER_LANG['provide_address'] = 'Você deve fornecer pelo menos um endereço de destinatário de email.';
21
+ $PHPMAILER_LANG['recipients_failed'] = 'Erro de SMTP: Os endereços de destinatário a seguir falharam: ';
22
+ //$PHPMAILER_LANG['signing'] = 'Signing Error: ';
23
+ //$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() failed.';
24
+ //$PHPMAILER_LANG['smtp_error'] = 'SMTP server error: ';
25
+ //$PHPMAILER_LANG['variable_set'] = 'Cannot set or reset variable: ';
26
+ ?>
classes/phpmailer/language/phpmailer.lang-ca.php CHANGED
@@ -1,22 +1,26 @@
1
  <?php
2
  /**
3
- * PHPMailer language file.
4
- * Catalan Version
5
- * By Ivan: web AT microstudi DOT com
6
- */
7
 
8
- $PHPMAILER_LANG = array();
9
-
10
- $PHPMAILER_LANG["provide_address"] = 'S\'ha de proveir almenys una adre�a d\'email com a destinatari.';
11
- $PHPMAILER_LANG["mailer_not_supported"] = ' mailer no est� suportat';
12
- $PHPMAILER_LANG["execute"] = 'No es pot executar: ';
13
- $PHPMAILER_LANG["instantiate"] = 'No s\'ha pogut crear una inst�ncia de la funci� Mail.';
14
- $PHPMAILER_LANG["authenticate"] = 'Error SMTP: No s\'hapogut autenticar.';
15
- $PHPMAILER_LANG["from_failed"] = 'La(s) seg�ent(s) adreces de remitent han fallat: ';
16
- $PHPMAILER_LANG["recipients_failed"] = 'Error SMTP: Els seg�ents destinataris han fallat: ';
17
- $PHPMAILER_LANG["data_not_accepted"] = 'Error SMTP: Dades no acceptades.';
18
- $PHPMAILER_LANG["connect_host"] = 'Error SMTP: No es pot connectar al servidor SMTP.';
19
- $PHPMAILER_LANG["file_access"] = 'No es pot accedir a l\'arxiu: ';
20
- $PHPMAILER_LANG["file_open"] = 'Error d\'Arxiu: No es pot obrir l\'arxiu: ';
21
- $PHPMAILER_LANG["encoding"] = 'Codificaci� desconeguda: ';
 
 
 
 
22
  ?>
1
  <?php
2
  /**
3
+ * PHPMailer language file: refer to English translation for definitive list
4
+ * Catalan Version
5
+ * By Ivan: web AT microstudi DOT com
6
+ */
7
 
8
+ $PHPMAILER_LANG['authenticate'] = 'Error SMTP: No s\'hapogut autenticar.';
9
+ $PHPMAILER_LANG['connect_host'] = 'Error SMTP: No es pot connectar al servidor SMTP.';
10
+ $PHPMAILER_LANG['data_not_accepted'] = 'Error SMTP: Dades no acceptades.';
11
+ //$PHPMAILER_LANG['empty_message'] = 'Message body empty';
12
+ $PHPMAILER_LANG['encoding'] = 'Codificació desconeguda: ';
13
+ $PHPMAILER_LANG['execute'] = 'No es pot executar: ';
14
+ $PHPMAILER_LANG['file_access'] = 'No es pot accedir a l\'arxiu: ';
15
+ $PHPMAILER_LANG['file_open'] = 'Error d\'Arxiu: No es pot obrir l\'arxiu: ';
16
+ $PHPMAILER_LANG['from_failed'] = 'La(s) següent(s) adreces de remitent han fallat: ';
17
+ $PHPMAILER_LANG['instantiate'] = 'No s\'ha pogut crear una instància de la funció Mail.';
18
+ //$PHPMAILER_LANG['invalid_email'] = 'Not sending, email address is invalid: ';
19
+ $PHPMAILER_LANG['mailer_not_supported'] = ' mailer no està suportat';
20
+ $PHPMAILER_LANG['provide_address'] = 'S\'ha de proveir almenys una adreça d\'email com a destinatari.';
21
+ $PHPMAILER_LANG['recipients_failed'] = 'Error SMTP: Els següents destinataris han fallat: ';
22
+ //$PHPMAILER_LANG['signing'] = 'Signing Error: ';
23
+ //$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() failed.';
24
+ //$PHPMAILER_LANG['smtp_error'] = 'SMTP server error: ';
25
+ //$PHPMAILER_LANG['variable_set'] = 'Cannot set or reset variable: ';
26
  ?>
classes/phpmailer/language/phpmailer.lang-ch.php ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * PHPMailer language file: refer to English translation for definitive list
4
+ * Chinese Version
5
+ * By LiuXin: www.80x86.cn/blog/
6
+ */
7
+
8
+ $PHPMAILER_LANG['authenticate'] = 'SMTP 错误:身份验证失败。';
9
+ $PHPMAILER_LANG['connect_host'] = 'SMTP 错误: 不能连接SMTP主机。';
10
+ $PHPMAILER_LANG['data_not_accepted'] = 'SMTP 错误: 数据不可接受。';
11
+ //$PHPMAILER_LANG['empty_message'] = 'Message body empty';
12
+ $PHPMAILER_LANG['encoding'] = '未知编码:';
13
+ $PHPMAILER_LANG['execute'] = '不能执行: ';
14
+ $PHPMAILER_LANG['file_access'] = '不能访问文件:';
15
+ $PHPMAILER_LANG['file_open'] = '文件错误:不能打开文件:';
16
+ $PHPMAILER_LANG['from_failed'] = '下面的发送地址邮件发送失败了: ';
17
+ $PHPMAILER_LANG['instantiate'] = '不能实现mail方法。';
18
+ //$PHPMAILER_LANG['invalid_email'] = 'Not sending, email address is invalid: ';
19
+ $PHPMAILER_LANG['mailer_not_supported'] = ' 您所选择的发送邮件的方法并不支持。';
20
+ $PHPMAILER_LANG['provide_address'] = '您必须提供至少一个 收信人的email地址。';
21
+ $PHPMAILER_LANG['recipients_failed'] = 'SMTP 错误: 下面的 收件人失败了: ';
22
+ //$PHPMAILER_LANG['signing'] = 'Signing Error: ';
23
+ //$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() failed.';
24
+ //$PHPMAILER_LANG['smtp_error'] = 'SMTP server error: ';
25
+ //$PHPMAILER_LANG['variable_set'] = 'Cannot set or reset variable: ';
26
+ ?>
classes/phpmailer/language/phpmailer.lang-cz.php CHANGED
@@ -1,24 +1,25 @@
1
  <?php
2
  /**
3
- * PHPMailer language file.
4
- * Czech Version
5
- */
6
 
7
- $PHPMAILER_LANG = array();
8
-
9
- $PHPMAILER_LANG["provide_address"] = 'Mus�te zadat alespo� jednu ' .
10
- 'emailovou adresu p��jemce.';
11
- $PHPMAILER_LANG["mailer_not_supported"] = ' mailov� klient nen� podporov�n.';
12
- $PHPMAILER_LANG["execute"] = 'Nelze prov�st: ';
13
- $PHPMAILER_LANG["instantiate"] = 'Nelze vytvo�it instanci emailov� funkce.';
14
- $PHPMAILER_LANG["authenticate"] = 'SMTP Error: Chyba autentikace.';
15
- $PHPMAILER_LANG["from_failed"] = 'N�sleduj�c� adresa From je nespr�vn�: ';
16
- $PHPMAILER_LANG["recipients_failed"] = 'SMTP Error: Adresy p��jemc� ' .
17
- 'nejsou spr�vn� ' .
18
- $PHPMAILER_LANG["data_not_accepted"] = 'SMTP Error: Data nebyla p�ijata';
19
- $PHPMAILER_LANG["connect_host"] = 'SMTP Error: Nelze nav�zat spojen� se ' .
20
- ' SMTP serverem.';
21
- $PHPMAILER_LANG["file_access"] = 'Soubor nenalezen: ';
22
- $PHPMAILER_LANG["file_open"] = 'File Error: Nelze otev��t soubor pro �ten�: ';
23
- $PHPMAILER_LANG["encoding"] = 'Nezn�m� k�dov�n�: ';
 
24
  ?>
1
  <?php
2
  /**
3
+ * PHPMailer language file: refer to English translation for definitive list
4
+ * Czech Version
5
+ */
6
 
7
+ $PHPMAILER_LANG['authenticate'] = 'SMTP Error: Chyba autentikace.';
8
+ $PHPMAILER_LANG['connect_host'] = 'SMTP Error: Nelze navázat spojení se SMTP serverem.';
9
+ $PHPMAILER_LANG['data_not_accepted'] = 'SMTP Error: Data nebyla pøijata';
10
+ //$PHPMAILER_LANG['empty_message'] = 'Message body empty';
11
+ $PHPMAILER_LANG['encoding'] = 'Neznámé kódování: ';
12
+ $PHPMAILER_LANG['execute'] = 'Nelze provést: ';
13
+ $PHPMAILER_LANG['file_access'] = 'Soubor nenalezen: ';
14
+ $PHPMAILER_LANG['file_open'] = 'File Error: Nelze otevøít soubor pro ètení: ';
15
+ $PHPMAILER_LANG['from_failed'] = 'Následující adresa From je nesprávná: ';
16
+ $PHPMAILER_LANG['instantiate'] = 'Nelze vytvoøit instanci emailové funkce.';
17
+ //$PHPMAILER_LANG['invalid_email'] = 'Not sending, email address is invalid: ';
18
+ $PHPMAILER_LANG['mailer_not_supported'] = ' mailový klient není podporován.';
19
+ $PHPMAILER_LANG['provide_address'] = 'Musíte zadat alespoò jednu emailovou adresu pøíjemce.';
20
+ $PHPMAILER_LANG['recipients_failed'] = 'SMTP Error: Adresy pøíjemcù nejsou správné ';
21
+ //$PHPMAILER_LANG['signing'] = 'Signing Error: ';
22
+ //$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() failed.';
23
+ //$PHPMAILER_LANG['smtp_error'] = 'SMTP server error: ';
24
+ //$PHPMAILER_LANG['variable_set'] = 'Cannot set or reset variable: ';
25
  ?>
classes/phpmailer/language/phpmailer.lang-de.php CHANGED
@@ -1,23 +1,25 @@
1
  <?php
2
  /**
3
- * PHPMailer language file.
4
- * German Version
5
- */
6
 
7
- $PHPMAILER_LANG = array();
8
-
9
- $PHPMAILER_LANG["provide_address"] = 'Bitte geben Sie mindestens eine ' .
10
- 'Empf&auml;nger Emailadresse an.';
11
- $PHPMAILER_LANG["mailer_not_supported"] = ' mailer wird nicht unterst&uuml;tzt.';
12
- $PHPMAILER_LANG["execute"] = 'Konnte folgenden Befehl nicht ausf&uuml;hren: ';
13
- $PHPMAILER_LANG["instantiate"] = 'Mail Funktion konnte nicht initialisiert werden.';
14
- $PHPMAILER_LANG["authenticate"] = 'SMTP Fehler: Authentifizierung fehlgeschlagen.';
15
- $PHPMAILER_LANG["from_failed"] = 'Die folgende Absenderadresse ist nicht korrekt: ';
16
- $PHPMAILER_LANG["recipients_failed"] = 'SMTP Fehler: Die folgenden ' .
17
- 'Empf&auml;nger sind nicht korrekt: ';
18
- $PHPMAILER_LANG["data_not_accepted"] = 'SMTP Fehler: Daten werden nicht akzeptiert.';
19
- $PHPMAILER_LANG["connect_host"] = 'SMTP Fehler: Konnte keine Verbindung zum SMTP-Host herstellen.';
20
- $PHPMAILER_LANG["file_access"] = 'Zugriff auf folgende Datei fehlgeschlagen: ';
21
- $PHPMAILER_LANG["file_open"] = 'Datei Fehler: konnte folgende Datei nicht &ouml;ffnen: ';
22
- $PHPMAILER_LANG["encoding"] = 'Unbekanntes Encoding-Format: ';
23
- ?>
 
 
1
  <?php
2
  /**
3
+ * PHPMailer language file: refer to English translation for definitive list
4
+ * German Version
5
+ */
6
 
7
+ $PHPMAILER_LANG['authenticate'] = 'SMTP Fehler: Authentifizierung fehlgeschlagen.';
8
+ $PHPMAILER_LANG['connect_host'] = 'SMTP Fehler: Konnte keine Verbindung zum SMTP-Host herstellen.';
9
+ $PHPMAILER_LANG['data_not_accepted'] = 'SMTP Fehler: Daten werden nicht akzeptiert.';
10
+ $PHPMAILER_LANG['empty_message'] = 'E-Mail Inhalt ist leer.';
11
+ $PHPMAILER_LANG['encoding'] = 'Unbekanntes Encoding-Format: ';
12
+ $PHPMAILER_LANG['execute'] = 'Konnte folgenden Befehl nicht ausführen: ';
13
+ $PHPMAILER_LANG['file_access'] = 'Zugriff auf folgende Datei fehlgeschlagen: ';
14
+ $PHPMAILER_LANG['file_open'] = 'Datei Fehler: konnte folgende Datei nicht öffnen: ';
15
+ $PHPMAILER_LANG['from_failed'] = 'Die folgende Absenderadresse ist nicht korrekt: ';
16
+ $PHPMAILER_LANG['instantiate'] = 'Mail Funktion konnte nicht initialisiert werden.';
17
+ $PHPMAILER_LANG['invalid_email'] = 'E-Mail wird nicht gesendet, die Adresse ist ungültig.';
18
+ $PHPMAILER_LANG['mailer_not_supported'] = ' mailer wird nicht unterstützt.';
19
+ $PHPMAILER_LANG['provide_address'] = 'Bitte geben Sie mindestens eine Empfänger E-Mailadresse an.';
20
+ $PHPMAILER_LANG['recipients_failed'] = 'SMTP Fehler: Die folgenden Empfänger sind nicht korrekt: ';
21
+ $PHPMAILER_LANG['signing'] = 'Fehler beim Signieren: ';
22
+ $PHPMAILER_LANG['smtp_connect_failed'] = 'Verbindung zu SMTP Server fehlgeschlagen.';
23
+ $PHPMAILER_LANG['smtp_error'] = 'Fehler vom SMTP Server: ';
24
+ $PHPMAILER_LANG['variable_set'] = 'Kann Variable nicht setzen oder zurücksetzen: ';
25
+ ?>
classes/phpmailer/language/phpmailer.lang-dk.php CHANGED
@@ -1,24 +1,26 @@
1
  <?php
2
  /**
3
- * PHPMailer language file.
4
- * Danish Version
5
- * Author: Mikael Stokkebro <info@stokkebro.dk>
6
- */
7
 
8
- $PHPMAILER_LANG = array();
9
-
10
- $PHPMAILER_LANG["provide_address"] = 'Du skal indtaste mindst en ' .
11
- 'modtagers emailadresse.';
12
- $PHPMAILER_LANG["mailer_not_supported"] = ' mailer underst�ttes ikke.';
13
- $PHPMAILER_LANG["execute"] = 'Kunne ikke k�re: ';
14
- $PHPMAILER_LANG["instantiate"] = 'Kunne ikke initialisere email funktionen.';
15
- $PHPMAILER_LANG["authenticate"] = 'SMTP fejl: Kunne ikke logge p�.';
16
- $PHPMAILER_LANG["from_failed"] = 'F�lgende afsenderadresse er forkert: ';
17
- $PHPMAILER_LANG["recipients_failed"] = 'SMTP fejl: F�lgende' .
18
- 'modtagere er forkerte: ';
19
- $PHPMAILER_LANG["data_not_accepted"] = 'SMTP fejl: Data kunne ikke accepteres.';
20
- $PHPMAILER_LANG["connect_host"] = 'SMTP fejl: Kunne ikke tilslutte SMTP serveren.';
21
- $PHPMAILER_LANG["file_access"] = 'Ingen adgang til fil: ';
22
- $PHPMAILER_LANG["file_open"] = 'Fil fejl: Kunne ikke �bne filen: ';
23
- $PHPMAILER_LANG["encoding"] = 'Ukendt encode-format: ';
 
 
24
  ?>
1
  <?php
2
  /**
3
+ * PHPMailer language file: refer to English translation for definitive list
4
+ * Danish Version
5
+ * Author: Mikael Stokkebro <info@stokkebro.dk>
6
+ */
7
 
8
+ $PHPMAILER_LANG['authenticate'] = 'SMTP fejl: Kunne ikke logge på.';
9
+ $PHPMAILER_LANG['connect_host'] = 'SMTP fejl: Kunne ikke tilslutte SMTP serveren.';
10
+ $PHPMAILER_LANG['data_not_accepted'] = 'SMTP fejl: Data kunne ikke accepteres.';
11
+ //$PHPMAILER_LANG['empty_message'] = 'Message body empty';
12
+ $PHPMAILER_LANG['encoding'] = 'Ukendt encode-format: ';
13
+ $PHPMAILER_LANG['execute'] = 'Kunne ikke køre: ';
14
+ $PHPMAILER_LANG['file_access'] = 'Ingen adgang til fil: ';
15
+ $PHPMAILER_LANG['file_open'] = 'Fil fejl: Kunne ikke åbne filen: ';
16
+ $PHPMAILER_LANG['from_failed'] = 'Følgende afsenderadresse er forkert: ';
17
+ $PHPMAILER_LANG['instantiate'] = 'Kunne ikke initialisere email funktionen.';
18
+ //$PHPMAILER_LANG['invalid_email'] = 'Not sending, email address is invalid: ';
19
+ $PHPMAILER_LANG['mailer_not_supported'] = ' mailer understøttes ikke.';
20
+ $PHPMAILER_LANG['provide_address'] = 'Du skal indtaste mindst en modtagers emailadresse.';
21
+ $PHPMAILER_LANG['recipients_failed'] = 'SMTP fejl: Følgende modtagere er forkerte: ';
22
+ //$PHPMAILER_LANG['signing'] = 'Signing Error: ';
23
+ //$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() failed.';
24
+ //$PHPMAILER_LANG['smtp_error'] = 'SMTP server error: ';
25
+ //$PHPMAILER_LANG['variable_set'] = 'Cannot set or reset variable: ';
26
  ?>
classes/phpmailer/language/phpmailer.lang-es.php CHANGED
@@ -1,23 +1,26 @@
1
  <?php
2
  /**
3
- * PHPMailer language file.
4
- * Versi�n en espa�ol
5
- */
 
6
 
7
- $PHPMAILER_LANG = array();
8
-
9
- $PHPMAILER_LANG["provide_address"] = 'Debe proveer al menos una ' .
10
- 'direcci�n de email como destinatario.';
11
- $PHPMAILER_LANG["mailer_not_supported"] = ' mailer no est� soportado.';
12
- $PHPMAILER_LANG["execute"] = 'No puedo ejecutar: ';
13
- $PHPMAILER_LANG["instantiate"] = 'No pude crear una instancia de la funci�n Mail.';
14
- $PHPMAILER_LANG["authenticate"] = 'Error SMTP: No se pudo autentificar.';
15
- $PHPMAILER_LANG["from_failed"] = 'La(s) siguiente(s) direcciones de remitente fallaron: ';
16
- $PHPMAILER_LANG["recipients_failed"] = 'Error SMTP: Los siguientes ' .
17
- 'destinatarios fallaron: ';
18
- $PHPMAILER_LANG["data_not_accepted"] = 'Error SMTP: Datos no aceptados.';
19
- $PHPMAILER_LANG["connect_host"] = 'Error SMTP: No puedo conectar al servidor SMTP.';
20
- $PHPMAILER_LANG["file_access"] = 'No puedo acceder al archivo: ';
21
- $PHPMAILER_LANG["file_open"] = 'Error de Archivo: No puede abrir el archivo: ';
22
- $PHPMAILER_LANG["encoding"] = 'Codificaci�n desconocida: ';
 
 
23
  ?>
1
  <?php
2
  /**
3
+ * PHPMailer language file: refer to English translation for definitive list
4
+ * Spanish version
5
+ * Versión en español
6
+ */
7
 
8
+ $PHPMAILER_LANG['authenticate'] = 'Error SMTP: No se pudo autentificar.';
9
+ $PHPMAILER_LANG['connect_host'] = 'Error SMTP: No puedo conectar al servidor SMTP.';
10
+ $PHPMAILER_LANG['data_not_accepted'] = 'Error SMTP: Datos no aceptados.';
11
+ //$PHPMAILER_LANG['empty_message'] = 'Message body empty';
12
+ $PHPMAILER_LANG['encoding'] = 'Codificación desconocida: ';
13
+ $PHPMAILER_LANG['execute'] = 'No puedo ejecutar: ';
14
+ $PHPMAILER_LANG['file_access'] = 'No puedo acceder al archivo: ';
15
+ $PHPMAILER_LANG['file_open'] = 'Error de Archivo: No puede abrir el archivo: ';
16
+ $PHPMAILER_LANG['from_failed'] = 'La(s) siguiente(s) direcciones de remitente fallaron: ';
17
+ $PHPMAILER_LANG['instantiate'] = 'No pude crear una instancia de la función Mail.';
18
+ //$PHPMAILER_LANG['invalid_email'] = 'Not sending, email address is invalid: ';
19
+ $PHPMAILER_LANG['mailer_not_supported'] = ' mailer no está soportado.';
20
+ $PHPMAILER_LANG['provide_address'] = 'Debe proveer al menos una dirección de email como destinatario.';
21
+ $PHPMAILER_LANG['recipients_failed'] = 'Error SMTP: Los siguientes destinatarios fallaron: ';
22
+ $PHPMAILER_LANG['signing'] = 'Error al firmar: ';
23
+ //$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() failed.';
24
+ //$PHPMAILER_LANG['smtp_error'] = 'SMTP server error: ';
25
+ //$PHPMAILER_LANG['variable_set'] = 'Cannot set or reset variable: ';
26
  ?>
classes/phpmailer/language/phpmailer.lang-et.php ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * PHPMailer language file: refer to English translation for definitive list
4
+ * Estonian Version
5
+ * By Indrek Päri
6
+ */
7
+
8
+ $PHPMAILER_LANG['authenticate'] = 'SMTP Viga: Autoriseerimise viga.';
9
+ $PHPMAILER_LANG['connect_host'] = 'SMTP Viga: Ei õnnestunud luua ühendust SMTP serveriga.';
10
+ $PHPMAILER_LANG['data_not_accepted'] = 'SMTP Viga: Vigased andmed.';
11
+ //$PHPMAILER_LANG['empty_message'] = 'Message body empty';
12
+ $PHPMAILER_LANG['encoding'] = 'Tundmatu Unknown kodeering: ';
13
+ $PHPMAILER_LANG['execute'] = 'Tegevus ebaõnnestus: ';
14
+ $PHPMAILER_LANG['file_access'] = 'Pole piisavalt õiguseid järgneva faili avamiseks: ';
15
+ $PHPMAILER_LANG['file_open'] = 'Faili Viga: Faili avamine ebaõnnestus: ';
16
+ $PHPMAILER_LANG['from_failed'] = 'Järgnev saatja e-posti aadress on vigane: ';
17
+ $PHPMAILER_LANG['instantiate'] = 'mail funktiooni käivitamine ebaõnnestus.';
18
+ //$PHPMAILER_LANG['invalid_email'] = 'Not sending, email address is invalid: ';
19
+ $PHPMAILER_LANG['provide_address'] = 'Te peate määrama vähemalt ühe saaja e-posti aadressi.';
20
+ $PHPMAILER_LANG['mailer_not_supported'] = ' maileri tugi puudub.';
21
+ $PHPMAILER_LANG['recipients_failed'] = 'SMTP Viga: Järgnevate saajate e-posti aadressid on vigased: ';
22
+ //$PHPMAILER_LANG['signing'] = 'Signing Error: ';
23
+ //$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() failed.';
24
+ //$PHPMAILER_LANG['smtp_error'] = 'SMTP server error: ';
25
+ //$PHPMAILER_LANG['variable_set'] = 'Cannot set or reset variable: ';
26
+ ?>
classes/phpmailer/language/phpmailer.lang-fi.php CHANGED
@@ -1,23 +1,27 @@
1
  <?php
2
  /**
3
- * PHPMailer language file.
4
- * Finnish Version
5
- * By Jyry Kuukanen
6
- */
7
 
8
- $PHPMAILER_LANG = array();
9
-
10
- $PHPMAILER_LANG["provide_address"] = 'Aseta v&auml;hint&auml;&auml;n yksi vastaanottajan ' .
11
- 's&auml;hk&ouml;postiosoite.';
12
- $PHPMAILER_LANG["mailer_not_supported"] = 'postiv&auml;litintyyppi&auml; ei tueta.';
13
- $PHPMAILER_LANG["execute"] = 'Suoritus ep&auml;onnistui: ';
14
- $PHPMAILER_LANG["instantiate"] = 'mail-funktion luonti ep&auml;onnistui.';
15
- $PHPMAILER_LANG["authenticate"] = 'SMTP-virhe: k&auml;ytt&auml;j&auml;tunnistus ep&auml;onnistui.';
16
- $PHPMAILER_LANG["from_failed"] = 'Seuraava l&auml;hett&auml;j&auml;n osoite on virheellinen: ';
17
- $PHPMAILER_LANG["recipients_failed"] = 'SMTP-virhe: seuraava vastaanottaja osoite on virheellinen.';
18
- $PHPMAILER_LANG["data_not_accepted"] = 'SMTP-virhe: data on virheellinen.';
19
- $PHPMAILER_LANG["connect_host"] = 'SMTP-virhe: yhteys palvelimeen ei onnistu.';
20
- $PHPMAILER_LANG["file_access"] = 'Seuraavaan tiedostoon ei ole oikeuksia: ';
21
- $PHPMAILER_LANG["file_open"] = 'Tiedostovirhe: Ei voida avata tiedostoa: ';
22
- $PHPMAILER_LANG["encoding"] = 'Tuntematon koodaustyyppi: ';
 
 
 
 
23
  ?>
1
  <?php
2
  /**
3
+ * PHPMailer language file: refer to English translation for definitive list
4
+ * Finnish Version
5
+ * By Jyry Kuukanen
6
+ */
7
 
8
+ $PHPMAILER_LANG['authenticate'] = 'SMTP-virhe: käyttäjätunnistus epäonnistui.';
9
+ $PHPMAILER_LANG['connect_host'] = 'SMTP-virhe: yhteys palvelimeen ei onnistu.';
10
+ $PHPMAILER_LANG['data_not_accepted'] = 'SMTP-virhe: data on virheellinen.';
11
+ //$PHPMAILER_LANG['empty_message'] = 'Message body empty';
12
+ $PHPMAILER_LANG['encoding'] = 'Tuntematon koodaustyyppi: ';
13
+ $PHPMAILER_LANG['execute'] = 'Suoritus epäonnistui: ';
14
+ $PHPMAILER_LANG['file_access'] = 'Seuraavaan tiedostoon ei ole oikeuksia: ';
15
+ $PHPMAILER_LANG['file_open'] = 'Tiedostovirhe: Ei voida avata tiedostoa: ';
16
+ $PHPMAILER_LANG['from_failed'] = 'Seuraava lähettäjän osoite on virheellinen: ';
17
+ $PHPMAILER_LANG['instantiate'] = 'mail-funktion luonti epäonnistui.';
18
+ //$PHPMAILER_LANG['invalid_email'] = 'Not sending, email address is invalid: ';
19
+ $PHPMAILER_LANG['mailer_not_supported'] = 'postivälitintyyppiä ei tueta.';
20
+ $PHPMAILER_LANG['provide_address'] = 'Aseta vähintään yksi vastaanottajan sähk&ouml;postiosoite.';
21
+ $PHPMAILER_LANG['recipients_failed'] = 'SMTP-virhe: seuraava vastaanottaja osoite on virheellinen.';
22
+ $PHPMAILER_LANG['encoding'] = 'Tuntematon koodaustyyppi: ';
23
+ //$PHPMAILER_LANG['signing'] = 'Signing Error: ';
24
+ //$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() failed.';
25
+ //$PHPMAILER_LANG['smtp_error'] = 'SMTP server error: ';
26
+ //$PHPMAILER_LANG['variable_set'] = 'Cannot set or reset variable: ';
27
  ?>
classes/phpmailer/language/phpmailer.lang-fo.php CHANGED
@@ -1,25 +1,27 @@
1
- <?php
2
- /**
3
- * PHPMailer language file.
4
- * Faroese Version [language of the Faroe Islands, a Danish dominion]
5
- * This file created: 11-06-2004
6
- * Supplied by D�vur S�rensen [www.profo-webdesign.dk]
7
- */
8
-
9
- $PHPMAILER_LANG = array();
10
-
11
- $PHPMAILER_LANG["provide_address"] = 'T� skal uppgeva minst ' .
12
- 'm�ttakara-emailadressu(r).';
13
- $PHPMAILER_LANG["mailer_not_supported"] = ' er ikki supportera�.';
14
- $PHPMAILER_LANG["execute"] = 'Kundi ikki �tf�ra: ';
15
- $PHPMAILER_LANG["instantiate"] = 'Kuni ikki instantiera mail funkti�n.';
16
- $PHPMAILER_LANG["authenticate"] = 'SMTP feilur: Kundi ikki g��kenna.';
17
- $PHPMAILER_LANG["from_failed"] = 'fylgjandi Fr�/From adressa miseydna�ist: ';
18
- $PHPMAILER_LANG["recipients_failed"] = 'SMTP Feilur: Fylgjandi ' .
19
- 'm�ttakarar miseydna�ust: ';
20
- $PHPMAILER_LANG["data_not_accepted"] = 'SMTP feilur: Data ikki g��kent.';
21
- $PHPMAILER_LANG["connect_host"] = 'SMTP feilur: Kundi ikki kn�ta samband vi� SMTP vert.';
22
- $PHPMAILER_LANG["file_access"] = 'Kundi ikki tilganga f�lu: ';
23
- $PHPMAILER_LANG["file_open"] = 'F�lu feilur: Kundi ikki opna f�lu: ';
24
- $PHPMAILER_LANG["encoding"] = '�kend encoding: ';
25
- ?>
 
 
1
+ <?php
2
+ /**
3
+ * PHPMailer language file: refer to English translation for definitive list
4
+ * Faroese Version [language of the Faroe Islands, a Danish dominion]
5
+ * This file created: 11-06-2004
6
+ * Supplied by Dávur Sørensen [www.profo-webdesign.dk]
7
+ */
8
+
9
+ $PHPMAILER_LANG['authenticate'] = 'SMTP feilur: Kundi ikki góðkenna.';
10
+ $PHPMAILER_LANG['connect_host'] = 'SMTP feilur: Kundi ikki knýta samband við SMTP vert.';
11
+ $PHPMAILER_LANG['data_not_accepted'] = 'SMTP feilur: Data ikki góðkent.';
12
+ //$PHPMAILER_LANG['empty_message'] = 'Message body empty';
13
+ $PHPMAILER_LANG['encoding'] = 'Ókend encoding: ';
14
+ $PHPMAILER_LANG['execute'] = 'Kundi ikki útføra: ';
15
+ $PHPMAILER_LANG['file_access'] = 'Kundi ikki tilganga fílu: ';
16
+ $PHPMAILER_LANG['file_open'] = 'Fílu feilur: Kundi ikki opna fílu: ';
17
+ $PHPMAILER_LANG['from_failed'] = 'fylgjandi Frá/From adressa miseydnaðist: ';
18
+ $PHPMAILER_LANG['instantiate'] = 'Kuni ikki instantiera mail funktión.';
19
+ //$PHPMAILER_LANG['invalid_email'] = 'Not sending, email address is invalid: ';
20
+ $PHPMAILER_LANG['mailer_not_supported'] = ' er ikki supporterað.';
21
+ $PHPMAILER_LANG['provide_address'] = ' skal uppgeva minst móttakara-emailadressu(r).';
22
+ $PHPMAILER_LANG['recipients_failed'] = 'SMTP Feilur: Fylgjandi móttakarar miseydnaðust: ';
23
+ //$PHPMAILER_LANG['signing'] = 'Signing Error: ';
24
+ //$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() failed.';
25
+ //$PHPMAILER_LANG['smtp_error'] = 'SMTP server error: ';
26
+ //$PHPMAILER_LANG['variable_set'] = 'Cannot set or reset variable: ';
27
+ ?>
classes/phpmailer/language/phpmailer.lang-fr.php CHANGED
@@ -1,24 +1,25 @@
1
  <?php
2
  /**
3
- * PHPMailer language file.
4
- * French Version
5
- * bruno@ioda-net.ch 09.08.2003
6
- */
7
 
8
- $PHPMAILER_LANG = array();
9
-
10
- $PHPMAILER_LANG["provide_address"] = 'Vous devez fournir au moins ' .
11
- 'une adresse de destinataire.';
12
- $PHPMAILER_LANG["mailer_not_supported"] = ' mailer non support�.';
13
- $PHPMAILER_LANG["execute"] = 'Ne peut pas lancer l\'ex�cution: ';
14
- $PHPMAILER_LANG["instantiate"] = 'Impossible d\'instancier la fonction mail.';
15
- $PHPMAILER_LANG["authenticate"] = 'SMTP Erreur: Echec de l\'authentification.';
16
- $PHPMAILER_LANG["from_failed"] = 'L\'adresse From suivante a �chou� : ';
17
- $PHPMAILER_LANG["recipients_failed"] = 'SMTP Erreur: Les destinataires ' .
18
- 'suivants sont en erreur : ';
19
- $PHPMAILER_LANG["data_not_accepted"] = 'SMTP Erreur: Data non accept�e.';
20
- $PHPMAILER_LANG["connect_host"] = 'SMTP Erreur: Impossible de connecter le serveur SMTP .';
21
- $PHPMAILER_LANG["file_access"] = 'N\'arrive pas acc�der au fichier: ';
22
- $PHPMAILER_LANG["file_open"] = 'Erreur Fichier: ouverture impossible: ';
23
- $PHPMAILER_LANG["encoding"] = 'Encodage inconnu: ';
24
- ?>
 
 
1
  <?php
2
  /**
3
+ * PHPMailer language file: refer to English translation for definitive list
4
+ * French Version
5
+ */
 
6
 
7
+ $PHPMAILER_LANG['authenticate'] = 'Erreur SMTP : Echec de l\'authentification.';
8
+ $PHPMAILER_LANG['connect_host'] = 'Erreur SMTP : Impossible de se connecter au serveur SMTP.';
9
+ $PHPMAILER_LANG['data_not_accepted'] = 'Erreur SMTP : Données incorrects.';
10
+ $PHPMAILER_LANG['empty_message'] = 'Corps de message vide';
11
+ $PHPMAILER_LANG['encoding'] = 'Encodage inconnu : ';
12
+ $PHPMAILER_LANG['execute'] = 'Impossible de lancer l\'exécution : ';
13
+ $PHPMAILER_LANG['file_access'] = 'Impossible d\'accéder au fichier : ';
14
+ $PHPMAILER_LANG['file_open'] = 'Erreur Fichier : ouverture impossible : ';
15
+ $PHPMAILER_LANG['from_failed'] = 'L\'adresse d\'expéditeur suivante a échouée : ';
16
+ $PHPMAILER_LANG['instantiate'] = 'Impossible d\'instancier la fonction mail.';
17
+ //$PHPMAILER_LANG['invalid_email'] = 'Not sending, email address is invalid: ';
18
+ $PHPMAILER_LANG['mailer_not_supported'] = ' client de messagerie non supporté.';
19
+ $PHPMAILER_LANG['provide_address'] = 'Vous devez fournir au moins une adresse de destinataire.';
20
+ $PHPMAILER_LANG['recipients_failed'] = 'Erreur SMTP : Les destinataires suivants sont en erreur : ';
21
+ //$PHPMAILER_LANG['signing'] = 'Signing Error: ';
22
+ //$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() failed.';
23
+ //$PHPMAILER_LANG['smtp_error'] = 'SMTP server error: ';
24
+ //$PHPMAILER_LANG['variable_set'] = 'Cannot set or reset variable: ';
25
+ ?>
classes/phpmailer/language/phpmailer.lang-hu.php CHANGED
@@ -1,23 +1,25 @@
1
  <?php
2
  /**
3
- * PHPMailer language file.
4
- * Hungarian Version
5
- */
6
 
7
- $PHPMAILER_LANG = array();
8
-
9
- $PHPMAILER_LANG["provide_address"] = 'Meg kell adnod legal�bb egy ' .
10
- 'c�mzett email c�met.';
11
- $PHPMAILER_LANG["mailer_not_supported"] = ' levelez� nem t�mogatott.';
12
- $PHPMAILER_LANG["execute"] = 'Nem tudtam v�grehajtani: ';
13
- $PHPMAILER_LANG["instantiate"] = 'Nem siker�lt p�ld�nyos�tani a mail funkci�t.';
14
- $PHPMAILER_LANG["authenticate"] = 'SMTP Hiba: Sikertelen autentik�ci�.';
15
- $PHPMAILER_LANG["from_failed"] = 'Az al�bbi Felad� c�m hib�s: ';
16
- $PHPMAILER_LANG["recipients_failed"] = 'SMTP Hiba: Az al�bbi ' .
17
- 'c�mzettek hib�sak: ';
18
- $PHPMAILER_LANG["data_not_accepted"] = 'SMTP Hiba: Nem elfogadhat� adat.';
19
- $PHPMAILER_LANG["connect_host"] = 'SMTP Hiba: Nem tudtam csatlakozni az SMTP host-hoz.';
20
- $PHPMAILER_LANG["file_access"] = 'Nem siker�lt el�rni a k�vetkez� f�jlt: ';
21
- $PHPMAILER_LANG["file_open"] = 'F�jl Hiba: Nem siker�lt megnyitni a k�vetkez� f�jlt: ';
22
- $PHPMAILER_LANG["encoding"] = 'Ismeretlen k�dol�s: ';
 
 
23
  ?>
1
  <?php
2
  /**
3
+ * PHPMailer language file: refer to English translation for definitive list
4
+ * Hungarian Version
5
+ */
6
 
7
+ $PHPMAILER_LANG['authenticate'] = 'SMTP Hiba: Sikertelen autentikáció.';
8
+ $PHPMAILER_LANG['connect_host'] = 'SMTP Hiba: Nem tudtam csatlakozni az SMTP host-hoz.';
9
+ $PHPMAILER_LANG['data_not_accepted'] = 'SMTP Hiba: Nem elfogadható adat.';
10
+ //$PHPMAILER_LANG['empty_message'] = 'Message body empty';
11
+ $PHPMAILER_LANG['encoding'] = 'Ismeretlen kódolás: ';
12
+ $PHPMAILER_LANG['execute'] = 'Nem tudtam végrehajtani: ';
13
+ $PHPMAILER_LANG['file_access'] = 'Nem sikerült elérni a következõ fájlt: ';
14
+ $PHPMAILER_LANG['file_open'] = 'Fájl Hiba: Nem sikerült megnyitni a következõ fájlt: ';
15
+ $PHPMAILER_LANG['from_failed'] = 'Az alábbi Feladó cím hibás: ';
16
+ $PHPMAILER_LANG['instantiate'] = 'Nem sikerült példányosítani a mail funkciót.';
17
+ //$PHPMAILER_LANG['invalid_email'] = 'Not sending, email address is invalid: ';
18
+ $PHPMAILER_LANG['provide_address'] = 'Meg kell adnod legalább egy címzett email címet.';
19
+ $PHPMAILER_LANG['mailer_not_supported'] = ' levelezõ nem támogatott.';
20
+ $PHPMAILER_LANG['recipients_failed'] = 'SMTP Hiba: Az alábbi címzettek hibásak: ';
21
+ //$PHPMAILER_LANG['signing'] = 'Signing Error: ';
22
+ //$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() failed.';
23
+ //$PHPMAILER_LANG['smtp_error'] = 'SMTP server error: ';
24
+ //$PHPMAILER_LANG['variable_set'] = 'Cannot set or reset variable: ';
25
  ?>
classes/phpmailer/language/phpmailer.lang-it.php CHANGED
@@ -1,28 +1,27 @@
1
  <?php
2
  /**
3
- * PHPMailer language file.
4
  * Italian version
5
  * @package PHPMailer
6
  * @author Ilias Bartolini <brain79@inwind.it>
7
  */
8
 
9
- $PHPMAILER_LANG = array();
10
-
11
- $PHPMAILER_LANG["provide_address"] = 'Deve essere fornito almeno un'.
12
- ' indirizzo ricevente';
13
- $PHPMAILER_LANG["mailer_not_supported"] = 'Mailer non supportato';
14
- $PHPMAILER_LANG["execute"] = "Impossibile eseguire l'operazione: ";
15
- $PHPMAILER_LANG["instantiate"] = 'Impossibile istanziare la funzione mail';
16
- $PHPMAILER_LANG["authenticate"] = 'SMTP Error: Impossibile autenticarsi.';
17
- $PHPMAILER_LANG["from_failed"] = 'I seguenti indirizzi mittenti hanno'.
18
- ' generato errore: ';
19
- $PHPMAILER_LANG["recipients_failed"] = 'SMTP Error: I seguenti indirizzi'.
20
- 'destinatari hanno generato errore: ';
21
- $PHPMAILER_LANG["data_not_accepted"] = 'SMTP Error: Data non accettati dal'.
22
- 'server.';
23
- $PHPMAILER_LANG["connect_host"] = 'SMTP Error: Impossibile connettersi'.
24
- ' all\'host SMTP.';
25
- $PHPMAILER_LANG["file_access"] = 'Impossibile accedere al file: ';
26
- $PHPMAILER_LANG["file_open"] = 'File Error: Impossibile aprire il file: ';
27
- $PHPMAILER_LANG["encoding"] = 'Encoding set dei caratteri sconosciuto: ';
28
- ?>
1
  <?php
2
  /**
3
+ * PHPMailer language file: refer to English translation for definitive list
4
  * Italian version
5
  * @package PHPMailer
6
  * @author Ilias Bartolini <brain79@inwind.it>
7
  */
8
 
9
+ $PHPMAILER_LANG['authenticate'] = 'SMTP Error: Impossibile autenticarsi.';
10
+ $PHPMAILER_LANG['connect_host'] = 'SMTP Error: Impossibile connettersi all\'host SMTP.';
11
+ $PHPMAILER_LANG['data_not_accepted'] = 'SMTP Error: Data non accettati dal server.';
12
+ //$PHPMAILER_LANG['empty_message'] = 'Message body empty';
13
+ $PHPMAILER_LANG['encoding'] = 'Encoding set dei caratteri sconosciuto: ';
14
+ $PHPMAILER_LANG['execute'] = 'Impossibile eseguire l\'operazione: ';
15
+ $PHPMAILER_LANG['file_access'] = 'Impossibile accedere al file: ';
16
+ $PHPMAILER_LANG['file_open'] = 'File Error: Impossibile aprire il file: ';
17
+ $PHPMAILER_LANG['from_failed'] = 'I seguenti indirizzi mittenti hanno generato errore: ';
18
+ $PHPMAILER_LANG['instantiate'] = 'Impossibile istanziare la funzione mail';
19
+ //$PHPMAILER_LANG['invalid_email'] = 'Not sending, email address is invalid: ';
20
+ $PHPMAILER_LANG['provide_address'] = 'Deve essere fornito almeno un indirizzo ricevente';
21
+ $PHPMAILER_LANG['mailer_not_supported'] = 'Mailer non supportato';
22
+ $PHPMAILER_LANG['recipients_failed'] = 'SMTP Error: I seguenti indirizzi destinatari hanno generato errore: ';
23
+ //$PHPMAILER_LANG['signing'] = 'Signing Error: ';
24
+ //$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() failed.';
25
+ //$PHPMAILER_LANG['smtp_error'] = 'SMTP server error: ';
26
+ //$PHPMAILER_LANG['variable_set'] = 'Cannot set or reset variable: ';
27
+ ?>
 
classes/phpmailer/language/phpmailer.lang-ja.php CHANGED
@@ -1,25 +1,26 @@
1
  <?php
2
  /**
3
- * PHPMailer language file.
4
- * Japanese Version
5
- * By Mitsuhiro Yoshida - http://mitstek.com/
6
- * This file is written in EUC-JP.
7
- */
8
 
9
- $PHPMAILER_LANG = array();
10
-
11
- $PHPMAILER_LANG["provide_address"] = '���ʤ��Ȥ�1�ĥ᡼�륢�ɥ쥹��' .
12
- '���ꤹ��ɬ�פ�����ޤ���';
13
- $PHPMAILER_LANG["mailer_not_supported"] = ' �᡼�顼�����ݡ��Ȥ���Ƥ��ޤ���';
14
- $PHPMAILER_LANG["execute"] = '�¹ԤǤ��ޤ���Ǥ���: ';
15
- $PHPMAILER_LANG["instantiate"] = '�᡼��ؿ��������ư��ޤ���Ǥ�����';
16
- $PHPMAILER_LANG["authenticate"] = 'SMTP���顼: ǧ�ڤǤ��ޤ���Ǥ�����';
17
- $PHPMAILER_LANG["from_failed"] = '����From���ɥ쥹�˴ְ㤤������ޤ�: ';
18
- $PHPMAILER_LANG["recipients_failed"] = 'SMTP���顼: ���μ����ԥ��ɥ쥹�� ' .
19
- '�ְ㤤������ޤ�: ';
20
- $PHPMAILER_LANG["data_not_accepted"] = 'SMTP���顼: �ǡ����������դ����ޤ���Ǥ�����';
21
- $PHPMAILER_LANG["connect_host"] = 'SMTP���顼: SMTP�ۥ��Ȥ���³�Ǥ��ޤ���Ǥ�����';
22
- $PHPMAILER_LANG["file_access"] = '�ե�����˥��������Ǥ��ޤ���: ';
23
- $PHPMAILER_LANG["file_open"] = '�ե����륨�顼: �ե�����򳫤��ޤ���: ';
24
- $PHPMAILER_LANG["encoding"] = '�����ʥ��󥳡��ǥ���: ';
 
 
25
  ?>
1
  <?php
2
  /**
3
+ * PHPMailer language file: refer to English translation for definitive list
4
+ * Japanese Version
5
+ * By Mitsuhiro Yoshida - http://mitstek.com/
6
+ */
 
7
 
8
+ $PHPMAILER_LANG['authenticate'] = 'SMTPエラー: 認証できませんでした。';
9
+ $PHPMAILER_LANG['connect_host'] = 'SMTPエラー: SMTPホストに接続できませんでした。';
10
+ $PHPMAILER_LANG['data_not_accepted'] = 'SMTPエラー: データが受け付けられませんでした。';
11
+ //$PHPMAILER_LANG['empty_message'] = 'Message body empty';
12
+ $PHPMAILER_LANG['encoding'] = '不明なエンコーディング: ';
13
+ $PHPMAILER_LANG['execute'] = '実行できませんでした: ';
14
+ $PHPMAILER_LANG['file_access'] = 'ファイルにアクセスできません: ';
15
+ $PHPMAILER_LANG['file_open'] = 'ファイルエラー: ファイルを開けません: ';
16
+ $PHPMAILER_LANG['from_failed'] = '次のFromアドレスに間違いがあります: ';
17
+ $PHPMAILER_LANG['instantiate'] = 'メール関数が正常に動作しませんでした。';
18
+ //$PHPMAILER_LANG['invalid_email'] = 'Not sending, email address is invalid: ';
19
+ $PHPMAILER_LANG['provide_address'] = '少なくとも1つメールアドレスを 指定する必要があります。';
20
+ $PHPMAILER_LANG['mailer_not_supported'] = ' メーラーがサポートされていません。';
21
+ $PHPMAILER_LANG['recipients_failed'] = 'SMTPエラー: 次の受信者アドレスに 間違いがあります: ';
22
+ //$PHPMAILER_LANG['signing'] = 'Signing Error: ';
23
+ //$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() failed.';
24
+ //$PHPMAILER_LANG['smtp_error'] = 'SMTP server error: ';
25
+ //$PHPMAILER_LANG['variable_set'] = 'Cannot set or reset variable: ';
26
  ?>
classes/phpmailer/language/phpmailer.lang-nl.php CHANGED
@@ -1,23 +1,25 @@
1
  <?php
2
  /**
3
- * PHPMailer language file.
4
- * Dutch Version
5
- */
6
 
7
- $PHPMAILER_LANG = array();
8
-
9
- $PHPMAILER_LANG["provide_address"] = 'Er moet tenmiste &eacute;&eacute;n ' .
10
- 'ontvanger emailadres opgegeven worden.';
11
- $PHPMAILER_LANG["mailer_not_supported"] = ' mailer wordt niet ondersteund.';
12
- $PHPMAILER_LANG["execute"] = 'Kon niet uitvoeren: ';
13
- $PHPMAILER_LANG["instantiate"] = 'Kon mail functie niet initialiseren.';
14
- $PHPMAILER_LANG["authenticate"] = 'SMTP Fout: authenticatie mislukt.';
15
- $PHPMAILER_LANG["from_failed"] = 'De volgende afzender adressen zijn mislukt: ';
16
- $PHPMAILER_LANG["recipients_failed"] = 'SMTP Fout: De volgende ' .
17
- 'ontvangers zijn mislukt: ';
18
- $PHPMAILER_LANG["data_not_accepted"] = 'SMTP Fout: Data niet geaccepteerd.';
19
- $PHPMAILER_LANG["connect_host"] = 'SMTP Fout: Kon niet verbinden met SMTP host.';
20
- $PHPMAILER_LANG["file_access"] = 'Kreeg geen toegang tot bestand: ';
21
- $PHPMAILER_LANG["file_open"] = 'Bestandsfout: Kon bestand niet openen: ';
22
- $PHPMAILER_LANG["encoding"] = 'Onbekende codering: ';
 
 
23
  ?>
1
  <?php
2
  /**
3
+ * PHPMailer language file: refer to English translation for definitive list
4
+ * Dutch Version
5
+ */
6
 
7
+ $PHPMAILER_LANG['authenticate'] = 'SMTP Fout: authenticatie mislukt.';
8
+ $PHPMAILER_LANG['connect_host'] = 'SMTP Fout: Kon niet verbinden met SMTP host.';
9
+ $PHPMAILER_LANG['data_not_accepted'] = 'SMTP Fout: Data niet geaccepteerd.';
10
+ //$PHPMAILER_LANG['empty_message'] = 'Message body empty';
11
+ $PHPMAILER_LANG['encoding'] = 'Onbekende codering: ';
12
+ $PHPMAILER_LANG['execute'] = 'Kon niet uitvoeren: ';
13
+ $PHPMAILER_LANG['file_access'] = 'Kreeg geen toegang tot bestand: ';
14
+ $PHPMAILER_LANG['file_open'] = 'Bestandsfout: Kon bestand niet openen: ';
15
+ $PHPMAILER_LANG['from_failed'] = 'De volgende afzender adressen zijn mislukt: ';
16
+ $PHPMAILER_LANG['instantiate'] = 'Kon mail functie niet initialiseren.';
17
+ //$PHPMAILER_LANG['invalid_email'] = 'Not sending, email address is invalid: ';
18
+ $PHPMAILER_LANG['provide_address'] = 'Er moet tenmiste één ontvanger emailadres opgegeven worden.';
19
+ $PHPMAILER_LANG['mailer_not_supported'] = ' mailer wordt niet ondersteund.';
20
+ $PHPMAILER_LANG['recipients_failed'] = 'SMTP Fout: De volgende ontvangers zijn mislukt: ';
21
+ //$PHPMAILER_LANG['signing'] = 'Signing Error: ';
22
+ //$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() failed.';
23
+ //$PHPMAILER_LANG['smtp_error'] = 'SMTP server error: ';
24
+ //$PHPMAILER_LANG['variable_set'] = 'Cannot set or reset variable: ';
25
  ?>
classes/phpmailer/language/phpmailer.lang-no.php CHANGED
@@ -1,23 +1,25 @@
1
  <?php
2
  /**
3
- * PHPMailer language file.
4
- * Norwegian Version
5
- */
6
 
7
- $PHPMAILER_LANG = array();
8
-
9
- $PHPMAILER_LANG["provide_address"] = 'Du m� ha med minst en' .
10
- 'mottager adresse.';
11
- $PHPMAILER_LANG["mailer_not_supported"] = ' mailer er ikke supportert.';
12
- $PHPMAILER_LANG["execute"] = 'Kunne ikke utf�re: ';
13
- $PHPMAILER_LANG["instantiate"] = 'Kunne ikke instantiate mail funksjonen.';
14
- $PHPMAILER_LANG["authenticate"] = 'SMTP Feil: Kunne ikke authentisere.';
15
- $PHPMAILER_LANG["from_failed"] = 'F�lgende Fra feilet: ';
16
- $PHPMAILER_LANG["recipients_failed"] = 'SMTP Feil: F�lgende' .
17
- 'mottagere feilet: ';
18
- $PHPMAILER_LANG["data_not_accepted"] = 'SMTP Feil: Data ble ikke akseptert.';
19
- $PHPMAILER_LANG["connect_host"] = 'SMTP Feil: Kunne ikke koble til SMTP host.';
20
- $PHPMAILER_LANG["file_access"] = 'Kunne ikke f� tilgang til filen: ';
21
- $PHPMAILER_LANG["file_open"] = 'Fil feil: Kunne ikke �pne filen: ';
22
- $PHPMAILER_LANG["encoding"] = 'Ukjent encoding: ';
23
- ?>
 
 
1
  <?php
2
  /**
3
+ * PHPMailer language file: refer to English translation for definitive list
4
+ * Norwegian Version
5
+ */
6
 
7
+ $PHPMAILER_LANG['authenticate'] = 'SMTP Feil: Kunne ikke authentisere.';
8
+ $PHPMAILER_LANG['connect_host'] = 'SMTP Feil: Kunne ikke koble til SMTP host.';
9
+ $PHPMAILER_LANG['data_not_accepted'] = 'SMTP Feil: Data ble ikke akseptert.';
10
+ //$PHPMAILER_LANG['empty_message'] = 'Message body empty';
11
+ $PHPMAILER_LANG['encoding'] = 'Ukjent encoding: ';
12
+ $PHPMAILER_LANG['execute'] = 'Kunne ikke utføre: ';
13
+ $PHPMAILER_LANG['file_access'] = 'Kunne ikke tilgang til filen: ';
14
+ $PHPMAILER_LANG['file_open'] = 'Fil feil: Kunne ikke åpne filen: ';
15
+ $PHPMAILER_LANG['from_failed'] = 'Følgende Fra feilet: ';
16
+ $PHPMAILER_LANG['instantiate'] = 'Kunne ikke instantiate mail funksjonen.';
17
+ //$PHPMAILER_LANG['invalid_email'] = 'Not sending, email address is invalid: ';
18
+ $PHPMAILER_LANG['provide_address'] = 'Du ha med minst en mottager adresse.';
19
+ $PHPMAILER_LANG['mailer_not_supported'] = ' mailer er ikke supportert.';
20
+ $PHPMAILER_LANG['recipients_failed'] = 'SMTP Feil: Følgende mottagere feilet: ';
21
+ //$PHPMAILER_LANG['signing'] = 'Signing Error: ';
22
+ //$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() failed.';
23
+ //$PHPMAILER_LANG['smtp_error'] = 'SMTP server error: ';
24
+ //$PHPMAILER_LANG['variable_set'] = 'Cannot set or reset variable: ';
25
+ ?>
classes/phpmailer/language/phpmailer.lang-pl.php CHANGED
@@ -1,24 +1,25 @@
1
  <?php
2
  /**
3
- * PHPMailer language file.
4
- * Polish Version, encoding: windows-1250
5
- * translated from english lang file ver. 1.72
6
- */
7
-
8
- $PHPMAILER_LANG = array();
9
-
10
- $PHPMAILER_LANG["provide_address"] = 'Nale�y poda� prawid�owy adres email Odbiorcy.';
11
- $PHPMAILER_LANG["mailer_not_supported"] = 'Wybrana metoda wysy�ki wiadomo�ci nie jest obs�ugiwana.';
12
- $PHPMAILER_LANG["execute"] = 'Nie mo�na uruchomi�: ';
13
- $PHPMAILER_LANG["instantiate"] = 'Nie mo�na wywo�a� funkcji mail(). Sprawd� konfiguracj� serwera.';
14
- $PHPMAILER_LANG["authenticate"] = 'B��d SMTP: Nie mo�na przeprowadzi� autentykacji.';
15
- $PHPMAILER_LANG["from_failed"] = 'Nast�puj�cy adres Nadawcy jest jest nieprawid�owy: ';
16
- $PHPMAILER_LANG["recipients_failed"] = 'B��d SMTP: Nast�puj�cy ' .
17
- 'odbiorcy s� nieprawid�owi: ';
18
- $PHPMAILER_LANG["data_not_accepted"] = 'B��d SMTP: Dane nie zosta�y przyj�te.';
19
- $PHPMAILER_LANG["connect_host"] = 'B��d SMTP: Nie mo�na po��czy� si� z wybranym hostem.';
20
- $PHPMAILER_LANG["file_access"] = 'Brak dost�pu do pliku: ';
21
- $PHPMAILER_LANG["file_open"] = 'Nie mo�na otworzy� pliku: ';
22
- $PHPMAILER_LANG["encoding"] = 'Nieznany spos�b kodowania znak�w: ';
23
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
  ?>
1
  <?php
2
  /**
3
+ * PHPMailer language file: refer to English translation for definitive list
4
+ * Polish Version
5
+ */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
+ $PHPMAILER_LANG['authenticate'] = 'Błąd SMTP: Nie można przeprowadzić autentykacji.';
8
+ $PHPMAILER_LANG['connect_host'] = 'Błąd SMTP: Nie można połączyć się z wybranym hostem.';
9
+ $PHPMAILER_LANG['data_not_accepted'] = 'Błąd SMTP: Dane nie zostały przyjęte.';
10
+ //$PHPMAILER_LANG['empty_message'] = 'Message body empty';
11
+ $PHPMAILER_LANG['encoding'] = 'Nieznany sposób kodowania znaków: ';
12
+ $PHPMAILER_LANG['execute'] = 'Nie można uruchomić: ';
13
+ $PHPMAILER_LANG['file_access'] = 'Brak dostępu do pliku: ';
14
+ $PHPMAILER_LANG['file_open'] = 'Nie można otworzyć pliku: ';
15
+ $PHPMAILER_LANG['from_failed'] = 'Następujący adres Nadawcy jest jest nieprawidłowy: ';
16
+ $PHPMAILER_LANG['instantiate'] = 'Nie można wywołać funkcji mail(). Sprawdź konfigurację serwera.';
17
+ //$PHPMAILER_LANG['invalid_email'] = 'Not sending, email address is invalid: ';
18
+ $PHPMAILER_LANG['provide_address'] = 'Należy podać prawidłowy adres email Odbiorcy.';
19
+ $PHPMAILER_LANG['mailer_not_supported'] = 'Wybrana metoda wysyłki wiadomości nie jest obsługiwana.';
20
+ $PHPMAILER_LANG['recipients_failed'] = 'Błąd SMTP: Następujący odbiorcy są nieprawidłowi: ';
21
+ //$PHPMAILER_LANG['signing'] = 'Signing Error: ';
22
+ //$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() failed.';
23
+ //$PHPMAILER_LANG['smtp_error'] = 'SMTP server error: ';
24
+ //$PHPMAILER_LANG['variable_set'] = 'Cannot set or reset variable: ';
25
  ?>
classes/phpmailer/language/phpmailer.lang-ro.php CHANGED
@@ -1,23 +1,27 @@
1
  <?php
2
  /**
3
- * PHPMailer language file.
4
- * Romanian Version
5
- * @package PHPMailer
6
- * @author Catalin Constantin <catalin@dazoot.ro>
7
- */
8
 
9
- $PHPMAILER_LANG = array();
10
-
11
- $PHPMAILER_LANG["provide_address"] = 'Trebuie sa adaugati cel putin un recipient (adresa de mail).';
12
- $PHPMAILER_LANG["mailer_not_supported"] = ' mailer nu este suportat.';
13
- $PHPMAILER_LANG["execute"] = 'Nu pot executa: ';
14
- $PHPMAILER_LANG["instantiate"] = 'Nu am putut instantia functia mail.';
15
- $PHPMAILER_LANG["authenticate"] = 'Eroare SMTP: Nu a functionat autentificarea.';
16
- $PHPMAILER_LANG["from_failed"] = 'Urmatoarele adrese From au dat eroare: ';
17
- $PHPMAILER_LANG["recipients_failed"] = 'Eroare SMTP: Urmatoarele adrese de mail au dat eroare: ';
18
- $PHPMAILER_LANG["data_not_accepted"] = 'Eroare SMTP: Continutul mailului nu a fost acceptat.';
19
- $PHPMAILER_LANG["connect_host"] = 'Eroare SMTP: Nu m-am putut conecta la adresa SMTP.';
20
- $PHPMAILER_LANG["file_access"] = 'Nu pot accesa fisierul: ';
21
- $PHPMAILER_LANG["file_open"] = 'Eroare de fisier: Nu pot deschide fisierul: ';
22
- $PHPMAILER_LANG["encoding"] = 'Encodare necunoscuta: ';
23
- ?>
 
 
 
 
1
  <?php
2
  /**
3
+ * PHPMailer language file: refer to English translation for definitive list
4
+ * Romanian Version
5
+ * @package PHPMailer
6
+ * @author Catalin Constantin <catalin@dazoot.ro>
7
+ */
8
 
9
+ $PHPMAILER_LANG['authenticate'] = 'Eroare SMTP: Nu a functionat autentificarea.';
10
+ $PHPMAILER_LANG['connect_host'] = 'Eroare SMTP: Nu m-am putut conecta la adresa SMTP.';
11
+ $PHPMAILER_LANG['data_not_accepted'] = 'Eroare SMTP: Continutul mailului nu a fost acceptat.';
12
+ //$PHPMAILER_LANG['empty_message'] = 'Message body empty';
13
+ $PHPMAILER_LANG['encoding'] = 'Encodare necunoscuta: ';
14
+ $PHPMAILER_LANG['execute'] = 'Nu pot executa: ';
15
+ $PHPMAILER_LANG['file_access'] = 'Nu pot accesa fisierul: ';
16
+ $PHPMAILER_LANG['file_open'] = 'Eroare de fisier: Nu pot deschide fisierul: ';
17
+ $PHPMAILER_LANG['from_failed'] = 'Urmatoarele adrese From au dat eroare: ';
18
+ $PHPMAILER_LANG['instantiate'] = 'Nu am putut instantia functia mail.';
19
+ //$PHPMAILER_LANG['invalid_email'] = 'Not sending, email address is invalid: ';
20
+ $PHPMAILER_LANG['mailer_not_supported'] = ' mailer nu este suportat.';
21
+ $PHPMAILER_LANG['provide_address'] = 'Trebuie sa adaugati cel putin un recipient (adresa de mail).';
22
+ $PHPMAILER_LANG['recipients_failed'] = 'Eroare SMTP: Urmatoarele adrese de mail au dat eroare: ';
23
+ //$PHPMAILER_LANG['signing'] = 'Signing Error: ';
24
+ //$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() failed.';
25
+ //$PHPMAILER_LANG['smtp_error'] = 'SMTP server error: ';
26
+ //$PHPMAILER_LANG['variable_set'] = 'Cannot set or reset variable: ';
27
+ ?>
classes/phpmailer/language/phpmailer.lang-ru.php CHANGED
@@ -1,23 +1,25 @@
1
- <?php
2
- /**
3
- * PHPMailer language file.
4
- * Russian Version
5
- */
6
-
7
- $PHPMAILER_LANG = array();
8
-
9
- $PHPMAILER_LANG["provide_address"] = '���������� ������� ������� ���� Email' .
10
- '����������.';
11
- $PHPMAILER_LANG["mailer_not_supported"] = ' mailer �� ��������������.';
12
- $PHPMAILER_LANG["execute"] = '���������� ��������� ��� �������: ';
13
- $PHPMAILER_LANG["instantiate"] = '��������� ������ ��� ������������� Mail �������.';
14
- $PHPMAILER_LANG["authenticate"] = 'SMTP ������: ������ �����������.';
15
- $PHPMAILER_LANG["from_failed"] = '�������� ����� �����������: ';
16
- $PHPMAILER_LANG["recipients_failed"] = 'SMTP ������: ��������� ' .
17
- '������ ����������� �������: ';
18
- $PHPMAILER_LANG["data_not_accepted"] = 'SMTP ������: ������ �� ���� �������.';
19
- $PHPMAILER_LANG["connect_host"] = 'SMTP ������: SMTP-Host ����������.';
20
- $PHPMAILER_LANG["file_access"] = ' ������� ���������� ����� ���� ��������: ';
21
- $PHPMAILER_LANG["file_open"] = '�� ���� ������� ����: ';
22
- $PHPMAILER_LANG["encoding"] = '����������� ������ ���������: ';
23
- ?>
 
 
1
+ <?php
2
+ /**
3
+ * PHPMailer language file: refer to English translation for definitive list
4
+ * Russian Version by Alexey Chumakov <alex@chumakov.ru>
5
+ */
6
+
7
+ $PHPMAILER_LANG['authenticate'] = 'Ошибка SMTP: ошибка авторизации.';
8
+ $PHPMAILER_LANG['connect_host'] = 'Ошибка SMTP: не удается подключиться к серверу SMTP.';
9
+ $PHPMAILER_LANG['data_not_accepted'] = 'Ошибка SMTP: данные не приняты.';
10
+ //$PHPMAILER_LANG['empty_message'] = 'Message body empty';
11
+ $PHPMAILER_LANG['encoding'] = 'Неизвестный вид кодировки: ';
12
+ $PHPMAILER_LANG['execute'] = 'Невозможно выполнить команду: ';
13
+ $PHPMAILER_LANG['file_access'] = 'Нет доступа к файлу: ';
14
+ $PHPMAILER_LANG['file_open'] = 'Файловая ошибка: не удается открыть файл: ';
15
+ $PHPMAILER_LANG['from_failed'] = 'Неверный адрес отправителя: ';
16
+ $PHPMAILER_LANG['instantiate'] = 'Невозможно запустить функцию mail.';
17
+ //$PHPMAILER_LANG['invalid_email'] = 'Not sending, email address is invalid: ';
18
+ $PHPMAILER_LANG['provide_address'] = 'Пожалуйста, введите хотя бы один адрес e-mail получателя.';
19
+ $PHPMAILER_LANG['mailer_not_supported'] = ' - почтовый сервер не поддерживается.';
20
+ $PHPMAILER_LANG['recipients_failed'] = 'Ошибка SMTP: отправка по следующим адресам получателей не удалась: ';
21
+ //$PHPMAILER_LANG['signing'] = 'Signing Error: ';
22
+ //$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() failed.';
23
+ //$PHPMAILER_LANG['smtp_error'] = 'SMTP server error: ';
24
+ //$PHPMAILER_LANG['variable_set'] = 'Cannot set or reset variable: ';
25
+ ?>
classes/phpmailer/language/phpmailer.lang-se.php CHANGED
@@ -1,24 +1,26 @@
1
  <?php
2
  /**
3
- * PHPMailer language file.
4
- * Swedish Version
5
- * Author: Johan Linn�r <johan@linner.biz>
6
- */
7
 
8
- $PHPMAILER_LANG = array();
9
-
10
- $PHPMAILER_LANG["provide_address"] = 'Du m�ste ange minst en ' .
11
- 'mottagares e-postadress.';
12
- $PHPMAILER_LANG["mailer_not_supported"] = ' mailer st�ds inte.';
13
- $PHPMAILER_LANG["execute"] = 'Kunde inte k�ra: ';
14
- $PHPMAILER_LANG["instantiate"] = 'Kunde inte initiera e-postfunktion.';
15
- $PHPMAILER_LANG["authenticate"] = 'SMTP fel: Kunde inte autentisera.';
16
- $PHPMAILER_LANG["from_failed"] = 'F�ljande avs�ndaradress �r felaktig: ';
17
- $PHPMAILER_LANG["recipients_failed"] = 'SMTP fel: F�ljande ' .
18
- 'mottagare �r felaktig: ';
19
- $PHPMAILER_LANG["data_not_accepted"] = 'SMTP fel: Data accepterades inte.';
20
- $PHPMAILER_LANG["connect_host"] = 'SMTP fel: Kunde inte ansluta till SMTP-server.';
21
- $PHPMAILER_LANG["file_access"] = 'Ingen �tkomst till fil: ';
22
- $PHPMAILER_LANG["file_open"] = 'Fil fel: Kunde inte �ppna fil: ';
23
- $PHPMAILER_LANG["encoding"] = 'Ok�nt encode-format: ';
 
 
24
  ?>
1
  <?php
2
  /**
3
+ * PHPMailer language file: refer to English translation for definitive list
4
+ * Swedish Version
5
+ * Author: Johan Linnér <johan@linner.biz>
6
+ */
7
 
8
+ $PHPMAILER_LANG['authenticate'] = 'SMTP fel: Kunde inte autentisera.';
9
+ $PHPMAILER_LANG['connect_host'] = 'SMTP fel: Kunde inte ansluta till SMTP-server.';
10
+ $PHPMAILER_LANG['data_not_accepted'] = 'SMTP fel: Data accepterades inte.';
11
+ //$PHPMAILER_LANG['empty_message'] = 'Message body empty';
12
+ $PHPMAILER_LANG['encoding'] = 'Okänt encode-format: ';
13
+ $PHPMAILER_LANG['execute'] = 'Kunde inte köra: ';
14
+ $PHPMAILER_LANG['file_access'] = 'Ingen åtkomst till fil: ';
15
+ $PHPMAILER_LANG['file_open'] = 'Fil fel: Kunde inte öppna fil: ';
16
+ $PHPMAILER_LANG['from_failed'] = 'Följande avsändaradress är felaktig: ';
17
+ $PHPMAILER_LANG['instantiate'] = 'Kunde inte initiera e-postfunktion.';
18
+ //$PHPMAILER_LANG['invalid_email'] = 'Not sending, email address is invalid: ';
19
+ $PHPMAILER_LANG['provide_address'] = 'Du måste ange minst en mottagares e-postadress.';
20
+ $PHPMAILER_LANG['mailer_not_supported'] = ' mailer stöds inte.';
21
+ $PHPMAILER_LANG['recipients_failed'] = 'SMTP fel: Följande mottagare är felaktig: ';
22
+ //$PHPMAILER_LANG['signing'] = 'Signing Error: ';
23
+ //$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() failed.';
24
+ //$PHPMAILER_LANG['smtp_error'] = 'SMTP server error: ';
25
+ //$PHPMAILER_LANG['variable_set'] = 'Cannot set or reset variable: ';
26
  ?>
classes/phpmailer/language/phpmailer.lang-tr.php CHANGED
@@ -1,25 +1,27 @@
1
  <?php
2
  /**
3
- * PHPMailer dil dosyas�.
4
- * T�rk�e Versiyonu
5
- * �ZYAZILIM - El�in �zel - Can Y�lmaz - Mehmet Benlio�lu
6
- */
7
-
8
- $PHPMAILER_LANG = array();
9
-
10
- $PHPMAILER_LANG["provide_address"] = 'En az bir tane mail adresi belirtmek zorundas�n�z ' .
11
- 'al�c�n�n email adresi.';
12
- $PHPMAILER_LANG["mailer_not_supported"] = ' mailler desteklenmemektedir.';
13
- $PHPMAILER_LANG["execute"] = '�al��t�r�lam�yor: ';
14
- $PHPMAILER_LANG["instantiate"] = '�rnek mail fonksiyonu yarat�lamad�.';
15
- $PHPMAILER_LANG["authenticate"] = 'SMTP Hatas�: Do�rulanam�yor.';
16
- $PHPMAILER_LANG["from_failed"] = 'Ba�ar�s�z olan g�nderici adresi: ';
17
- $PHPMAILER_LANG["recipients_failed"] = 'SMTP Hatas�: ' .
18
- 'al�c�lara ula�mad�: ';
19
- $PHPMAILER_LANG["data_not_accepted"] = 'SMTP Hatas�: Veri kabul edilmedi.';
20
- $PHPMAILER_LANG["connect_host"] = 'SMTP Hatas�: SMTP hosta ba�lan�lam�yor.';
21
- $PHPMAILER_LANG["file_access"] = 'Dosyaya eri�ilemiyor: ';
22
- $PHPMAILER_LANG["file_open"] = 'Dosya Hatas�: Dosya a��lam�yor: ';
23
- $PHPMAILER_LANG["encoding"] = 'Bilinmeyen �ifreleme: ';
24
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25
  ?>
1
  <?php
2
  /**
3
+ * PHPMailer language file: refer to English translation for definitive list
4
+ * Turkish version
5
+ * Türkçe Versiyonu
6
+ * ÝZYAZILIM - Elçin Özel - Can Yýlmaz - Mehmet Benlioðlu
7
+ */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
 
9
+ $PHPMAILER_LANG['authenticate'] = 'SMTP Hatasý: Doðrulanamýyor.';
10
+ $PHPMAILER_LANG['connect_host'] = 'SMTP Hatasý: SMTP hosta baðlanýlamýyor.';
11
+ $PHPMAILER_LANG['data_not_accepted'] = 'SMTP Hatasý: Veri kabul edilmedi.';
12
+ //$PHPMAILER_LANG['empty_message'] = 'Message body empty';
13
+ $PHPMAILER_LANG['encoding'] = 'Bilinmeyen þifreleme: ';
14
+ $PHPMAILER_LANG['execute'] = 'Çalýþtýrýlamýyor: ';
15
+ $PHPMAILER_LANG['file_access'] = 'Dosyaya eriþilemiyor: ';
16
+ $PHPMAILER_LANG['file_open'] = 'Dosya Hatasý: Dosya açýlamýyor: ';
17
+ $PHPMAILER_LANG['from_failed'] = 'Baþarýsýz olan gönderici adresi: ';
18
+ $PHPMAILER_LANG['instantiate'] = 'Örnek mail fonksiyonu yaratýlamadý.';
19
+ //$PHPMAILER_LANG['invalid_email'] = 'Not sending, email address is invalid: ';
20
+ $PHPMAILER_LANG['provide_address'] = 'En az bir tane mail adresi belirtmek zorundasýnýz alýcýnýn email adresi.';
21
+ $PHPMAILER_LANG['mailer_not_supported'] = ' mailler desteklenmemektedir.';
22
+ $PHPMAILER_LANG['recipients_failed'] = 'SMTP Hatasý: alýcýlara ulaþmadý: ';
23
+ //$PHPMAILER_LANG['signing'] = 'Signing Error: ';
24
+ //$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() failed.';
25
+ //$PHPMAILER_LANG['smtp_error'] = 'SMTP server error: ';
26
+ //$PHPMAILER_LANG['variable_set'] = 'Cannot set or reset variable: ';
27
  ?>
classes/phpmailer/language/phpmailer.lang-zh.php ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * PHPMailer language file: refer to English translation for definitive list
4
+ * Traditional Chinese Version
5
+ * @author liqwei <liqwei@liqwei.com>
6
+ */
7
+
8
+ $PHPMAILER_LANG['authenticate'] = 'SMTP 錯誤:登錄失敗。';
9
+ $PHPMAILER_LANG['connect_host'] = 'SMTP 錯誤:無法連接到 SMTP 主機。';
10
+ $PHPMAILER_LANG['data_not_accepted'] = 'SMTP 錯誤:數據不被接受。';
11
+ //$PHPMAILER_LANG['empty_message'] = 'Message body empty';
12
+ $PHPMAILER_LANG['encoding'] = '未知編碼: ';
13
+ $PHPMAILER_LANG['file_access'] = '無法訪問文件:';
14
+ $PHPMAILER_LANG['file_open'] = '文件錯誤:無法打開文件:';
15
+ $PHPMAILER_LANG['from_failed'] = '發送地址錯誤:';
16
+ $PHPMAILER_LANG['execute'] = '無法執行:';
17
+ $PHPMAILER_LANG['instantiate'] = '未知函數調用。';
18
+ //$PHPMAILER_LANG['invalid_email'] = 'Not sending, email address is invalid: ';
19
+ $PHPMAILER_LANG['provide_address'] = '必須提供至少一個收件人地址。';
20
+ $PHPMAILER_LANG['mailer_not_supported'] = '發信客戶端不被支持。';
21
+ $PHPMAILER_LANG['recipients_failed'] = 'SMTP 錯誤:收件人地址錯誤:';
22
+ //$PHPMAILER_LANG['signing'] = 'Signing Error: ';
23
+ //$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() failed.';
24
+ //$PHPMAILER_LANG['smtp_error'] = 'SMTP server error: ';
25
+ //$PHPMAILER_LANG['variable_set'] = 'Cannot set or reset variable: ';
26
+ ?>
classes/phpmailer/language/phpmailer.lang-zh_cn.php ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * PHPMailer language file: refer to English translation for definitive list
4
+ * Simplified Chinese Version
5
+ * @author liqwei <liqwei@liqwei.com>
6
+ */
7
+
8
+ $PHPMAILER_LANG['authenticate'] = 'SMTP 错误:登录失败。';
9
+ $PHPMAILER_LANG['connect_host'] = 'SMTP 错误:无法连接到 SMTP 主机。';
10
+ $PHPMAILER_LANG['data_not_accepted'] = 'SMTP 错误:数据不被接受。';
11
+ //$P$PHPMAILER_LANG['empty_message'] = 'Message body empty';
12
+ $PHPMAILER_LANG['encoding'] = '未知编码: ';
13
+ $PHPMAILER_LANG['execute'] = '无法执行:';
14
+ $PHPMAILER_LANG['file_access'] = '无法访问文件:';
15
+ $PHPMAILER_LANG['file_open'] = '文件错误:无法打开文件:';
16
+ $PHPMAILER_LANG['from_failed'] = '发送地址错误:';
17
+ $PHPMAILER_LANG['instantiate'] = '未知函数调用。';
18
+ //$PHPMAILER_LANG['invalid_email'] = 'Not sending, email address is invalid: ';
19
+ $PHPMAILER_LANG['mailer_not_supported'] = '发信客户端不被支持。';
20
+ $PHPMAILER_LANG['provide_address'] = '必须提供至少一个收件人地址。';
21
+ $PHPMAILER_LANG['recipients_failed'] = 'SMTP 错误:收件人地址错误:';
22
+ //$PHPMAILER_LANG['signing'] = 'Signing Error: ';
23
+ //$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() failed.';
24
+ //$PHPMAILER_LANG['smtp_error'] = 'SMTP server error: ';
25
+ //$PHPMAILER_LANG['variable_set'] = 'Cannot set or reset variable: ';
26
+ ?>
em-actions.php ADDED
@@ -0,0 +1,512 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Performs actions on init. This works for both ajax and normal requests, the return results depends if an em_ajax flag is passed via POST or GET.
4
+ */
5
+ function em_init_actions() {
6
+ global $wpdb,$EM_Notices,$EM_Event;
7
+ if( defined('DOING_AJAX') && DOING_AJAX ) $_REQUEST['em_ajax'] = true;
8
+
9
+ //NOTE - No EM objects are globalized at this point, as we're hitting early init mode.
10
+ //TODO Clean this up.... use a uniformed way of calling EM Ajax actions
11
+ if( !empty($_REQUEST['em_ajax']) || !empty($_REQUEST['em_ajax_action']) ){
12
+ if(isset($_REQUEST['em_ajax_action']) && $_REQUEST['em_ajax_action'] == 'get_location') {
13
+ if(isset($_REQUEST['id'])){
14
+ $EM_Location = new EM_Location($_REQUEST['id'], 'location_id');
15
+ $location_array = $EM_Location->to_array();
16
+ $location_array['location_balloon'] = $EM_Location->output(get_option('dbem_location_baloon_format'));
17
+ echo EM_Object::json_encode($location_array);
18
+ }
19
+ die();
20
+ }
21
+ if(isset($_REQUEST['em_ajax_action']) && $_REQUEST['em_ajax_action'] == 'delete_ticket') {
22
+ if(isset($_REQUEST['id'])){
23
+ $EM_Ticket = new EM_Ticket($_REQUEST['id']);
24
+ $result = $EM_Ticket->delete();
25
+ if($result){
26
+ $result = array('result'=>true);
27
+ }else{
28
+ $result = array('result'=>false, 'error'=>$EM_Ticket->feedback_message);
29
+ }
30
+ }else{
31
+ $result = array('result'=>false, 'error'=>__('No ticket id provided','dbem'));
32
+ }
33
+ echo EM_Object::json_encode($result);
34
+ die();
35
+ }
36
+ if(isset($_REQUEST['query']) && $_REQUEST['query'] == 'GlobalMapData') {
37
+ $EM_Locations = EM_Locations::get( $_REQUEST );
38
+ $json_locations = array();
39
+ foreach($EM_Locations as $location_key => $EM_Location) {
40
+ $json_locations[$location_key] = $EM_Location->to_array();
41
+ $json_locations[$location_key]['location_balloon'] = $EM_Location->output(get_option('dbem_map_text_format'));
42
+ }
43
+ echo EM_Object::json_encode($json_locations);
44
+ die();
45
+ }
46
+
47
+ if(isset($_REQUEST['ajaxCalendar']) && $_REQUEST['ajaxCalendar']) {
48
+ //FIXME if long events enabled originally, this won't show up on ajax call
49
+ echo EM_Calendar::output($_REQUEST);
50
+ die();
51
+ }
52
+ }
53
+
54
+ //Event Actions
55
+ if( !empty($_REQUEST['action']) && substr($_REQUEST['action'],0,5) == 'event' ){
56
+ //Load the event object, with saved event if requested
57
+ if( !empty($_REQUEST['event_id']) ){
58
+ $EM_Event = new EM_Event($_REQUEST['event_id']);
59
+ }else{
60
+ $EM_Event = new EM_Event();
61
+ }
62
+ //Save Event, only via BP or via [event_form]
63
+ if( $_REQUEST['action'] == 'event_save' && (current_user_can('edit_events') || (!is_user_logged_in() && get_option('dbem_events_anonymous_submissions'))) ){
64
+ //Check Nonces
65
+ if( !wp_verify_nonce($_REQUEST['_wpnonce'], 'wpnonce_event_save') ) exit('Trying to perform an illegal action.');
66
+ //Grab and validate submitted data
67
+ if ( $EM_Event->get_post() && $EM_Event->save() ) { //EM_Event gets the event if submitted via POST and validates it (safer than to depend on JS)
68
+ $events_result = true;
69
+ $EM_Notices->add_confirm($EM_Event->feedback_message, true);
70
+ $redirect = !empty($_REQUEST['redirect_to']) ? $_REQUEST['redirect_to'] : wp_get_referer();
71
+ wp_redirect( $redirect );
72
+ exit();
73
+ }else{
74
+ $EM_Notices->add_error( $EM_Event->get_errors() );
75
+ $events_result = false;
76
+ }
77
+ }
78
+ if ( $_REQUEST['action'] == 'event_duplicate' ) {
79
+ $EM_Event = $EM_Event->duplicate();
80
+ if( $EM_Event === false ){
81
+ $EM_Notices->add_error($EM_Event->errors, true);
82
+ }else{
83
+ if( $EM_Event->event_id == $_REQUEST['event_id'] ){
84
+ $EM_Notices->add_confirm($EM_Event->feedback_message ." ". sprintf(__('You are now viewing the duplicated %s.', 'dbem'),__('event','dbem')), true);
85
+ wp_redirect( admin_url().'post.php?action=edit&post='.$EM_Event->post_id );
86
+ }else{
87
+ $EM_Notices->add_confirm($EM_Event->feedback_message, true);
88
+ wp_redirect( admin_url().'edit.php?post_type='.EM_POST_TYPE_EVENT );
89
+ }
90
+ exit();
91
+ }
92
+ }
93
+ if ( $_REQUEST['action'] == 'event_delete' ) {
94
+ //DELETE action
95
+ $selectedEvents = !empty($_REQUEST['events']) ? $_REQUEST['events']:'';
96
+ if( EM_Object::array_is_numeric($selectedEvents) ){
97
+ $events_result = EM_Events::delete( $selectedEvents );
98
+ }elseif( is_object($EM_Event) ){
99
+ $events_result = $EM_Event->delete();
100
+ }
101
+ $plural = (count($selectedEvents) > 1) ? __('Events','dbem'):__('Event','dbem');
102
+ if($events_result){
103
+ $message = ( is_object($EM_Event) ) ? $EM_Event->feedback_message : sprintf(__('%s successfully deleted.','dbem'),$plural);
104
+ $EM_Notices->add_confirm( $message );
105
+ }else{
106
+ $message = ( is_object($EM_Event) ) ? $EM_Event->errors : sprintf(__('%s could not be deleted.','dbem'),$plural);
107
+ $EM_Notices->add_confirm( $message );
108
+ }
109
+ }elseif( $_REQUEST['action'] == 'event_detach' && wp_verify_nonce($_REQUEST['_wpnonce'],'event_detach_'.get_current_user_id().'_'.$EM_Event->event_id) ){
110
+ //Detach event and move on
111
+ if($EM_Event->detach()){
112
+ $EM_Notices->add_confirm( $EM_Event->feedback_message, true );
113
+ }else{
114
+ $EM_Notices->add_error( $EM_Event->errors, true );
115
+ }
116
+ wp_redirect(wp_get_referer());
117
+ exit();
118
+ }elseif( $_REQUEST['action'] == 'event_attach' && !empty($_REQUEST['undo_id']) && wp_verify_nonce($_REQUEST['_wpnonce'],'event_attach_'.get_current_user_id().'_'.$EM_Event->event_id) ){
119
+ //Detach event and move on
120
+ if($EM_Event->attach($_REQUEST['undo_id'])){
121
+ $EM_Notices->add_confirm( $EM_Event->feedback_message, true );
122
+ }else{
123
+ $EM_Notices->add_error( $EM_Event->errors, true );
124
+ }
125
+ wp_redirect(wp_get_referer());
126
+ exit();
127
+ }
128
+
129
+ //AJAX Exit
130
+ if( isset($events_result) && !empty($_REQUEST['em_ajax']) ){
131
+ if( $events_result ){
132
+ $return = array('result'=>true, 'message'=>$EM_Event->feedback_message);
133
+ }else{
134
+ $return = array('result'=>false, 'message'=>$EM_Event->feedback_message, 'errors'=>$EM_Event->errors);
135
+ }
136
+ }
137
+ }
138
+
139
+ //Location Actions
140
+ if( !empty($_REQUEST['action']) && substr($_REQUEST['action'],0,8) == 'location' ){
141
+ global $EM_Location, $EM_Notices;
142
+ //Load the location object, with saved event if requested
143
+ if( !empty($_REQUEST['location_id']) ){
144
+ $EM_Location = new EM_Location($_REQUEST['location_id']);
145
+ }else{
146
+ $EM_Location = new EM_Location();
147
+ }
148
+ if( $_REQUEST['action'] == 'location_save' && current_user_can('edit_locations') ){
149
+ if( get_site_option('dbem_ms_mainblog_locations') ) EM_Object::ms_global_switch(); //switch to main blog if locations are global
150
+ //Check Nonces
151
+ em_verify_nonce('location_save');
152
+ //Grab and validate submitted data
153
+ if ( $EM_Location->get_post() && $EM_Location->save() ) { //EM_location gets the location if submitted via POST and validates it (safer than to depend on JS)
154
+ $EM_Notices->add_confirm($EM_Location->feedback_message, true);
155
+ $redirect = !empty($_REQUEST['redirect_to']) ? $_REQUEST['redirect_to'] : wp_get_referer();
156
+ wp_redirect( $redirect );
157
+ exit();
158
+ }else{
159
+ $EM_Notices->add_error( $EM_Location->get_errors() );
160
+ $result = false;
161
+ }
162
+ if( get_site_option('dbem_ms_mainblog_locations') ) EM_Object::ms_global_switch_back();
163
+ }elseif( !empty($_REQUEST['action']) && $_REQUEST['action'] == "location_delete" ){
164
+ //delete location
165
+ //get object or objects
166
+ if( !empty($_REQUEST['locations']) || !empty($_REQUEST['location_id']) ){
167
+ $args = !empty($_REQUEST['locations']) ? $_REQUEST['locations']:$_REQUEST['location_id'];
168
+ $locations = EM_Locations::get($args);
169
+ foreach($locations as $location) {
170
+ if( !$location->delete() ){
171
+ $EM_Notices->add_error($location->get_errors());
172
+ $errors = true;
173
+ }
174
+ }
175
+ if( empty($errors) ){
176
+ $result = true;
177
+ $location_term = ( count($locations) > 1 ) ?__('Locations', 'dbem') : __('Location', 'dbem');
178
+ $EM_Notices->add_confirm( sprintf(__('%s successfully deleted', 'dbem'), $location_term) );
179
+ }else{
180
+ $result = false;
181
+ }
182
+ }
183
+ }elseif( !empty($_REQUEST['action']) && $_REQUEST['action'] == "locations_search" && (!empty($_REQUEST['term']) || !empty($_REQUEST['q'])) ){
184
+ $location_cond = ( !current_user_can('edit_others_locations') && !current_user_can('read_others_locations') ) ? "AND location_owner=".get_current_user_id() : '';
185
+ $term = (isset($_REQUEST['term'])) ? '%'.$_REQUEST['term'].'%' : '%'.$_REQUEST['q'].'%';
186
+ $sql = $wpdb->prepare("
187
+ SELECT
188
+ location_id AS `id`,
189
+ Concat( location_name, ', ', location_address, ', ', location_town) AS `label`,
190
+ location_name AS `value`,
191
+ location_address AS `address`,
192
+ location_town AS `town`,
193
+ location_state AS `state`,
194
+ location_postcode AS `postcode`,
195
+ location_country AS `country`
196
+ FROM ".EM_LOCATIONS_TABLE."
197
+ WHERE ( `location_name` LIKE %s ) $location_cond LIMIT 10
198
+ ", $term);
199
+ echo EM_Object::json_encode($wpdb->get_results($sql));
200
+ die();
201
+ }
202
+ if( isset($result) && $result && !empty($_REQUEST['em_ajax']) ){
203
+ $return = array('result'=>true, 'message'=>$EM_Location->feedback_message);
204
+ echo EM_Object::json_encode($return);
205
+ die();
206
+ }elseif( isset($result) && !$result && !empty($_REQUEST['em_ajax']) ){
207
+ $return = array('result'=>false, 'message'=>$EM_Location->feedback_message, 'errors'=>$EM_Notices->get_errors());
208
+ echo EM_Object::json_encode($return);
209
+ die();
210
+ }
211
+ }
212
+
213
+ //Booking Actions
214
+ if( !empty($_REQUEST['action']) && substr($_REQUEST['action'],0,7) == 'booking' && (is_user_logged_in() || ($_REQUEST['action'] == 'booking_add' && get_option('dbem_bookings_anonymous'))) ){
215
+ global $EM_Event, $EM_Booking, $EM_Person;
216
+ //Load the booking object, with saved booking if requested
217
+ $EM_Booking = ( !empty($_REQUEST['booking_id']) ) ? new EM_Booking($_REQUEST['booking_id']) : new EM_Booking();
218
+ //Load the event object, with saved event if requested
219
+ $EM_Event = $EM_Booking->get_event();
220
+ $allowed_actions = array('bookings_approve'=>'approve','bookings_reject'=>'reject','bookings_unapprove'=>'unapprove', 'bookings_delete'=>'delete');
221
+ $result = false;
222
+ if ( $_REQUEST['action'] == 'booking_add') {
223
+ //ADD/EDIT Booking
224
+ em_verify_nonce('booking_add');
225
+ do_action('em_booking_add', $EM_Event, $EM_Booking);
226
+ if( !is_user_logged_in() || get_option('dbem_bookings_double') || !$EM_Event->get_bookings()->has_booking(get_current_user_id()) ){
227
+ if( $EM_Booking->get_post() ){
228
+ //Does this user need to be registered first?
229
+ $registration = true;
230
+ //TODO do some ticket validation before registering the user
231
+ if ( $EM_Event->get_bookings()->get_available_spaces() >= $EM_Booking->get_spaces(true) ) {
232
+ if( !is_user_logged_in() && get_option('dbem_bookings_anonymous') && !get_option('dbem_bookings_registration_disable') ){
233
+ //find random username - less options for user, less things go wrong
234
+ $username_root = explode('@', $_REQUEST['user_email']);
235
+ $username_rand = $username_root[0].rand(1,1000);
236
+ while( username_exists($username_root[0].rand(1,1000)) ){
237
+ $username_rand = $username_root[0].rand(1,1000);
238
+ }
239
+ $_REQUEST['user_phone'] = (!empty($_REQUEST['user_phone'])) ? $_REQUEST['user_phone']:''; //fix to prevent warnings
240
+ $_REQUEST['user_