PageRenderTime 31ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 1ms

/wp-content/plugins/ajax-event-calendar/ajax-event-calendar.php

https://bitbucket.org/nathancorbier/wastark.com
PHP | 1801 lines | 1501 code | 187 blank | 113 comment | 144 complexity | 1f0cf6b0ae9c577e95405dbda7a12cb2 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. <?php
  2. /*
  3. Plugin Name: Ajax Event Calendar
  4. Plugin URI: http://wordpress.org/extend/plugins/ajax-event-calendar/
  5. Description: A fully localized community calendar that allows authorized users to manage events in custom categories.
  6. Version: 1.0.4
  7. Author: Eran Miller
  8. Author URI: http://eranmiller.com
  9. License: GPL2
  10. */
  11. /* Copyright 2011 Eran Miller <email: plugins@eranmiller.com>
  12. This program is free software; you can redistribute it and/or modify
  13. it under the terms of the GNU General Public License, version 2, as
  14. published by the Free Software Foundation.
  15. This program is distributed in the hope that it will be useful,
  16. but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. GNU General Public License for more details.
  19. You should have received a copy of the GNU General Public License
  20. along with this program; if not, write to the Free Software
  21. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  22. */
  23. // disallow direct access to file
  24. if (basename($_SERVER['PHP_SELF']) == basename(__FILE__)) {
  25. die('Sorry, but you cannot access this page directly.');
  26. }
  27. if (version_compare(PHP_VERSION, '5', '<')) {
  28. $out = "<div id='message' style='width:94%' class='message error'>";
  29. $out .= sprintf("<p><strong>Your PHP version is '%s'.<br>The Ajax Event Calendar WordPress plugin requires PHP 5 or higher.</strong></p><p>Ask your web host how to enable PHP 5 on your site.</p>", PHP_VERSION);
  30. $out .= "</div>";
  31. print $out;
  32. }
  33. define('AEC_MENU_POSITION', null); //previously 30
  34. define('AEC_VERSION', '1.0.4');
  35. define('AEC_FILE', basename(__FILE__));
  36. define('AEC_NAME', str_replace('.php', '', AEC_FILE));
  37. define('AEC_PATH', plugin_dir_path(__FILE__));
  38. define('AEC_URL', plugin_dir_url(__FILE__));
  39. define('AEC_EVENT_TABLE', 'aec_event');
  40. define('AEC_CATEGORY_TABLE', 'aec_event_category');
  41. define('AEC_HOMEPAGE', 'http://wordpress.org/extend/plugins/' . AEC_NAME . '/');
  42. define('AEC_WP_DATE_FORMAT', get_option('date_format'));
  43. define('AEC_WP_TIME_FORMAT', get_option('time_format'));
  44. define('AEC_DB_DATETIME_FORMAT', 'Y-m-d H:i:s');
  45. define('AEC_LOCALE', substr(get_locale(), 0, 2)); // for javascript localization scripts
  46. // if uncommented, overrides the location of the WP error log to the AEC plugin root
  47. // @ini_set('error_log', AEC_PATH . 'aec_debug.log');
  48. if (!class_exists('ajax_event_calendar')) {
  49. class ajax_event_calendar {
  50. private $required_fields = array();
  51. private $shortcode_params = array();
  52. private $admin_messages = array();
  53. private $plugin_defaults = array(
  54. 'filter_label' => 'Show Type',
  55. 'limit' => '0',
  56. 'show_weekends' => '1',
  57. 'show_map_link' => '1',
  58. 'menu' => '1',
  59. 'make_links' => '0',
  60. 'popup_links' => '1',
  61. 'step_interval' => '30',
  62. 'addy_format' => '0',
  63. 'scroll' => '1',
  64. 'title' => '2',
  65. 'venue' => '1',
  66. 'address' => '2',
  67. 'city' => '2',
  68. 'state' => '2',
  69. 'zip' => '2',
  70. 'country' => '1',
  71. 'link' => '1',
  72. 'description' => '2',
  73. 'contact' => '2',
  74. 'contact_info' => '2',
  75. 'accessible' => '0',
  76. 'rsvp' => '0',
  77. 'reset' => '0'
  78. );
  79. function __construct() {
  80. add_action('plugins_loaded', array($this, 'version_patches'));
  81. add_action('init', array($this, 'localize_plugin'));
  82. add_action('admin_menu', array($this, 'render_admin_menu'));
  83. add_action('admin_init', array($this, 'admin_options_initialize'));
  84. add_action('wp_print_styles', array($this, 'calendar_styles'));
  85. add_action('wp_print_scripts', array($this, 'frontend_calendar_scripts'));
  86. add_action('delete_user', array($this, 'delete_events_by_user'));
  87. add_action('admin_notices', array(&$this, 'admin_alert'));
  88. // ajax hooks
  89. add_action('wp_ajax_nopriv_get_events', array($this, 'render_calendar_events'));
  90. add_action('wp_ajax_get_events', array($this, 'render_calendar_events'));
  91. add_action('wp_ajax_nopriv_get_event', array($this, 'render_frontend_modal'));
  92. add_action('wp_ajax_get_event', array($this, 'render_frontend_modal'));
  93. add_action('wp_ajax_admin_event', array($this, 'render_admin_modal'));
  94. add_action('wp_ajax_add_event', array($this, 'add_event'));
  95. add_action('wp_ajax_copy_event', array($this, 'copy_event'));
  96. add_action('wp_ajax_update_event', array($this, 'update_event'));
  97. add_action('wp_ajax_delete_event', array($this, 'delete_event'));
  98. add_action('wp_ajax_move_event', array($this, 'move_event'));
  99. add_action('wp_ajax_add_category', array($this, 'add_category'));
  100. add_action('wp_ajax_update_filter_label', array($this, 'update_filter_label'));
  101. add_action('wp_ajax_update_category', array($this, 'update_category'));
  102. add_action('wp_ajax_delete_category', array($this, 'confirm_delete_category'));
  103. add_action('wp_ajax_reassign_category', array($this, 'reassign_category'));
  104. // wordpress overrides
  105. add_filter('manage_users_columns', array($this, 'add_events_column'));
  106. add_filter('manage_users_custom_column', array($this, 'add_events_column_data'), 10, 3);
  107. add_filter('plugin_action_links', array($this, 'settings_link'), 10, 2);
  108. add_filter('option_page_capability_aec_plugin_options', array($this, 'set_option_page_capability'));
  109. add_shortcode('calendar', array($this, 'render_shortcode_calendar'));
  110. add_shortcode('eventlist', array($this, 'render_shortcode_eventlist'));
  111. // activate shortcode in text widgets
  112. add_filter('widget_text', 'shortcode_unautop');
  113. add_filter('widget_text', 'do_shortcode');
  114. }
  115. function install() {
  116. require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
  117. global $wpdb;
  118. if ($wpdb->get_var('SHOW TABLES LIKE "' . $wpdb->prefix . AEC_EVENT_TABLE . '"') != $wpdb->prefix . AEC_EVENT_TABLE) {
  119. $sql = 'CREATE TABLE ' . $wpdb->prefix . AEC_EVENT_TABLE . ' (
  120. id BIGINT(20) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
  121. user_id INT(10) UNSIGNED NOT NULL,
  122. title VARCHAR(100) NOT NULL,
  123. start DATETIME NOT NULL,
  124. end DATETIME NOT NULL,
  125. repeat_freq TINYINT(4) UNSIGNED DEFAULT 0,
  126. repeat_int TINYINT(4) UNSIGNED DEFAULT 0,
  127. repeat_end DATE,
  128. allDay TINYINT(1) UNSIGNED DEFAULT 0,
  129. category_id TINYINT(4) UNSIGNED NOT NULL,
  130. description VARCHAR(2500),
  131. link VARCHAR(2000),
  132. venue VARCHAR(100),
  133. address VARCHAR(100),
  134. city VARCHAR(50),
  135. state VARCHAR(50),
  136. zip VARCHAR(10),
  137. country VARCHAR(50),
  138. contact VARCHAR(50),
  139. contact_info VARCHAR(50),
  140. access TINYINT(1) UNSIGNED DEFAULT 0,
  141. rsvp TINYINT(1) UNSIGNED DEFAULT 0)
  142. CHARSET=utf8;';
  143. dbDelta($sql);
  144. }
  145. if ($wpdb->get_var('SHOW TABLES LIKE "' . $wpdb->prefix . AEC_CATEGORY_TABLE . '"') != $wpdb->prefix . AEC_CATEGORY_TABLE) {
  146. $sql = 'CREATE TABLE ' . $wpdb->prefix . AEC_CATEGORY_TABLE . ' (
  147. id TINYINT(4) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
  148. category VARCHAR(25) NOT NULL,
  149. bgcolor CHAR(6) NOT NULL,
  150. fgcolor CHAR(6) NOT NULL
  151. ) CHARSET=utf8;
  152. ## DEFAULT CATEGORIES
  153. INSERT INTO ' . $wpdb->prefix . AEC_CATEGORY_TABLE . ' (id, category, bgcolor, fgcolor)
  154. VALUES (NULL, "Event", "517ed6", "FFFFFF"),
  155. (NULL, "Deadline", "e3686c", "FFFFFF"),
  156. (NULL, "Volunteer", "8fc9b0", "FFFFFF");';
  157. dbDelta($sql);
  158. }
  159. // add new role
  160. add_role('calendar_contributor', 'Calendar Contributor', array(
  161. 'read' => 1,
  162. 'aec_add_events' => 1
  163. ));
  164. // add calendar capabilities to administrator
  165. $role = get_role('administrator');
  166. $role->add_cap('aec_add_events');
  167. $role->add_cap('aec_manage_events');
  168. $role->add_cap('aec_manage_calendar');
  169. }
  170. function version_patches() {
  171. $plugin_updated = false;
  172. $options = get_option('aec_options');
  173. $current = get_option('aec_version');
  174. // initial and manual option initialization
  175. if (!is_array($options) || !isset($options['reset']) || $options['reset'] == '1') {
  176. update_option('aec_options', $this->plugin_defaults);
  177. }
  178. if (version_compare($current, AEC_VERSION, '==')) {
  179. return;
  180. }
  181. // set version for new plugin installations
  182. if ($current === false) {
  183. update_option('aec_version', AEC_VERSION);
  184. $current = get_option('aec_version');
  185. $plugin_updated = true;
  186. }
  187. // < 0.9.6
  188. if (version_compare($current, '0.9.6', '<')) {
  189. // set title as a required field
  190. $options = $this->insert_option('title', 2);
  191. // update database fields in event table
  192. require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
  193. global $wpdb;
  194. $sql = 'ALTER TABLE ' . $wpdb->prefix . AEC_EVENT_TABLE . ' '
  195. . 'modify venue VARCHAR(100),'
  196. . 'modify city VARCHAR(50),'
  197. . 'modify state CHAR(2),'
  198. . 'modify zip VARCHAR(10),'
  199. . 'modify contact VARCHAR(50),'
  200. . 'modify contact_info VARCHAR(50);';
  201. $wpdb->query($sql);
  202. $plugin_updated = true;
  203. }
  204. // < 0.9.8.1
  205. if (version_compare($current, '0.9.8.1', '<')) {
  206. // add calendar weekend toggle, and event detail map link toggle
  207. $options = $this->insert_option('show_weekends', 1);
  208. $options = $this->insert_option('show_map_link', 1);
  209. $plugin_updated = true;
  210. }
  211. // < 0.9.8.5
  212. if (version_compare($current, '0.9.8.5', '<')) {
  213. // update tables to UTF8 and modify category table
  214. require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
  215. global $wpdb;
  216. $sqla = 'ALTER TABLE ' . $wpdb->prefix . AEC_EVENT_TABLE . ' CONVERT TO CHARACTER SET utf8;';
  217. $wpdb->query($sqla);
  218. $sqlb = 'ALTER TABLE ' . $wpdb->prefix . AEC_CATEGORY_TABLE . ' CONVERT TO CHARACTER SET utf8;';
  219. $wpdb->query($sqlb);
  220. $sqlc = 'ALTER TABLE ' . $wpdb->prefix . AEC_CATEGORY_TABLE . ' '
  221. . 'modify category VARCHAR(100) NOT NULL;';
  222. $wpdb->query($sqlc);
  223. // remove sidebar option
  224. $this->decommission_options(array('sidebar'));
  225. // remove retired administrator capability
  226. $role = get_role('administrator');
  227. $role->remove_cap('aec_run_reports');
  228. // remove retired role
  229. remove_role('blog_calendar_contributor');
  230. // remove outdated widget option
  231. delete_option('widget_upcoming_events');
  232. delete_option('widget_contributor_list');
  233. $plugin_updated = true;
  234. }
  235. // < 0.9.9.1
  236. if (version_compare($current, '0.9.9.1', '<')) {
  237. // update table to support Aussi state length
  238. require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
  239. global $wpdb;
  240. $sql = 'ALTER TABLE ' . $wpdb->prefix . AEC_EVENT_TABLE
  241. . ' MODIFY state CHAR(3);';
  242. $wpdb->query($sql);
  243. // add filter label, description link options and address format options
  244. $options = $this->insert_option('filter_label', 'Show Type');
  245. $options = $this->insert_option('make_links', 0);
  246. $options = $this->insert_option('popup_links', 1);
  247. $options = $this->insert_option('addy_format', 0);
  248. $plugin_updated = true;
  249. }
  250. // < 1.0
  251. if (version_compare($current, '1.0', '<')) {
  252. // update table with repeating event fields, country, larger description, and larger state/province
  253. require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
  254. global $wpdb;
  255. $sql = 'ALTER TABLE ' . $wpdb->prefix . AEC_EVENT_TABLE
  256. . ' MODIFY description VARCHAR(2500),'
  257. . ' MODIFY state VARCHAR(50),'
  258. . ' ADD country VARCHAR(50),'
  259. . ' ADD repeat_freq TINYINT(4) UNSIGNED DEFAULT 0,'
  260. . ' ADD repeat_int TINYINT(4) UNSIGNED DEFAULT 0,'
  261. . ' ADD repeat_end DATE;';
  262. $wpdb->query($sql);
  263. // add mousescroll control, country field, and step d options
  264. $options = $this->insert_option('scroll', 1);
  265. $options = $this->insert_option('country', 0);
  266. $options = $this->insert_option('step_interval', 30);
  267. $plugin_updated = true;
  268. }
  269. // < 1.0.1
  270. if (version_compare($current, '1.0.1', '<')) {
  271. // update to accomodate long urls
  272. require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
  273. global $wpdb;
  274. $sql = 'ALTER TABLE ' . $wpdb->prefix . AEC_EVENT_TABLE
  275. . ' MODIFY link VARCHAR(2000);';
  276. $wpdb->query($sql);
  277. $plugin_updated = true;
  278. }
  279. // update routines completed
  280. if ($plugin_updated) {
  281. // update plugin version
  282. update_option('aec_version', AEC_VERSION);
  283. // add sample event
  284. $_POST['event']['user_id'] = 0; // system id
  285. $_POST['event']['title'] = "Ajax Event Calendar [v" . AEC_VERSION . "] successfully installed!";
  286. $_POST['event']['start_date'] = date('Y-m-d');
  287. $_POST['event']['start_time'] = '00:00:00';
  288. $_POST['event']['end_date'] = date('Y-m-d');
  289. $_POST['event']['end_time'] = '00:00:00';
  290. $_POST['event']['allDay'] = 1;
  291. $_POST['event']['repeat_freq'] = 0;
  292. $_POST['event']['repeat_int'] = 0;
  293. $_POST['event']['repeat_end'] = null;
  294. $_POST['event']['category_id'] = 1;
  295. $_POST['event']['description'] = "Ajax Event Calendar WordPress Plugin is a fully localized (including RTL language support) community calendar that allows authorized users to add, edit, copy, move, resize and delete events into custom categories. Highly customized calendars can be added to pages, posts or text widgets using the <strong>[calendar]</strong> shortcode. Similarly, a list view of events can be added using the <strong>[eventlist]</strong> shortcode. Click on the event link to learn about available the shortcode options.";
  296. $_POST['event']['link'] = AEC_HOMEPAGE;
  297. $_POST['event']['venue'] = 'Cloud Gate "The Bean"';
  298. $_POST['event']['address'] = '201 East Randolph Street';
  299. $_POST['event']['city'] = 'Chicago';
  300. $_POST['event']['state'] = 'Illinois';
  301. $_POST['event']['zip'] = '60601-6530';
  302. $_POST['event']['country'] = 'United States';
  303. $_POST['event']['contact'] = 'Eran Miller';
  304. $_POST['event']['contact_info'] = '123-123-1234';
  305. $_POST['event']['access'] = 1;
  306. $_POST['event']['rsvp'] = 0;
  307. // removes previously created release events and creates a new one
  308. $_POST['user_id'] = $_POST['event']['user_id'];
  309. $this->delete_events_by_user();
  310. $this->db_insert_event($this->cleanse_event_input($_POST['event']), false);
  311. }
  312. }
  313. function set_admin_alert($message) {
  314. array_push($this->admin_messages, print_r($message, true));
  315. }
  316. // display admin alerts
  317. function admin_alert() {
  318. $alerts = $this->admin_messages;
  319. if (count($alerts)) {
  320. foreach ($alerts as $alert) {
  321. printf('<div class="updated">%s</div>', $alert);
  322. }
  323. }
  324. }
  325. function localize_plugin($page) {
  326. load_plugin_textdomain(AEC_NAME, false, AEC_NAME . '/locale/');
  327. $timezone = get_option('timezone_string');
  328. if ($timezone) {
  329. date_default_timezone_set($timezone);
  330. } else {
  331. // TODO: look into converting gmt_offset into timezone_string
  332. date_default_timezone_set('UTC');
  333. }
  334. // localization: date/time
  335. if (get_option('timezone_string')) {
  336. $this->timezone = get_option('timezone_string');
  337. } else {
  338. $this->set_admin_alert(sprintf('<p>Ajax Event Calendar %s.<br>%s... <a href="http://www.travelmath.com/time-zone/" target="_blank"><strong>%s</strong></a>.</p>
  339. <h3><a href="' . admin_url() . 'options-general.php">%s</a></h3>'
  340. , __('requires a city value for the Timezone setting', AEC_NAME)
  341. , __("Not all cities are listed. Can't find your city in the timezone dropdown?", AEC_NAME)
  342. , __('Search for your standardized timezone.', AEC_NAME)
  343. , __('Update Blog Settings', AEC_NAME)));
  344. }
  345. // get_magic_quotes_gpc issue
  346. if (get_magic_quotes_gpc()) {
  347. $this->set_admin_alert(sprintf('<p>%s %s <br>%s <a href="http://wordpress.org/support/topic/plugin-ajax-event-calendar-ajax-event-calendar-dont-like-the-apostrophes?replies=11#post-2259386" target="_blank"> <strong>%s</strong></a>. %s</p>'
  348. , __('Your server has PHP magic_quotes_gpc set to active.', AEC_NAME)
  349. , __('This produces formatting errors in the Ajax Event Calendar plugin.', AEC_NAME)
  350. , __('Learn how to disable this setting', AEC_NAME)
  351. , __('in this forum thread', AEC_NAME)
  352. , __('Ask your host provider for help.', AEC_NAME)));
  353. }
  354. // register scripts
  355. wp_register_script('fullcalendar', AEC_URL . 'js/jquery.fullcalendar.min.js', array('jquery'), '1.5.3', true);
  356. wp_register_script('simplemodal', AEC_URL . 'js/jquery.simplemodal.1.4.3.min.js', array('jquery'), '1.4.3', true);
  357. wp_register_script('jquery-ui-datepicker', AEC_URL . 'js/jquery.ui.datepicker.min.js', array('jquery-ui-core'), '1.8.5', true);
  358. wp_register_script('datepicker-locale', AEC_URL . 'js/i18n/jquery.ui.datepicker-' . substr(get_locale(), 0, 2) . '.js', array('jquery-ui-datepicker'), '1.8.5', true);
  359. wp_register_script('timepicker', AEC_URL . 'js/jquery.timePicker.min.js', array('jquery'), '5195', true);
  360. wp_register_script('growl', AEC_URL . 'js/jquery.jgrowl.min.js', array('jquery'), '1.2.5', true);
  361. wp_register_script('miniColors', AEC_URL . 'js/jquery.miniColors.min.js', array('jquery'), '0.1', true);
  362. wp_register_script('jeditable', AEC_URL . 'js/jquery.jeditable.min.js', array('jquery'), '1.7.1', true);
  363. wp_register_script('mousewheel', AEC_URL . 'js/jquery.mousewheel.min.js', array('jquery'), '3.0.6', true);
  364. wp_register_script('init_admin_calendar', AEC_URL . 'js/jquery.init_admin_calendar.js', array('jquery'), AEC_VERSION, true);
  365. wp_register_script('init_show_calendar', AEC_URL . 'js/jquery.init_show_calendar.js', array('jquery'), AEC_VERSION, true);
  366. wp_register_script('init_show_category', AEC_URL . '/js/jquery.init_admin_category.js', array('jquery'), AEC_VERSION, true);
  367. wp_register_script('tweet', 'http://platform.twitter.com/widgets.js', false, '1.0', true);
  368. wp_register_script('facebook', 'http://connect.facebook.net/en_US/all.js#xfbml=1', false, '1.0', true);
  369. // register styles
  370. wp_register_style('custom', AEC_URL . 'css/custom.css', null, AEC_VERSION);
  371. wp_register_style('custom_rtl', AEC_URL . 'css/custom_rtl.css', null, AEC_VERSION);
  372. wp_register_style('jq_ui_css', AEC_URL . 'css/jquery-ui-1.8.16.custom.css', null, '1.8.16');
  373. }
  374. function render_admin_menu() {
  375. if (function_exists('add_options_page')) {
  376. // main menu page: calendar
  377. $page = add_menu_page('Ajax Event Calendar', __('Calendar', AEC_NAME), 'aec_add_events', AEC_FILE, array($this, 'render_admin_calendar'), AEC_URL . 'css/images/em-icon-16.png', AEC_MENU_POSITION);
  378. // calendar admin specific scripts and styles
  379. add_action("admin_print_scripts-$page", array($this, 'admin_calendar_scripts'));
  380. add_action("admin_print_styles-$page", array($this, 'calendar_styles'));
  381. if (current_user_can('aec_manage_calendar')) {
  382. // sub menu page: category management
  383. $sub_category = add_submenu_page(AEC_FILE, 'Categories', __('Categories', AEC_NAME), 'aec_manage_calendar', 'aec_manage_categories', array($this, 'render_admin_category'));
  384. // category admin specific scripts and styles
  385. add_action("admin_print_scripts-$sub_category", array($this, 'admin_category_scripts'));
  386. add_action("admin_print_scripts-$sub_category", array($this, 'admin_social_scripts'));
  387. add_action("admin_print_styles-$sub_category", array($this, 'admin_category_styles'));
  388. // sub menu page: activity report
  389. $sub_report = add_submenu_page(AEC_FILE, 'Activity Report', __('Activity Report', AEC_NAME), 'aec_manage_calendar', 'aec_activity_report', array($this, 'render_activity_report'));
  390. add_action("admin_print_scripts-$sub_report", array($this, 'admin_social_scripts'));
  391. add_action("admin_print_styles-$sub_report", array($this, 'calendar_styles'));
  392. // sub menu page: calendar options
  393. $sub_options = add_submenu_page(AEC_FILE, 'Options', __('Options', AEC_NAME), 'aec_manage_calendar', 'aec_calendar_options', array($this, 'render_calendar_options'));
  394. add_action("admin_print_scripts-$sub_options", array($this, 'admin_social_scripts'));
  395. add_action("admin_print_styles-$sub_options", array($this, 'calendar_styles'));
  396. }
  397. }
  398. }
  399. // STYLES, SCRIPTS & VIEWS
  400. function localized_variables() {
  401. $options = get_option('aec_options');
  402. // initialize required form fields
  403. foreach ($options as $option => $value) {
  404. if ($value == 2) {
  405. $this->add_required_field($option);
  406. }
  407. }
  408. $isEuroDate = $this->parse_date_format(AEC_WP_DATE_FORMAT);
  409. $is24HrTime = $this->parse_time_format(AEC_WP_TIME_FORMAT);
  410. return array(
  411. 'is_rtl' => is_rtl(),
  412. 'locale' => AEC_LOCALE,
  413. 'start_of_week' => get_option('start_of_week'),
  414. 'step_interval' => intval($options['step_interval'], 10),
  415. 'datepicker_format' => ($isEuroDate) ? 'dd-mm-yy' : 'mm/dd/yy', // jquery datepicker format
  416. 'is24HrTime' => $is24HrTime,
  417. 'show_weekends' => $options['show_weekends'],
  418. 'agenda_time_format' => ($is24HrTime) ? 'H:mm{ - H:mm}' : 'h:mmt{ - h:mmt}',
  419. 'other_time_format' => ($is24HrTime) ? 'H:mm' : 'h:mmt',
  420. 'axis_time_format' => ($is24HrTime) ? 'HH:mm' : 'h:mmt',
  421. 'limit' => $options['limit'],
  422. 'today' => __('Today', AEC_NAME),
  423. 'all_day' => __('All Day', AEC_NAME),
  424. 'years' => __('Years', AEC_NAME),
  425. 'year' => __('Year', AEC_NAME),
  426. 'months' => __('Months', AEC_NAME),
  427. 'month' => __('Month', AEC_NAME),
  428. 'weeks' => __('Weeks', AEC_NAME),
  429. 'week' => __('Week', AEC_NAME),
  430. 'days' => __('Days', AEC_NAME),
  431. 'day' => __('Day', AEC_NAME),
  432. 'hours' => __('Hours', AEC_NAME),
  433. 'hour' => __('Hour', AEC_NAME),
  434. 'minutes' => __('Minutes', AEC_NAME),
  435. 'minute' => __('Minute', AEC_NAME),
  436. 'january' => __('January', AEC_NAME),
  437. 'february' => __('February', AEC_NAME),
  438. 'march' => __('March', AEC_NAME),
  439. 'april' => __('April', AEC_NAME),
  440. 'may' => __('May', AEC_NAME),
  441. 'june' => __('June', AEC_NAME),
  442. 'july' => __('July', AEC_NAME),
  443. 'august' => __('August', AEC_NAME),
  444. 'september' => __('September', AEC_NAME),
  445. 'october' => __('October', AEC_NAME),
  446. 'november' => __('November', AEC_NAME),
  447. 'december' => __('December', AEC_NAME),
  448. 'jan' => __('Jan', AEC_NAME),
  449. 'feb' => __('Feb', AEC_NAME),
  450. 'mar' => __('Mar', AEC_NAME),
  451. 'apr' => __('Apr', AEC_NAME),
  452. 'may_short' => _x('May', 'Three-letter month name abbreviation', AEC_NAME),
  453. 'jun' => __('Jun', AEC_NAME),
  454. 'jul' => __('Jul', AEC_NAME),
  455. 'aug' => __('Aug', AEC_NAME),
  456. 'sep' => __('Sep', AEC_NAME),
  457. 'oct' => __('Oct', AEC_NAME),
  458. 'nov' => __('Nov', AEC_NAME),
  459. 'dec' => __('Dec', AEC_NAME),
  460. 'sunday' => __('Sunday', AEC_NAME),
  461. 'monday' => __('Monday', AEC_NAME),
  462. 'tuesday' => __('Tuesday', AEC_NAME),
  463. 'wednesday' => __('Wednesday', AEC_NAME),
  464. 'thursday' => __('Thursday', AEC_NAME),
  465. 'friday' => __('Friday', AEC_NAME),
  466. 'saturday' => __('Saturday', AEC_NAME),
  467. 'sun' => __('Sun', AEC_NAME),
  468. 'mon' => __('Mon', AEC_NAME),
  469. 'tue' => __('Tue', AEC_NAME),
  470. 'wed' => __('Wed', AEC_NAME),
  471. 'thu' => __('Thu', AEC_NAME),
  472. 'fri' => __('Fri', AEC_NAME),
  473. 'sat' => __('Sat', AEC_NAME),
  474. 'close_event_form' => __('Close Event Form', AEC_NAME),
  475. 'loading_event_form' => __('Loading Event Form...', AEC_NAME),
  476. 'update_btn' => __('Update', AEC_NAME),
  477. 'delete_btn' => __('Delete', AEC_NAME),
  478. 'category_type' => __('Category type', AEC_NAME),
  479. 'hide_all_notifications' => __('hide all notifications', AEC_NAME),
  480. 'has_been_created' => __('has been created.', AEC_NAME),
  481. 'has_been_modified' => __('has been modified.', AEC_NAME),
  482. 'has_been_deleted' => __('has been deleted.', AEC_NAME),
  483. 'add_event' => __('Add Event', AEC_NAME),
  484. 'edit_event' => __('Edit Event', AEC_NAME),
  485. 'delete_event' => __('Delete this event?', AEC_NAME),
  486. 'loading' => __('Loading Events...', AEC_NAME),
  487. 'category_filter_label' => __('Category filter label', AEC_NAME),
  488. 'repeats_every' => __('Repeats Every', AEC_NAME),
  489. 'until' => __('Until', AEC_NAME),
  490. 'success' => __('Success!', AEC_NAME),
  491. 'whoops' => __('Whoops!', AEC_NAME)
  492. );
  493. }
  494. function admin_calendar_variables() {
  495. $is_admin = (current_user_can('aec_manage_events')) ? 1 : 0;
  496. $options = get_option('aec_options');
  497. return array_merge($this->localized_variables(),
  498. array(
  499. 'admin' => $is_admin,
  500. 'scroll' => $options['scroll'],
  501. 'required_fields' => join(",", $this->get_required_fields()),
  502. 'editable' => true,
  503. 'error_no_rights' => __('You cannot edit events created by other users.', AEC_NAME),
  504. 'error_past_create' => __('You cannot create events in the past.', AEC_NAME),
  505. 'error_future_create' => __('You cannot create events more than a year in advance.', AEC_NAME),
  506. 'error_past_resize' => __('You cannot resize expired events.', AEC_NAME),
  507. 'error_past_move' => __('You cannot move events into the past.', AEC_NAME),
  508. 'error_past_edit' => __('You cannot edit expired events.', AEC_NAME),
  509. 'error_invalid_duration' => __('Invalid duration.', AEC_NAME)
  510. )
  511. );
  512. }
  513. function frontend_calendar_variables() {
  514. return array_merge($this->localized_variables(),
  515. array(
  516. 'ajaxurl' => admin_url('admin-ajax.php', is_ssl() ? 'https' : 'http'),
  517. 'editable' => false
  518. )
  519. );
  520. }
  521. function admin_category_variables() {
  522. return array_merge($this->localized_variables(),
  523. array(
  524. 'error_blank_category' => __('Category type cannot be a blank value.', AEC_NAME),
  525. 'confirm_category_delete' => __('Are you sure you want to delete this category type?', AEC_NAME),
  526. 'confirm_category_reassign' => __('Several events are associated with this category. Click OK to reassign these events to the default category.', AEC_NAME),
  527. 'events_reassigned' => __('Events have been reassigned to the default category.', AEC_NAME)
  528. )
  529. );
  530. }
  531. function calendar_styles() {
  532. // disabled: until I can conditionally load these scripts in text widgets with shortcodes
  533. // if ($this->has_shortcode('calendar') || $this->has_shortcode('eventlist')) {
  534. wp_enqueue_style('jq_ui_css');
  535. wp_enqueue_style('categories');
  536. wp_enqueue_style('custom');
  537. if (is_rtl()) {
  538. wp_enqueue_style('custom_rtl');
  539. }
  540. //}
  541. }
  542. function admin_category_styles() {
  543. wp_enqueue_style('categories');
  544. wp_enqueue_style('custom');
  545. if (is_rtl()) {
  546. wp_enqueue_style('custom_rtl');
  547. }
  548. }
  549. function admin_calendar_scripts() {
  550. wp_enqueue_script('jquery');
  551. wp_enqueue_script('jquery-ui-core');
  552. wp_enqueue_script('jquery-ui-draggable');
  553. wp_enqueue_script('jquery-ui-resizable');
  554. wp_enqueue_script('jquery-ui-datepicker');
  555. if (AEC_LOCALE != 'en') {
  556. wp_enqueue_script('datepicker-locale'); // if not in English, load localization
  557. }
  558. wp_enqueue_script('fullcalendar');
  559. wp_enqueue_script('simplemodal');
  560. wp_enqueue_script('growl');
  561. wp_enqueue_script('timepicker');
  562. wp_enqueue_script('mousewheel');
  563. wp_enqueue_script('init_admin_calendar');
  564. wp_localize_script('init_admin_calendar', 'custom', $this->admin_calendar_variables());
  565. }
  566. function frontend_calendar_scripts() {
  567. if (is_admin()) {
  568. return;
  569. }
  570. wp_enqueue_script('jquery');
  571. wp_enqueue_script('fullcalendar');
  572. wp_enqueue_script('simplemodal');
  573. wp_enqueue_script('mousewheel');
  574. wp_enqueue_script('growl');
  575. wp_enqueue_script('jquery-ui-datepicker');
  576. if (AEC_LOCALE != 'en') {
  577. wp_enqueue_script('datepicker-locale'); // if not in English, load localization
  578. }
  579. wp_enqueue_script('init_show_calendar');
  580. wp_localize_script('init_show_calendar', 'custom', $this->frontend_calendar_variables());
  581. }
  582. function admin_social_scripts() {
  583. wp_enqueue_script('tweet');
  584. wp_enqueue_script('facebook');
  585. }
  586. function admin_category_scripts() {
  587. wp_enqueue_script('jquery');
  588. wp_enqueue_script('growl');
  589. wp_enqueue_script('miniColors');
  590. wp_enqueue_script('jeditable');
  591. wp_enqueue_script('init_show_category');
  592. wp_localize_script('init_show_category', 'custom', $this->admin_category_variables());
  593. }
  594. function render_aec_version() {
  595. return "<span class='aec-credit'>AEC v" . AEC_VERSION . "</span>\n";
  596. }
  597. function render_admin_calendar() {
  598. if (!current_user_can('aec_add_events')) {
  599. wp_die(__('You do not have sufficient permissions to access this page.', AEC_NAME));
  600. }
  601. $options = get_option('aec_options');
  602. $out = $this->generate_css();
  603. $out .= "<div class='wrap'>\n";
  604. $out .= "<a href='". AEC_HOMEPAGE . "' target='_blank'><span class='em-icon icon32'></span></a>\n";
  605. $out .= $this->render_category_filter($options);
  606. $out .= "<h2>" . __('Ajax Event Calendar', AEC_NAME) . "</h2>\n";
  607. $out .= "<div id='aec-calendar'></div>\n";
  608. $out .= $this->render_aec_version();
  609. $out .= "</div>\n";
  610. echo $out;
  611. }
  612. function render_shortcode_calendar($atts) {
  613. extract(shortcode_atts(array(
  614. 'categories' => '',
  615. 'excluded' => 0,
  616. 'filter' => 'all',
  617. 'month' => date('m'),
  618. 'year' => date('Y'),
  619. 'view' => 'month',
  620. 'views' => 'month,agendaWeek',
  621. 'nav' => 'prev,next, today',
  622. 'height' => '',
  623. 'scroll' => 0,
  624. 'mini' => 0
  625. ), $atts));
  626. // shortcode input validation
  627. $isTrue = array("true", "1");
  628. $isFalse = array("false", "0");
  629. $viewopts = array("month", "agendaWeek", "agendaDay", "basicWeek", "basicDay");
  630. $categories = $this->cleanse_shortcode_input($categories);
  631. $excluded = ($categories && $excluded) ? $excluded : 0;
  632. if (in_array($filter, $isFalse, true)) {
  633. $filter = false;
  634. } elseif (intval($filter)) {
  635. $filter = 'cat' . intval($filter);
  636. } else {
  637. $filter = 'all';
  638. }
  639. $month = intval($month)-1;
  640. if ($year != date('Y')) {
  641. $year = intval($year);
  642. }
  643. if (!in_array($view, $viewopts)) {
  644. $view = 'month';
  645. }
  646. if (!intval($height)) {
  647. $height = '';
  648. }
  649. if (in_array($scroll, $isTrue, true)) {
  650. $scroll = 1;
  651. }
  652. if (in_array($mini, $isTrue, true)) {
  653. $mini = 1;
  654. $views = '';
  655. $filter = 0;
  656. $height = 200;
  657. }
  658. $out = $this->generate_css();
  659. // pass shortcode parameters to javascript
  660. $out .= "<script type='text/javascript'>\n";
  661. $out .= "var shortcode = {\n";
  662. $out .= "categories: '{$categories}',\n";
  663. $out .= "excluded: {$excluded},\n";
  664. $out .= "filter: '{$filter}',\n";
  665. $out .= "view: '{$view}',\n";
  666. $out .= "month: {$month},\n";
  667. $out .= "year: {$year},\n";
  668. $out .= "views: '{$views}',\n";
  669. $out .= "nav: '{$nav}',\n";
  670. $out .= "height: '{$height}',\n";
  671. $out .= "scroll: {$scroll},\n";
  672. $out .= "mini: {$mini}\n";
  673. $out .= "};\n";
  674. $out .= "</script>\n";
  675. $out .= "<div id='aec-container'>\n";
  676. $out .= "<div id='aec-header'>\n";
  677. $options = get_option('aec_options');
  678. if ($options['menu']) {
  679. $out .= "<div id='aec-menu'>\n";
  680. $out .= "<a href='" . admin_url() . "admin.php?page=ajax-event-calendar.php'>" . __('Add Events', AEC_NAME) . "</a>";
  681. $out .= "</div>\n";
  682. }
  683. if ($filter) {
  684. $out .= $this->render_category_filter($options, $categories, $excluded);
  685. }
  686. $out .= "</div>\n";
  687. $out .= "<div id='aec-calendar'></div>\n";
  688. $out .= $this->render_aec_version();
  689. $out .= "</div>\n";
  690. return $out;
  691. }
  692. function render_shortcode_eventlist($atts) {
  693. // shortcode defaults
  694. extract(shortcode_atts(array(
  695. 'categories' => false,
  696. 'excluded' => false,
  697. 'start' => date('Y-m-d'),
  698. 'end' => date('Y-m-d', mktime(0, 0, 0, date("m"), date("d"), date("Y")+1)),
  699. 'limit' => 4,
  700. 'whitelabel' => false,
  701. 'noresults' => __('No upcoming events', AEC_NAME)
  702. ), $atts));
  703. // shortcode input validation
  704. $categories = (isset($categories)) ? $this->cleanse_shortcode_input($categories) : false;
  705. $excluded = ($categories && isset($excluded)) ? $excluded : false;
  706. $limit = ($limit == "none") ? false : intval($limit);
  707. $whitelabel = ($whitelabel == "true") ? true : false;
  708. $start = date('Y-m-d', strtotime($start));
  709. $end = date('Y-m-d', strtotime($end));
  710. $events = $this->db_query_events($start, $end, $categories, $excluded, $limit);
  711. $events = $this->process_events($events, $start, $end, true);
  712. $out = $this->generate_css();
  713. $out .= "<ul class='aec-eventlist'>";
  714. if ($events) {
  715. $out .= $this->render_eventlist_events($events, $whitelabel, $limit);
  716. } else {
  717. $out .= "<li>{$noresults}</li>";
  718. }
  719. $out .= "</ul>\n";
  720. $out .= $this->render_aec_version();
  721. return $out;
  722. }
  723. function render_calendar_events() {
  724. $categories = (isset($_POST['categories'])) ? $this->cleanse_shortcode_input($_POST['categories']) : false;
  725. $excluded = ($categories && isset($_POST['excluded'])) ? $_POST['excluded'] : false;
  726. $start = date('Y-m-d', $_POST['start']);
  727. $end = date('Y-m-d', $_POST['end']);
  728. $readonly = (isset($_POST['readonly'])) ? true : false;
  729. $events = $this->db_query_events($start, $end, $categories, $excluded);
  730. $this->render_json($this->process_events($events, $start, $end, $readonly));
  731. }
  732. function render_eventlist_events($events, $whitelabel, $limit) {
  733. usort($events, array($this, 'array_compare_order'));
  734. $rows = $this->convert_array_to_object($events);
  735. $out = '';
  736. foreach ($rows as $count => $row) {
  737. //if ($count < $limit) {
  738. if (!$limit || $count < $limit) {
  739. // split database formatted datetime value into display formatted date and time values
  740. $row->start_date = $this->convert_date($row->start, AEC_DB_DATETIME_FORMAT, AEC_WP_DATE_FORMAT);
  741. $row->start_time = $this->convert_date($row->start, AEC_DB_DATETIME_FORMAT, AEC_WP_TIME_FORMAT);
  742. $row->end_date = $this->convert_date($row->end, AEC_DB_DATETIME_FORMAT, AEC_WP_DATE_FORMAT);
  743. $row->end_time = $this->convert_date($row->end, AEC_DB_DATETIME_FORMAT, AEC_WP_TIME_FORMAT);
  744. // link to event
  745. $class = ($whitelabel) ? '' : ' ' . $row->className;
  746. $out .= '<li class="fc-event round5' . $class . '" onClick="jQuery.aecDialog({\'id\':' . $row->id . ',\'start\':\'' . $row->start . '\',\'end\':\'' . $row->end . '\'});">';
  747. $out .= '<span class="fc-event-time">';
  748. $out .= $row->start_date;
  749. if (!$row->allDay) {
  750. $out .= ' ' . $row->start_time;
  751. }
  752. $out .= '</span>';
  753. $out .= '<span class="fc-event-title">' . $this->render_i18n_data($row->title) . '</span>';
  754. $out .= '</li>';
  755. }
  756. }
  757. return $out;
  758. }
  759. function render_category_filter($options, $categories=false, $excluded=false) {
  760. $categories = $this->db_query_categories($categories, $excluded);
  761. if (sizeof($categories) > 1) {
  762. $out = "<ul id='aec-filter'>\n";
  763. $out .= "<li>" . $this->render_i18n_data($options['filter_label']) . "</li>\n";
  764. $out .= '<li class="active"><a class="round5 all">' . __('All', AEC_NAME) . '</a></li>' . "\n";
  765. foreach ($categories as $category) {
  766. $out .= '<li><a class="round5 cat' . $category->id . '">' . $this->render_i18n_data($category->category) . '</a></li>' . "\n";
  767. }
  768. $out .= "</ul>\n";
  769. return $out;
  770. }
  771. }
  772. function render_admin_modal() {
  773. if (!current_user_can('aec_add_events')) {
  774. wp_die(__('You do not have sufficient permissions to access this page.', AEC_NAME));
  775. }
  776. require_once AEC_PATH . 'inc/admin-event.php';
  777. exit();
  778. }
  779. function render_frontend_modal() {
  780. require_once AEC_PATH . 'inc/show-event.php';
  781. }
  782. function render_admin_category() {
  783. if (!current_user_can('aec_manage_calendar')) {
  784. wp_die(__('You do not have sufficient permissions to access this page.', AEC_NAME));
  785. }
  786. $add = $this->generate_css();
  787. $add .= $this->add_wrap(__('To add a new category, enter a category label and select a background color.', AEC_NAME), "<p>", "</p>");
  788. $add .= "<form id='aec-category-form'>\n";
  789. $add .= "<input type='hidden' id='fgcolor' name='fgcolor' class='fg ltr' value='#FFFFFF' />";
  790. $add .= "<p><input type='text' id='category' name='category' value='' /> ";
  791. $add .= "<input class='bg colors ltr' type='text' id='bgcolor' name='bgcolor' value='#005294' size='7' maxlength='7' autocomplete='off' /> ";
  792. $add .= $this->add_wrap(__('Add', AEC_NAME), "<button class='add button-primary'>", "</button></p>");
  793. $add .= "</form>\n";
  794. $aec_options = get_option('aec_options');
  795. $add .= $this->add_wrap(__('Category filter label', AEC_NAME), "<p>", "</p>");
  796. $add .= $this->add_wrap("<input type='text' name='filter_label' id='filter_label' value='" . esc_attr($this->render_i18n_data($aec_options['filter_label'])) . "' />", "<p>", "");
  797. $add .= $this->add_wrap(__('Update', AEC_NAME), "<button id='filter_update' class='filter-update button-secondary'>", "</button></p>");
  798. $add .= $this->add_wrap(__('Category IDs are displayed in color bubbles at the beginning of each row.' , AEC_NAME), "<p>", "<br/>");
  799. $add .= $this->add_wrap(__('To change category color, click the color swatch or edit the hex color value and click Update.', AEC_NAME), "", "</p>");
  800. $add .= "<form id='aec-category-list'>\n";
  801. $categories = $this->db_query_categories();
  802. foreach ($categories as $category) {
  803. $add .= "<p id='id_{$category->id}'>\n";
  804. $add .= "<input type='hidden' name='fgcolor' value='#{$category->fgcolor}' class='fg ltr' />\n";
  805. $add .= "<span class='round5 cat{$category->id}'>{$category->id}</span> ";
  806. $add .= "<input type='text' name='category' value='" . $this->render_i18n_data($category->category) . "' class='edit' />\n";
  807. $add .= "<input type='text' name='bgcolor' size='7' maxlength='7' autocomplete='off' value='#{$category->bgcolor}' class='bg colors ltr' />\n";
  808. $add .= $this->add_wrap(__('Update', AEC_NAME), "<button class='update button-secondary'>", "</button>");
  809. if ($category->id > 1) {
  810. $add .= $this->add_wrap(__('Delete', AEC_NAME), "<button class='button-secondary delete'>", "</button>");
  811. }
  812. $add .= "</p>\n";
  813. }
  814. $add .= "</form>\n";
  815. $out = $this->add_panel(__('Manage Categories', AEC_NAME), $add);
  816. $top = "<a href='http://". AEC_HOMEPAGE . "' target='_blank'><span class='em-icon icon32'></span></a>\n";
  817. $top .= $this->add_wrap(__('Categories', AEC_NAME), "<h2>", "</h2>");
  818. $out = $this->add_wrap($out, "<div class='postbox-container' style='width:65%'>", "</div>");
  819. $out .= $this->add_sidebar();
  820. echo $this->add_wrap($out, "<div class='wrap'>{$top}", "</div>");
  821. }
  822. function render_activity_report() {
  823. if (!current_user_can('aec_manage_calendar')) {
  824. wp_die(__('You do not have sufficient permissions to access this page.', AEC_NAME));
  825. }
  826. $rows = $this->db_query_monthly_activity();
  827. $out = $this->generate_css();
  828. if (count($rows)) {
  829. foreach ($rows as $row) {
  830. $out .= "<p class='round5 cat{$row->category_id}'>{$row->cnt} ";
  831. $out .= $this->render_i18n_data($row->category);
  832. $out .= " " . _n('Event', 'Events', $row->cnt, AEC_NAME);
  833. $out .= "</p>\n";
  834. }
  835. $out .= $this->add_wrap(__('NOTE: Each repeating event is counted once.', AEC_NAME), "<p><em>", "</em></p>");
  836. } else {
  837. $out .= $this->add_wrap(__('No events this month.', AEC_NAME), "<p><em>", "</em></p>");
  838. }
  839. $out = $this->add_panel(__('Number of events scheduled for the current month, by category:', AEC_NAME), $out);
  840. $top = "<a href='http://". AEC_HOMEPAGE . "' target='_blank'><span class='em-icon icon32'></span></a>\n";
  841. $top .= $this->add_wrap(__('Activity Report', AEC_NAME), "<h2>", "</h2>");
  842. $out = $this->add_wrap($out, "<div class='postbox-container' style='width:65%'>", "</div>");
  843. $out .= $this->add_sidebar();
  844. echo $this->add_wrap($out, "<div class='wrap'>{$top}", "</div>");
  845. }
  846. function render_calendar_options() {
  847. if (!current_user_can('aec_manage_calendar')) {
  848. wp_die(__('You do not have sufficient permissions to access this page.', AEC_NAME));
  849. }
  850. require_once AEC_PATH . 'inc/admin-options.php';
  851. }
  852. function process_events($events, $start, $end, $readonly) {
  853. if ($events) {
  854. $output = array();
  855. foreach ($events as $event) {
  856. $event->view_start = $start;
  857. $event->view_end = $end;
  858. $event = $this->process_event($event, $readonly, true);
  859. if (is_array($event)) {
  860. foreach ($event as $repeat) {
  861. array_push($output, $repeat);
  862. }
  863. } else {
  864. array_push($output, $event);
  865. }
  866. }
  867. return $output;
  868. }
  869. }
  870. function process_event($input, $readonly=false, $queue=false) {
  871. $output = array();
  872. if ($repeats = $this->generate_repeating_event($input)) {
  873. foreach ($repeats as $repeat) {
  874. array_push($output, $this->generate_event($repeat, $this->return_auth($readonly), $queue));
  875. }
  876. } else {
  877. array_push($output, $this->generate_event($input, $this->return_auth($readonly), $queue));
  878. }
  879. if ($queue) {
  880. return $output;
  881. }
  882. $this->render_json($output);
  883. }
  884. function generate_repeating_event($event) {
  885. if ($event->repeat_freq) {
  886. $event_start = strtotime($event->start);
  887. $event_end = strtotime($event->end);
  888. $repeat_end = strtotime($event->repeat_end) + 86400;
  889. $view_start = strtotime($event->view_start);
  890. $view_end = strtotime($event->view_end);
  891. $repeats = array();
  892. while($event_start < $repeat_end) {
  893. if ($event_start >= $view_start && $event_start <= $view_end) {
  894. $event = clone $event; // clone event details and override dates
  895. $event->start = date(AEC_DB_DATETIME_FORMAT, $event_start);
  896. $event->end = date(AEC_DB_DATETIME_FORMAT, $event_end);
  897. array_push($repeats, $event);
  898. }
  899. $event_start = $this->get_next_date($event_start, $event->repeat_freq, $event->repeat_int);
  900. $event_end = $this->get_next_date($event_end, $event->repeat_freq, $event->repeat_int);
  901. }
  902. return $repeats;
  903. }
  904. return false;
  905. }
  906. function get_next_date($date, $freq, $int) {
  907. if ($int == 0) return strtotime("+" . $freq . " days", $date);
  908. if ($int == 1) return strtotime("+" . $freq . " weeks", $date);
  909. if ($int == 2) return $this->get_next_month($date, $freq);
  910. if ($int == 3) return $this->get_next_year($date, $freq);
  911. }
  912. function get_next_month($date, $n = 1) {
  913. $newDate = strtotime("+{$n} months", $date);
  914. // adjustment for events that repeat on the 29th, 30th and 31st of a month
  915. if (date('j', $date) !== (date('j', $newDate))) {
  916. $newDate = strtotime("+" . $n+1 . " months", $date);
  917. }
  918. return $newDate;
  919. }
  920. function get_next_year($date, $n = 1) {
  921. $newDate = strtotime("+{$n} years", $date);
  922. // adjustment for events that repeat on february 29th
  923. if (date('j', $date) !== (date('j', $newDate))) {
  924. $newDate = strtotime("+" . $n+3 . " years", $date);
  925. }
  926. return $newDate;
  927. }
  928. function generate_event($input, $user_id) {
  929. $permissions = new stdClass();
  930. $permissions = $this->get_event_permissions($input, $user_id);
  931. $repeats = ($input->repeat_freq) ? ' aec-repeating' : '';
  932. $output = array(
  933. 'id' => $input->id,
  934. 'title' => $input->title,
  935. 'start' => $input->start,
  936. 'end' => $input->end,
  937. 'allDay' => ($input->allDay) ? true : false,
  938. 'className' => "cat{$input->category_id}{$permissions->cssclass}{$repeats}",
  939. 'editable' => $permissions->editable,
  940. 'repeat_i' => $input->repeat_int,
  941. 'repeat_f' => $input->repeat_freq,
  942. 'repeat_e' => $input->repeat_end
  943. );
  944. return $output;
  945. }
  946. function get_event_permissions($input, $user_id) {
  947. $permissions = new stdClass();
  948. // users that are not logged-in see all events
  949. if ($user_id == -1) {
  950. $permissions->editable = false;
  951. $permissions->cssclass = '';
  952. } else {
  953. // users with aec_manage_events capability can edit all events
  954. // users with aec_add_events capability can edit events only they create
  955. if ($input->user_id == $user_id || $user_id == false) {
  956. $permissions->editable = true;
  957. $permissions->cssclass = '';
  958. } else {
  959. $permissions->editable = false;
  960. $permissions->cssclass = ' fc-event-disabled';
  961. }
  962. }
  963. return $permissions;
  964. }
  965. // OPTION CONTROLS
  966. function add_panel($name, $content) {
  967. $before = "<div class='metabox-holder'>\n";
  968. $before .= "<div class='postbox'>\n";
  969. $before .= "<h3 style='cursor:default'><span>{$name}</span></h3>\n";
  970. $before .= "<div class='inside'>\n";
  971. $after = str_repeat("</div>\n", 3);
  972. return $this->add_wrap($content, $before, $after);
  973. }
  974. function add_hidden_field($field, $value=false) {
  975. if ($value === false) {
  976. $aec_options = get_option('aec_options');
  977. $value = $aec_options[$field];
  978. }
  979. return "<input type='hidden' name='aec_options[{$field}]' value='{$value}' />\n";
  980. }
  981. function add_text_field($field, $label, $tip=false) {
  982. $aec_options = get_option('aec_options');
  983. $out = "<label for='{$field}' class='semi'>{$label}</label>\n";
  984. $out .= "<input type='text' name='aec_options[{$field}]' id='{$field}' value='" . esc_attr($aec_options[$field]) . "' />\n";
  985. if ($tip) {
  986. $out .= "<span class='description'>{$tip}</span>\n";
  987. }
  988. return $this->add_wrap($out, '<p class="hhh">', '</p>');
  989. }
  990. function add_checkbox_field($field, $label, $tip=false) {
  991. $aec_options = get_option('aec_options');
  992. $checked = ($aec_options[$field]) ? ' checked="checked" ' : ' ';
  993. $out = $this->add_hidden_field($field, 0);
  994. $out .= "<input type='checkbox' name='aec_options[{$field}]' id='{$field}' value='1' {$checked} />\n";
  995. $out .= "<label for='{$field}' class='auto'>{$label}</label>\n";
  996. if ($tip) {
  997. $out .= "<span class='description'>{$tip}</span>\n";
  998. }
  999. return $this->add_wrap($out, '<p class="hhh">', '</p>');
  1000. }
  1001. function add_select_field($field, $label, $options, $values=false) {
  1002. $aec_options = get_option('aec_options');
  1003. $out = "<label for='{$field}'>{$label}</label>\n";
  1004. $out .= "<select id='{$field}' class='semi' name='aec_options[{$field}]'>";
  1005. foreach ($options as $option => $value) {
  1006. if (is_numeric($value)) $option = $value;
  1007. if ($values) {
  1008. $option = $values[$option];
  1009. }
  1010. $out .= "<option value='{$option}' name='aec_options[{$field}]' " . selected($aec_options[$field], $option, false) . ">{$value}</option>\n";
  1011. }
  1012. $out .= "</select>\n";
  1013. return $this->add_wrap($out, '<p class="hhh">', '</p>');
  1014. }
  1015. function add_wrap($content, $before='', $after='') {
  1016. return "{$before}{$content}{$after}\n";
  1017. }
  1018. function add_sidebar() {
  1019. $help = $this->add_wrap(__('Read about installation and options', AEC_NAME), "<p><a href='" . AEC_HOMEPAGE . "installation/' target='_blank'>", "</a>.</p>");
  1020. $help .= $this->add_wrap(__('Review the FAQ', AEC_NAME), "<p><a href='" . AEC_HOMEPAGE . "faq/' target='_blank'>", "</a>.</p>");
  1021. $help .= $this->add_wrap(__('Ask for help in the WordPress forum', AEC_NAME), "<p><a href='http://wordpress.org/tags/ajax-event-calendar' target='_blank'>", "</a>.</p>");
  1022. $help .= $this->add_wrap(__('Use the issue tracker', AEC_NAME), "<p><a href='http://code.google.com/p/wp-aec/issues/list' target='_blank'>", "</a> ");
  1023. $help .= $this->add_wrap(__('to track and report bugs, feature requests, and to submit', AEC_NAME), "", "");
  1024. $help .= $this->add_wrap(__('poEdit', AEC_NAME), " (<a href='http://weblogtoolscollection.com/archives/2007/08/27/localizing-a-wordpress-plugin-using-poedit/' target='_blank'>", "</a>)");
  1025. $help .= $this->add_wrap(__('translation files', AEC_NAME), "", ".</p>");
  1026. $like = $this->add_wrap(__('Give the plugin a good rating', AEC_NAME), "<p><a href='" . AEC_HOMEPAGE . "' target='_blank'>", "</a>.</p>");
  1027. $like .= $this->add_wrap(__('Make a donation in recognition of countless hours spent making this plugin', AEC_NAME), "<p>", "</p>");
  1028. $like .= $this->add_wrap("<form style='text-align:center' action='https://www.paypal.com/cgi-bin/webscr' method='post'><input type='hidden' name='cmd' value='_s-xclick' /><input type='hidden' name='hosted_button_id' value='NCDKRE46K2NBA' /><input type='image' src='https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif' name='submit' alt='PayPal - The safer, easier way to pay online!' /><img alt='' border='0' src='https://www.paypalobjects.com/en_US/i/scr/pixel.gif' width='1' height='1' /></form>", "<p>", "</p>");
  1029. $social = $this->add_wrap(__('Create a blog review or an instructional video about the Calendar and share it', AEC_NAME), "<p>", ".</p>");
  1030. $social .= $this->add_wrap("<a href='http://twitter.com/share' class='twitter-share-button' data-url='" . AEC_HOMEPAGE . "' data-count='horizontal' data-via='Ajax Event Calendar WordPress Plugin'>Tweet</a>", "<p>", "</p>");
  1031. $social .= $this->add_wrap("<fb:like href='" . AEC_HOMEPAGE . "'; layout='standard' show_faces='true' width='150' font='arial'></fb:like>", "<p>", "</p>");
  1032. $sidebar = $this->add_panel(__('Support', AEC_NAME), $help);
  1033. $sidebar .= $this->add_panel(__('Share the Love', AEC_NAME), $like);
  1034. $sidebar .= $this->add_panel(__('Spread the Word', AEC_NAME), $social);
  1035. return $this->add_wrap($sidebar, "<div class='postbox-container' style='margin-left:10px; width:20%'>", "</div>");
  1036. }
  1037. // USER ACTIONS
  1038. function add_event() {
  1039. if (!isset($_POST['event'])) {
  1040. return;
  1041. }
  1042. $this->db_insert_event($this->cleanse_event_input($_POST['event']), true);
  1043. }
  1044. function copy_event() {
  1045. if (!isset($_POST['event'])) {
  1046. return;
  1047. }
  1048. $input = $this->cleanse_event_input($_POST['event']);
  1049. $input->user_id = $this->return_current_user_id();
  1050. $this->db_insert_event($input, true);
  1051. }
  1052. function move_event() {
  1053. if (!isset($_POST['event']))
  1054. return;
  1055. $input = $this->convert_array_to_object($_POST['event']);
  1056. $offset = $input->dayDelta*86400 + $input->minuteDelta*60;
  1057. $event = $this->db_query_event($input->id);
  1058. $twoHours = 7200;
  1059. $event->allDay = $input->allDay;
  1060. $event->end = date(AEC_DB_DATETIME_FORMAT, strtotime($event->end) + $offset);
  1061. $event->repeat_end = date(AEC_DB_DATETIME_FORMAT, strtotime($event->repeat_end) + $offset);
  1062. if ($input->resize) { $offset = 0; }
  1063. $event->start = date(AEC_DB_DATETIME_FORMAT, strtotime($event->start) + $offset);
  1064. // add an end date for events with a null end date
  1065. if (isset($input->end)) {
  1066. //if (!$input->allDay && !isset($input->end)) {
  1067. $event->end = date(AEC_DB_DATETIME_FORMAT, strtotime($event->start) + $twoHours);
  1068. }
  1069. $event->view_start = $input->view_start;
  1070. $event->view_end = $input->view_end;
  1071. $this->db_update_event($event);
  1072. }
  1073. function update_event() {
  1074. if (!isset($_POST['event'])) {
  1075. return;
  1076. }
  1077. $this->db_update_event($this->cleanse_event_input($_POST['event']));
  1078. }
  1079. function delete_event() {
  1080. if (!isset($_POST['id'])) {
  1081. return;
  1082. }
  1083. $this->db_delete_event($_POST['id']);
  1084. }
  1085. function delete_events_by_user() {
  1086. if (!isset($_POST['user_id'])) {
  1087. return;
  1088. }
  1089. $this->db_delete_events_by_user($_POST['user_id']);
  1090. }
  1091. function update_filter_label() {
  1092. if (!isset($_POST['label'])) {
  1093. return;
  1094. }
  1095. $this->overwrite_option('filter_label', $this->cleanse_data_input($_POST['label']));
  1096. }
  1097. // outputs added/updated category as json
  1098. function render_category($input) {
  1099. $output = array(
  1100. 'id' => $input->id,
  1101. 'category' => $input->category,
  1102. 'bgcolor' => $input->bgcolor,
  1103. 'fgcolor' => $input->fgcolor
  1104. );
  1105. $this->render_json($output);
  1106. }
  1107. function add_category() {
  1108. if (!isset($_POST['category_data'])) {
  1109. return;
  1110. }
  1111. $this->db_insert_category($this->cleanse_category_input($_POST['category_data']));
  1112. }
  1113. function update_category() {
  1114. if (!isset($_POST['category_data'])) {
  1115. return;
  1116. }
  1117. $this->db_update_category($this->cleanse_category_input($_POST['category_data']));
  1118. }
  1119. function reassign_category() {
  1120. if (!isset($_POST['id'])) {
  1121. return;
  1122. }
  1123. $this->db_reassign_category($_POST['id']);
  1124. }
  1125. function confirm_delete_category() {
  1126. if (!isset($_POST['id'])) {
  1127. return;
  1128. }
  1129. if ($this->db_query_events_by_category($_POST['id'])) {
  1130. $this->render_json('false');
  1131. }
  1132. $this->db_delete_category($_POST['id']);
  1133. }
  1134. // DATABASE QUERIES
  1135. function db_query_monthly_activity() {
  1136. global $wpdb;
  1137. $result = $wpdb->get_results('SELECT COUNT(a.category_id) AS cnt, a.category_id, b.category FROM ' .
  1138. $wpdb->prefix . AEC_EVENT_TABLE . ' AS a ' .
  1139. 'INNER JOIN ' . $wpdb->prefix . AEC_CATEGORY_TABLE . ' AS b ' .
  1140. 'ON a.category_id = b.id ' .
  1141. 'WHERE MONTH(start) = MONTH(NOW()) ' .
  1142. 'GROUP BY category_id ' .
  1143. 'ORDER BY cnt DESC;'
  1144. );
  1145. return $this->return_result($result);
  1146. }
  1147. function db_query_event($id) {
  1148. global $wpdb;
  1149. $result = $wpdb->get_row($wpdb->prepare('SELECT *
  1150. FROM ' . $wpdb->prefix . AEC_EVENT_TABLE . '
  1151. WHERE id = %d ORDER BY start;', $id));
  1152. return $this->return_result($result);
  1153. }
  1154. function db_query_events($start, $end, $category_id, $excluded, $limit=false) {
  1155. global $wpdb;
  1156. $excluded = ($excluded) ? 'NOT IN' : 'IN';
  1157. $andcategory = ($category_id) ? " AND category_id {$excluded}({$category_id})" : '';
  1158. $limit = ($limit) ? " LIMIT {$limit}" : "";
  1159. $result = $wpdb->get_results("SELECT
  1160. id,
  1161. user_id,
  1162. title,
  1163. start,
  1164. end,
  1165. allDay,
  1166. repeat_int,
  1167. repeat_freq,
  1168. repeat_end,
  1169. category_id
  1170. FROM " . $wpdb->prefix . AEC_EVENT_TABLE . "
  1171. WHERE (
  1172. (start >= '{$start}' AND start < '{$end}')
  1173. OR (end >= '{$start}' AND end < '{$end}')
  1174. OR (start <= '{$start}' AND end >= '{$end}')
  1175. OR (start < '{$end}' AND (repeat_freq > 0 AND repeat_end >= '{$start}'))
  1176. )
  1177. {$andcategory} ORDER BY start{$limit};");
  1178. return $this->return_result($result);
  1179. }
  1180. function db_query_events_by_user($user_id) {
  1181. global $wpdb;
  1182. $result = $wpdb->get_var($wpdb->prepare('SELECT count(id)
  1183. FROM ' . $wpdb->prefix . AEC_EVENT_TABLE . '
  1184. WHERE user_id = %d;', $user_id));
  1185. return $this->return_result($result);
  1186. }
  1187. function db_query_events_by_category($id) {
  1188. global $wpdb;
  1189. $result = $wpdb->get_var($wpdb->prepare('SELECT COUNT(*) as count
  1190. FROM ' . $wpdb->prefix . AEC_EVENT_TABLE . '
  1191. WHERE category_id = %d;', $id));
  1192. return $this->return_result($result);
  1193. }
  1194. function db_insert_event($input, $render) {
  1195. global $wpdb;
  1196. $result = $wpdb->insert($wpdb->prefix . AEC_EVENT_TABLE,
  1197. array('user_id' => $input->user_id,
  1198. 'title' => $input->title,
  1199. 'start' => $input->start,
  1200. 'end' => $input->end,
  1201. 'allDay' => $input->allDay,
  1202. 'repeat_freq' => $input->repeat_freq,
  1203. 'repeat_int' => $input->repeat_int,
  1204. 'repeat_end' => $input->repeat_end,
  1205. 'category_id' => $input->category_id,
  1206. 'description' => $input->description,
  1207. 'link' => $input->link,
  1208. 'venue' => $input->venue,
  1209. 'address' => $input->address,
  1210. 'city' => $input->city,
  1211. 'state' => $input->state,
  1212. 'zip' => $input->zip,
  1213. 'country' => $input->country,
  1214. 'contact' => $input->contact,
  1215. 'contact_info' => $input->contact_info,
  1216. 'access' => $input->access,
  1217. 'rsvp' => $input->rsvp
  1218. ),
  1219. array('%d', // user_id
  1220. '%s', // title
  1221. '%s', // start
  1222. '%s', // end
  1223. '%d', // allDay
  1224. '%d', // repeat_freq
  1225. '%d', // repeat_int
  1226. '%s', // repeat_end
  1227. '%d', // category_id
  1228. '%s', // description
  1229. '%s', // link
  1230. '%s', // venue
  1231. '%s', // address
  1232. '%s', // city
  1233. '%s', // state
  1234. '%s', // zip
  1235. '%s', // country
  1236. '%s', // contact
  1237. '%s', // contact_info
  1238. '%d', // access
  1239. '%d' // rsvp
  1240. )
  1241. );
  1242. if ($this->return_result($result)) {
  1243. if ($render) {
  1244. $input->id = $wpdb->insert_id; // id of newly created row
  1245. $this->process_event($input);
  1246. }
  1247. }
  1248. }
  1249. function db_update_event($input) {
  1250. global $wpdb;
  1251. $result = $wpdb->update($wpdb->prefix . AEC_EVENT_TABLE,
  1252. array('user_id' => $input->user_id,
  1253. 'title' => $input->title,
  1254. 'start' => $input->start,
  1255. 'end' => $input->end,
  1256. 'allDay' => $input->allDay,
  1257. 'repeat_freq' => $input->repeat_freq,
  1258. 'repeat_int' => $input->repeat_int,
  1259. 'repeat_end' => $input->repeat_end,
  1260. 'category_id' => $input->category_id,
  1261. 'description' => $input->description,
  1262. 'link' => $input->link,
  1263. 'venue' => $input->venue,
  1264. 'address' => $input->address,
  1265. 'city' => $input->city,
  1266. 'state' => $input->state,
  1267. 'zip' => $input->zip,
  1268. 'country' => $input->country,
  1269. 'contact' => $input->contact,
  1270. 'contact_info' => $input->contact_info,
  1271. 'access' => $input->access,
  1272. 'rsvp' => $input->rsvp
  1273. ),
  1274. array('id' => $input->id),
  1275. array('%d', // user_id
  1276. '%s', // title
  1277. '%s', // start
  1278. '%s', // end
  1279. '%d', // allDay
  1280. '%d', // repeat_freq
  1281. '%d', // repeat_int
  1282. '%s', // repeat_end
  1283. '%d', // category_id
  1284. '%s', // description
  1285. '%s', // link
  1286. '%s', // venue
  1287. '%s', // address
  1288. '%s', // city
  1289. '%s', // state
  1290. '%s', // zip
  1291. '%s', // country
  1292. '%s', // contact
  1293. '%s', // contact_info
  1294. '%d', // access
  1295. '%d' // rsvp
  1296. ),
  1297. array ('%d') // id
  1298. );
  1299. if ($this->return_result($result)) {
  1300. $this->process_event($input);
  1301. }
  1302. }
  1303. function db_delete_event() {
  1304. global $wpdb;
  1305. $result = $wpdb->query($wpdb->prepare('DELETE FROM ' . $wpdb->prefix . AEC_EVENT_TABLE . ' WHERE id = %d;', $_POST['id']));
  1306. $this->render_json($this->return_result($result));
  1307. }
  1308. function db_delete_events_by_user($id) {
  1309. global $wpdb;
  1310. $result = $wpdb->query($wpdb->prepare('DELETE FROM ' . $wpdb->prefix . AEC_EVENT_TABLE . ' WHERE user_id = %d;', $id));
  1311. return $this->return_result($result);
  1312. }
  1313. function db_query_categories($category_id=false, $excluded=false) {
  1314. global $wpdb;
  1315. $excluded = ($excluded) ? 'NOT IN' : 'IN';
  1316. $wherecategory = ($category_id) ? " WHERE id {$excluded}({$category_id})" : '';
  1317. $result = $wpdb->get_results('SELECT * FROM ' . $wpdb->prefix . AEC_CATEGORY_TABLE . $wherecategory . ' ORDER BY id;');
  1318. return $this->return_result($result);
  1319. }
  1320. function db_insert_category($input) {
  1321. global $wpdb;
  1322. $result = $wpdb->insert($wpdb->prefix . AEC_CATEGORY_TABLE,
  1323. array('category' => $input->category,
  1324. 'bgcolor' => $input->bgcolor,
  1325. 'fgcolor' => $input->fgcolor
  1326. ),
  1327. array('%s',
  1328. '%s',
  1329. '%s'
  1330. )
  1331. );
  1332. if ($this->return_result($result)) {
  1333. $input->id = $wpdb->insert_id; // id of newly created row
  1334. $this->render_category($input);
  1335. }
  1336. }
  1337. function db_update_category($input) {
  1338. global $wpdb;
  1339. $result = $wpdb->update($wpdb->prefix . AEC_CATEGORY_TABLE,
  1340. array('category' => $input->category,
  1341. 'bgcolor' => $input->bgcolor,
  1342. 'fgcolor' => $input->fgcolor
  1343. ),
  1344. array('id' => $input->id),
  1345. array('%s',
  1346. '%s',
  1347. '%s'
  1348. ),
  1349. array ('%d') //id
  1350. );
  1351. if ($this->return_result($result)) {
  1352. $this->render_category($input);
  1353. }
  1354. }
  1355. function db_reassign_category($id) {
  1356. global $wpdb;
  1357. $result = $wpdb->update($wpdb->prefix . AEC_EVENT_TABLE,
  1358. array('category_id' => 1),
  1359. array('category_id' => $id),
  1360. array('%d'),
  1361. array('%d')
  1362. );
  1363. if ($this->return_result($result)) {
  1364. $this->db_delete_category($id);
  1365. }
  1366. }
  1367. function db_delete_category($id) {
  1368. global $wpdb;
  1369. $result = $wpdb->query($wpdb->prepare('DELETE FROM ' . $wpdb->prefix . AEC_CATEGORY_TABLE . ' WHERE id = %d;', $id));
  1370. if ($this->return_result($result)) {
  1371. $this->generate_css();
  1372. $this->render_json($result);
  1373. }
  1374. }
  1375. // UTILITIES
  1376. function parse_input($input) {
  1377. if (!is_array($input)) {
  1378. parse_str($input, $array); // convert serialized form into array
  1379. $input = $array;
  1380. }
  1381. array_walk($input, create_function('&$val', '$val = trim($val);')); // trim whitespace from input
  1382. return $input;
  1383. }
  1384. // removes slashes from strings and arrays
  1385. function cleanse_output($output) {
  1386. if (is_array($output)) {
  1387. array_walk_recursive($output, create_function('&$val', '$val = trim(stripslashes($val));'));
  1388. } else {
  1389. $output = stripslashes($output);
  1390. }
  1391. return $output;
  1392. }
  1393. function cleanse_data_input($input) {
  1394. return trim($input);
  1395. }
  1396. function cleanse_event_input($input) {
  1397. $clean = $this->convert_array_to_object($this->parse_input($input));
  1398. if ($clean->allDay) {
  1399. $clean->start_time = '00:00:00';
  1400. $clean->end_time = '00:00:00';
  1401. }
  1402. $clean->start = $this->merge_date_time($clean->start_date, $clean->start_time);
  1403. $clean->end = $this->merge_date_time($clean->end_date, $clean->end_time);
  1404. $clean->repeat_end = substr($this->merge_date_time($clean->repeat_end, '00:00:00'),0,-9);
  1405. return $clean;
  1406. }
  1407. function cleanse_category_input($input) {
  1408. $clean = $this->convert_array_to_object($this->parse_input($input));
  1409. $clean->bgcolor = str_replace('#', '', $clean->bgcolor); // strip '#' for storage
  1410. $clean->fgcolor = str_replace('#', '', $clean->fgcolor);
  1411. return $clean;
  1412. }
  1413. // convert category string input into array, force integer values, return serialized
  1414. function cleanse_shortcode_input($input) {
  1415. $input = explode(',', $input);
  1416. array_walk($input, create_function('&$val', '$val = intval($val);'));
  1417. return join(',', $input);
  1418. }
  1419. // set required fields on admin event detail form
  1420. function add_required_field($field) {
  1421. array_push($this->required_fields, $field);
  1422. }
  1423. function get_required_fields() {
  1424. if (count($this->required_fields)) {
  1425. return $this->required_fields;
  1426. }
  1427. return;
  1428. }
  1429. function convert_object_to_array($object) {
  1430. $array = array();
  1431. foreach ($object as $key => $value) {
  1432. $array[$key] = $value;
  1433. }
  1434. return $array;
  1435. }
  1436. function convert_array_to_object($array = array()) {
  1437. $return = new stdClass();
  1438. foreach ($array as $key => $val) {
  1439. if (is_array($val)) {
  1440. $return->$key = $this->convert_array_to_object($val);
  1441. } else {
  1442. $return->{$key} = $val;
  1443. }
  1444. }
  1445. return $return;
  1446. }
  1447. function return_result($result) {
  1448. if ($result === false) {
  1449. global $wpdb;
  1450. $this->log($wpdb->print_error());
  1451. return false;
  1452. }
  1453. return $result;
  1454. }
  1455. function return_current_user_id() {
  1456. global $current_user;
  1457. get_currentuserinfo();
  1458. return $current_user->ID;
  1459. }
  1460. function return_auth($readonly = false) {
  1461. if ($readonly) {
  1462. return "-1";
  1463. }
  1464. return (current_user_can('aec_manage_events')) ? false : $this->return_current_user_id();
  1465. }
  1466. function render_i18n_data($data) {
  1467. return htmlentities(stripslashes($data), ENT_COMPAT, 'UTF-8');
  1468. }
  1469. function render_json($output) {
  1470. header("Content-Type: application/json");
  1471. echo json_encode($this->cleanse_output($output));
  1472. exit;
  1473. }
  1474. function generate_css() {
  1475. $categories = $this->db_query_categories();
  1476. $out = "<style>";
  1477. foreach ($categories as $category) {
  1478. $out .= ".cat{$category->id}";
  1479. $out .= ",.cat{$category->id} .fc-event-skin";
  1480. $out .= ",.fc-agenda .cat{$category->id}";
  1481. $out .= ",a.cat{$category->id}";
  1482. $out .= ",a.cat{$category->id}:active";
  1483. $out .= ",a.cat{$category->id}:visited{";
  1484. $out .= "color:#{$category->fgcolor} !important;";
  1485. $out .= "background-color:#{$category->bgcolor} !important;";
  1486. $out .= "border-color:#{$category->bgcolor} !important}\n";
  1487. $out .= "a.cat{$category->id}:hover{-moz-box-shadow:0 0 2px #000;-webkit-box-shadow:0 0 2px #000;box-shadow:0 0 2px #000;";
  1488. $out .= "color:#{$category->fgcolor} !important;";
  1489. $out .= "background-color:#{$category->bgcolor} !important;";
  1490. $out .= "border-color:#{$category->fgcolor} !important}\n";
  1491. }
  1492. $out .= "</style>";
  1493. return $out;
  1494. }
  1495. // overwrite option, preserving other serialized options
  1496. function overwrite_option($key, $value) {
  1497. $options = get_option('aec_options');
  1498. $options[$key] = $value;
  1499. update_option('aec_options', $options);
  1500. }
  1501. // if not present, add options
  1502. function insert_option($key, $value) {
  1503. $options = get_option('aec_options');
  1504. if (!array_key_exists($key, $options)) {
  1505. $options[$key] = $value;
  1506. }
  1507. update_option('aec_options', $options);
  1508. }
  1509. function decommission_options($keys) {
  1510. $options = get_option('aec_options');
  1511. foreach ($keys as $key) {
  1512. if (array_key_exists($key, $options)) {
  1513. unset($options[$key]);
  1514. }
  1515. }
  1516. update_option('aec_options', $options);
  1517. }
  1518. function log($message) {
  1519. if (is_array($message) || is_object($message)) {
  1520. error_log(print_r($message, true));
  1521. } else {
  1522. error_log($message);
  1523. }
  1524. return;
  1525. }
  1526. function convert_date($date, $from, $to=false) {
  1527. // if date format is d/m/Y, modify token to 'd-m-Y' so strtotime parses date correctly
  1528. if (strpos($from, 'd') == 0) {
  1529. $date = str_replace("/", "-", $date);
  1530. }
  1531. if ($to) {
  1532. return date_i18n($to, strtotime($date));
  1533. }
  1534. return strtotime($date);
  1535. }
  1536. function parse_date_format($format) {
  1537. // d | j 1 | 01, day of the month
  1538. // m | n 3 | 03, month of the year
  1539. // if date format begins with d or j assign Euro format, otherwise US format
  1540. return (strpos($format, 'd') === 0 || strpos($format, 'j') === 0) ? true : false;
  1541. }
  1542. function parse_time_format($format) {
  1543. // H | G 24-hour, with | without leading zeros
  1544. // g | H 24-hour, with | without leading zeros
  1545. return (strpos($format, 'G') !== false || strpos($format, 'H') !== false) ? true : false;
  1546. }
  1547. // restricts jquery datepicker format (based on WP date format) to ensure accurate localization
  1548. function get_wp_date_format() {
  1549. return ($this->parse_date_format(AEC_WP_DATE_FORMAT)) ? 'd-m-Y' : 'm/d/Y';
  1550. }
  1551. // restricts jquery timepicker format (based on WP time format) to ensure accurate localization
  1552. function get_wp_time_format() {
  1553. return ($this->parse_time_format(AEC_WP_TIME_FORMAT)) ? 'H:i' : 'h:i A';
  1554. }
  1555. // split datetime fields
  1556. function split_datetime($datetime) {
  1557. $out = array();
  1558. array_push($out, $this->convert_date($datetime, AEC_DB_DATETIME_FORMAT, $this->get_wp_date_format()));
  1559. array_push($out, $this->convert_date($datetime, AEC_DB_DATETIME_FORMAT, $this->get_wp_time_format()));
  1560. return $out;
  1561. }
  1562. // merge date and time fields, and convert to database format
  1563. function merge_date_time($date, $time) {
  1564. $datetime = "{$date} {$time}";
  1565. $format = "{$this->get_wp_date_format()} {$this->get_wp_time_format()}";
  1566. return $this->convert_date($datetime, $format, AEC_DB_DATETIME_FORMAT);
  1567. }
  1568. function array_compare_order($a, $b) {
  1569. return strtotime($a['start']) - strtotime($b['start']);
  1570. }
  1571. // CUSTOMIZE WORDPRESS
  1572. // adds column field label to WordPress users page
  1573. function add_events_column($columns) {
  1574. $columns['calendar_events'] = __('Events', AEC_NAME);
  1575. return $columns;
  1576. }
  1577. // adds column field value to WordPress users page
  1578. function add_events_column_data($empty='', $column_name, $user_id) {
  1579. if ($column_name == 'calendar_events') {
  1580. return $this->db_query_events_by_user($user_id);
  1581. }
  1582. }
  1583. // displays the "settings" link beside the plugin on the WordPress plugins page
  1584. function settings_link($links, $file) {
  1585. if ($file == plugin_basename(__FILE__)) {
  1586. $settings = '<a href="' . get_admin_url() . 'admin.php?page=aec_calendar_options">' . __('Settings', AEC_NAME) . '</a>';
  1587. array_unshift($links, $settings); // make the 'Settings' link appear first
  1588. }
  1589. return $links;
  1590. }
  1591. // changes the permissions for using the calendar settings page
  1592. function set_option_page_capability($capability) {
  1593. return 'aec_manage_calendar';
  1594. }
  1595. function admin_options_initialize() {
  1596. register_setting('aec_plugin_options', 'aec_options', array($this, 'admin_options_validate'));
  1597. }
  1598. function admin_options_validate($input) {
  1599. // validation placeholder
  1600. return $input;
  1601. }
  1602. }
  1603. }
  1604. register_activation_hook(__FILE__, array('ajax_event_calendar', 'install'));
  1605. if (class_exists('ajax_event_calendar')) {
  1606. require_once AEC_PATH . 'inc/widget-contributors.php';
  1607. require_once AEC_PATH . 'inc/widget-upcoming.php';
  1608. $aec = new ajax_event_calendar();
  1609. }
  1610. ?>