コード例 #1
0
 /**
  * update function
  *
  * Called when a user submits the widget configuration form. The data should
  * be validated and returned.
  *
  * @param array $new_instance The new data that was submitted.
  * @param array $old_instance The widget's old data.
  * @return array The new data to save for this widget instance.
  */
 function update($new_instance, $old_instance)
 {
     // Save existing data as a base to modify with new data
     $instance = $old_instance;
     $instance['title'] = strip_tags($new_instance['title']);
     $instance['events_per_page'] = Ai1ec_Number_Utility::index($new_instance['events_per_page'], 1, 1);
     $instance['days_per_page'] = Ai1ec_Number_Utility::index($new_instance['days_per_page'], 1, 1);
     $instance['events_seek_type'] = $this->_valid_seek_type($new_instance['events_seek_type']);
     $instance['show_subscribe_buttons'] = $new_instance['show_subscribe_buttons'] ? true : false;
     $instance['show_calendar_button'] = $new_instance['show_calendar_button'] ? true : false;
     $instance['hide_on_calendar_page'] = $new_instance['hide_on_calendar_page'] ? true : false;
     // For limits, set the limit to False if no IDs were selected, or set the respective IDs to empty if "limit by" was unchecked
     $instance['limit_by_cat'] = false;
     $instance['event_cat_ids'] = array();
     if (isset($new_instance['event_cat_ids']) && $new_instance['event_cat_ids'] != false) {
         $instance['limit_by_cat'] = true;
     }
     if (isset($new_instance['limit_by_cat']) && $new_instance['limit_by_cat'] != false) {
         $instance['limit_by_cat'] = true;
     }
     if (isset($new_instance['event_cat_ids']) && $instance['limit_by_cat'] === true) {
         $instance['event_cat_ids'] = $new_instance['event_cat_ids'];
     }
     $instance['limit_by_tag'] = false;
     $instance['event_tag_ids'] = array();
     if (isset($new_instance['event_tag_ids']) && $new_instance['event_tag_ids'] != false) {
         $instance['limit_by_tag'] = true;
     }
     if (isset($new_instance['limit_by_tag']) && $new_instance['limit_by_tag'] != false) {
         $instance['limit_by_tag'] = true;
     }
     if (isset($new_instance['event_tag_ids']) && $instance['limit_by_tag'] === true) {
         $instance['event_tag_ids'] = $new_instance['event_tag_ids'];
     }
     $instance['limit_by_post'] = false;
     $instance['event_post_ids'] = array();
     if (isset($new_instance['event_post_ids']) && $new_instance['event_post_ids'] != false) {
         $instance['limit_by_post'] = true;
     }
     if (isset($new_instance['limit_by_post']) && $new_instance['limit_by_post'] != false) {
         $instance['limit_by_post'] = true;
     }
     if (isset($new_instance['event_post_ids']) && $instance['limit_by_post'] === true) {
         $instance['event_post_ids'] = $new_instance['event_post_ids'];
     }
     return $instance;
 }
コード例 #2
0
 /**
  * add_ics_feed function
  *
  * Adds submitted ics feed to the database
  *
  * @return string JSON output
  **/
 public function add_ics_feed()
 {
     global $ai1ec_view_helper, $wpdb;
     $table_name = $wpdb->prefix . 'ai1ec_event_feeds';
     $entry = array('feed_url' => $_REQUEST['feed_url'], 'feed_category' => $_REQUEST['feed_category'], 'feed_tags' => $_REQUEST['feed_tags'], 'comments_enabled' => Ai1ec_Number_Utility::db_bool($_REQUEST['comments_enabled']), 'map_display_enabled' => Ai1ec_Number_Utility::db_bool($_REQUEST['map_display_enabled']));
     $format = array('%s', '%d', '%s', '%d', '%d');
     $wpdb->insert($table_name, $entry, $format);
     $feed_id = $wpdb->insert_id;
     ob_start();
     $feed_category = get_term($_REQUEST['feed_category'], 'events_categories');
     $args = array('feed_url' => $_REQUEST['feed_url'], 'event_category' => $feed_category->name, 'tags' => $_REQUEST['feed_tags'], 'feed_id' => $feed_id, 'comments_enabled' => (bool) intval($_REQUEST['comments_enabled']), 'map_display_enabled' => (bool) intval($_REQUEST['map_display_enabled']), 'events' => 0);
     // display added feed row
     $ai1ec_view_helper->display_admin('feed_row.php', $args);
     $output = ob_get_contents();
     ob_end_clean();
     $output = array("error" => 0, "message" => stripslashes($output));
     echo json_encode($output);
     exit;
 }
コード例 #3
0
 /**
  * add_vcalendar_events_to_db method
  *
  * Process vcalendar instance - add events to database
  *
  * @param vcalendar $v              Calendar to retrieve data from
  * @param stdClass  $feed           Instance of feed (see Ai1ecIcs plugin)
  * @param string    $comment_status WP comment status: 'open' or 'closed'
  * @param int       $do_show_map    Map display status (DB boolean: 0 or 1)
  *
  * @return int Count of events added to database
  */
 public function add_vcalendar_events_to_db(vcalendar $v, $feed, $comment_status, $do_show_map = 0)
 {
     global $ai1ec_events_helper;
     $count = 0;
     $do_show_map = Ai1ec_Number_Utility::db_bool($do_show_map);
     $v->sort();
     // Reverse the sort order, so that RECURRENCE-IDs are listed before the
     // defining recurrence events, and therefore take precedence during
     // caching.
     $v->components = array_reverse($v->components);
     // TODO: select only VEVENT components that occur after, say, 1 month ago.
     // Maybe use $v->selectComponents(), which takes into account recurrence
     // Fetch default timezone in case individual properties don't define it
     $timezone = $v->getProperty('X-WR-TIMEZONE');
     $timezone = (string) $timezone[1];
     // go over each event
     while ($e = $v->getComponent('vevent')) {
         // Event data array.
         $data = array();
         // =====================
         // = Start & end times =
         // =====================
         $start = $e->getProperty('dtstart', 1, true);
         $end = $e->getProperty('dtend', 1, true);
         // For cases where a "VEVENT" calendar component
         // specifies a "DTSTART" property with a DATE value type but none
         // of "DTEND" nor "DURATION" property, the event duration is taken to
         // be one day.  For cases where a "VEVENT" calendar component
         // specifies a "DTSTART" property with a DATE-TIME value type but no
         // "DTEND" property, the event ends on the same calendar date and
         // time of day specified by the "DTSTART" property.
         if (empty($end)) {
             // #1 if duration is present, assign it to end time
             $end = $e->getProperty('duration', 1, true, true);
             if (empty($end)) {
                 // #2 if only DATE value is set for start, set duration to 1 day
                 if (!isset($start['value']['hour'])) {
                     $end = array('value' => array('year' => $start['value']['year'], 'month' => $start['value']['month'], 'day' => $start['value']['day'] + 1, 'hour' => 0, 'min' => 0, 'sec' => 0, 'tz' => $start['value']['tz']));
                 } else {
                     // #3 set end date to start time
                     $end = $start;
                 }
             }
         }
         $categories = $e->getProperty("CATEGORIES", false, true);
         $imported_cat = array();
         // If the user chose to preserve taxonomies during import, add categories.
         if ($categories && $feed->keep_tags_categories) {
             $imported_cat = $this->add_categories_and_tags($categories['value'], $imported_cat, false, true);
         }
         $feed_categories = $feed->feed_category;
         if (!empty($feed_categories)) {
             $imported_cat = $this->add_categories_and_tags($feed_categories, $imported_cat, false, false);
         }
         $tags = $e->getProperty("X-TAGS", false, true);
         $imported_tags = array();
         // If the user chose to preserve taxonomies during import, add tags.
         if ($tags && $feed->keep_tags_categories) {
             $imported_tags = $this->add_categories_and_tags($tags[1]['value'], $imported_tags, true, true);
         }
         $feed_tags = $feed->feed_tags;
         if (!empty($feed_tags)) {
             $imported_tags = $this->add_categories_and_tags($feed_tags, $imported_tags, true, true);
         }
         // Event is all-day if no time components are defined
         $allday = $this->_is_timeless($start['value']) && $this->_is_timeless($end['value']);
         // Also check the proprietary MS all-day field.
         $ms_allday = $e->getProperty('X-MICROSOFT-CDO-ALLDAYEVENT');
         if (!empty($ms_allday) && $ms_allday[1] == 'TRUE') {
             $allday = true;
         }
         $start = $this->time_array_to_timestamp($start, $timezone);
         $end = $this->time_array_to_timestamp($end, $timezone);
         if (false === $start || false === $end) {
             trigger_error('Failed to parse one or more dates given timezone "' . var_export($timezone, true) . '".', E_USER_WARNING);
             continue;
         }
         // If all-day, and start and end times are equal, then this event has
         // invalid end time (happens sometimes with poorly implemented iCalendar
         // exports, such as in The Event Calendar), so set end time to 1 day
         // after start time.
         if ($allday && $start === $end) {
             $end += 24 * 60 * 60;
         }
         $data += compact('start', 'end', 'allday');
         // =======================================
         // = Recurrence rules & recurrence dates =
         // =======================================
         if ($rrule = $e->createRrule()) {
             $rrule = trim(end(explode(':', $rrule)));
         }
         if ($exrule = $e->createExrule()) {
             $exrule = trim(end(explode(':', $exrule)));
         }
         if ($rdate = $e->createRdate()) {
             $rdate = trim(end(explode(':', $rdate)));
         }
         // ===================
         // = Exception dates =
         // ===================
         $exdate_array = array();
         if ($exdates = $e->createExdate()) {
             // We may have two formats:
             // one exdate with many dates ot more EXDATE rules
             $exdates = explode("EXDATE", $exdates);
             foreach ($exdates as $exd) {
                 if (empty($exd)) {
                     continue;
                 }
                 $exdate_array[] = trim(end(explode(':', $exd)));
             }
         }
         // This is the local string.
         $exdate_loc = implode(',', $exdate_array);
         $gmt_exdates = array();
         // Now we convert the string to gmt. I must do it here
         // because EXDATE:date1,date2,date3 must be parsed
         if (!empty($exdate_loc)) {
             foreach (explode(',', $exdate_loc) as $date) {
                 // If the date is > 8 char that's a datetime, we just want the
                 // date part for the exclusion rules
                 if (strlen($date) > 8) {
                     $date = substr($date, 0, 8);
                 }
                 $gmt_exdates[] = $ai1ec_events_helper->exception_dates_to_gmt($date);
             }
         }
         $exdate = implode(',', $gmt_exdates);
         // ========================
         // = Latitude & longitude =
         // ========================
         $latitude = $longitude = NULL;
         $geo_tag = $e->getProperty('geo');
         if (is_array($geo_tag)) {
             if (isset($geo_tag['latitude']) && isset($geo_tag['longitude'])) {
                 $latitude = (double) $geo_tag['latitude'];
                 $longitude = (double) $geo_tag['longitude'];
             }
         } else {
             if (!empty($geo_tag) && false !== strpos($geo_tag, ';')) {
                 list($latitude, $longitude) = explode(';', $geo_tag, 2);
                 $latitude = (double) $latitude;
                 $longitude = (double) $longitude;
             }
         }
         unset($geo_tag);
         if (NULL !== $latitude) {
             $data += compact('latitude', 'longitude');
             // Check the input coordinates checkbox, otherwise lat/long data
             // is not present on the edit event page
             $data['show_coordinates'] = 1;
         }
         // ===================
         // = Venue & address =
         // ===================
         $address = $venue = '';
         $location = $e->getProperty('location');
         $matches = array();
         // This regexp matches a venue / address in the format
         // "venue @ address" or "venue - address".
         preg_match('/\\s*(.*\\S)\\s+[\\-@]\\s+(.*)\\s*/', $location, $matches);
         // if there is no match, it's not a combined venue + address
         if (empty($matches)) {
             // if there is a comma, probably it's an address
             if (false === strpos($location, ',')) {
                 $venue = $location;
             } else {
                 $address = $location;
             }
         } else {
             $venue = isset($matches[1]) ? $matches[1] : '';
             $address = isset($matches[2]) ? $matches[2] : '';
         }
         // =====================================================
         // = Set show map status based on presence of location =
         // =====================================================
         if (1 === $do_show_map && NULL === $latitude && empty($address)) {
             $do_show_map = 0;
         }
         // ==================
         // = Cost & tickets =
         // ==================
         $cost = $e->getProperty('X-COST');
         $cost = $cost ? $cost[1] : '';
         $ticket_url = $e->getProperty('X-TICKETS-URL');
         $ticket_url = $ticket_url ? $ticket_url[1] : '';
         // ===============================
         // = Contact name, phone, e-mail =
         // ===============================
         $organizer = $e->getProperty('organizer');
         if ('MAILTO:' === substr($organizer, 0, 7) && false === strpos($organizer, '@')) {
             $organizer = substr($organizer, 7);
         }
         $contact = $e->getProperty('contact');
         $elements = explode(';', $contact, 4);
         foreach ($elements as $el) {
             $el = trim($el);
             // Detect e-mail address.
             if (false !== strpos($el, '@')) {
                 $data['contact_email'] = $el;
             } elseif (false !== strpos($el, '://')) {
                 $data['contact_url'] = $el;
             } elseif (preg_match('/\\d/', $el)) {
                 $data['contact_phone'] = $el;
             } else {
                 $data['contact_name'] = $el;
             }
         }
         if (!isset($data['contact_name']) || !$data['contact_name']) {
             // If no contact name, default to organizer property.
             $data['contact_name'] = $organizer;
         }
         // Store yet-unsaved values to the $data array.
         $data += array('recurrence_rules' => $rrule, 'exception_rules' => $exrule, 'recurrence_dates' => $rdate, 'exception_dates' => $exdate, 'venue' => $venue, 'address' => $address, 'cost' => $cost, 'ticket_url' => $ticket_url, 'show_map' => $do_show_map, 'ical_feed_url' => $feed->feed_url, 'ical_source_url' => $e->getProperty('url'), 'ical_organizer' => $organizer, 'ical_contact' => $contact, 'ical_uid' => $e->getProperty('uid'), 'categories' => array_keys($imported_cat), 'tags' => array_keys($imported_tags), 'feed' => $feed, 'post' => array('post_status' => 'publish', 'comment_status' => $comment_status, 'post_type' => AI1EC_POST_TYPE, 'post_author' => 1, 'post_title' => $e->getProperty('summary'), 'post_content' => stripslashes(str_replace('\\n', "\n", $e->getProperty('description')))));
         // Create event object.
         $event = new Ai1ec_Event($data);
         // TODO: when singular events change their times in an ICS feed from one
         // import to another, the matching_event_id is null, which is wrong. We
         // want to match that event that previously had a different time.
         // However, we also want the function to NOT return a matching event in
         // the case of recurring events, and different events with different
         // RECURRENCE-IDs... ponder how to solve this.. may require saving the
         // RECURRENCE-ID as another field in the database.
         $matching_event_id = $ai1ec_events_helper->get_matching_event_id($event->ical_uid, $event->ical_feed_url, $event->start, !empty($event->recurrence_rules));
         if (NULL === $matching_event_id) {
             // =================================================
             // = Event was not found, so store it and the post =
             // =================================================
             $event->save();
         } else {
             // ======================================================
             // = Event was found, let's store the new event details =
             // ======================================================
             // Update the post
             $post = get_post($matching_event_id);
             $post->post_title = $event->post->post_title;
             $post->post_content = $event->post->post_content;
             wp_update_post($post);
             // Update the event
             $event->post_id = $matching_event_id;
             $event->post = $post;
             $event->save(true);
             // Delete event's cache
             $ai1ec_events_helper->delete_event_cache($matching_event_id);
         }
         // Regenerate event's cache
         $ai1ec_events_helper->cache_event($event);
         $count++;
     }
     return $count;
 }
コード例 #4
0
 /**
  * filter_by_terms function
  *
  * Returns a subset of post IDs from the given set of post IDs that have any
  * of the given taxonomy term IDs. This is actually useful for all posts and
  * taxonomies in general, not just event posts and event-specific taxonomies.
  *
  * @param array|string $post_ids  Post IDs as an array of ints or
  *                                comma-separated string
  * @param array|string $term_ids  Term IDs as an array of ints or
  *                                comma-separated string
  *
  * @return array                  Filtered post IDs as an array of ints
  */
 public function filter_by_terms($post_ids, $term_ids)
 {
     global $wpdb;
     // ===============================================
     // = Sanitize provided IDs against SQL injection =
     // ===============================================
     $post_ids = implode(',', Ai1ec_Number_Utility::convert_to_int_list(',', $post_ids));
     $term_ids = implode(',', Ai1ec_Number_Utility::convert_to_int_list(',', $term_ids));
     $query = 'SELECT DISTINCT p.ID ' . 'FROM ' . $wpdb->posts . ' p ' . 'INNER JOIN ' . $wpdb->term_relationships . ' tr ON p.ID = tr.object_id ' . 'INNER JOIN ' . $wpdb->term_taxonomy . ' tt ON tr.term_taxonomy_id = tt.term_taxonomy_id ' . 'WHERE p.ID IN ( ' . $post_ids . ' ) ' . 'AND tt.term_id IN ( ' . $term_ids . ' )';
     return $wpdb->get_col($query);
 }
コード例 #5
0
 /**
  * export_events function
  *
  * Export events
  *
  * @return void
  **/
 function export_events()
 {
     global $ai1ec_events_helper, $ai1ec_exporter_helper, $ai1ec_localization_helper;
     $ai1ec_cat_ids = !empty($_REQUEST['ai1ec_cat_ids']) ? $_REQUEST['ai1ec_cat_ids'] : false;
     $ai1ec_tag_ids = !empty($_REQUEST['ai1ec_tag_ids']) ? $_REQUEST['ai1ec_tag_ids'] : false;
     $ai1ec_post_ids = !empty($_REQUEST['ai1ec_post_ids']) ? $_REQUEST['ai1ec_post_ids'] : false;
     if (!empty($_REQUEST['lang'])) {
         $ai1ec_localization_helper->set_language($_REQUEST['lang']);
     }
     $filter = array();
     if ($ai1ec_cat_ids) {
         $filter['cat_ids'] = Ai1ec_Number_Utility::convert_to_int_list(',', $ai1ec_cat_ids);
     }
     if ($ai1ec_tag_ids) {
         $filter['tag_ids'] = Ai1ec_Number_Utility::convert_to_int_list(',', $ai1ec_tag_ids);
     }
     if ($ai1ec_post_ids) {
         $filter['post_ids'] = Ai1ec_Number_Utility::convert_to_int_list(',', $ai1ec_post_ids);
     }
     // when exporting events by post_id, do not look up the event's start/end date/time
     $start = $ai1ec_post_ids !== false ? false : Ai1ec_Time_Utility::current_time(true) - 24 * 60 * 60;
     // Include any events ending today
     $end = false;
     $c = new vcalendar();
     $c->setProperty('calscale', 'GREGORIAN');
     $c->setProperty('method', 'PUBLISH');
     // if no post id are specified do not export those properties
     // as they would create a new calendar in outlook.
     // a user reported this in AIOEC-982 and said this would fix it
     if (false === $ai1ec_post_ids) {
         $c->setProperty('X-WR-CALNAME', get_bloginfo('name'));
         $c->setProperty('X-WR-CALDESC', get_bloginfo('description'));
     }
     $c->setProperty('X-FROM-URL', home_url());
     // Timezone setup
     $tz = Ai1ec_Meta::get_option('timezone_string');
     if ($tz) {
         $c->setProperty('X-WR-TIMEZONE', $tz);
         $tz_xprops = array('X-LIC-LOCATION' => $tz);
         iCalUtilityFunctions::createTimezone($c, $tz, $tz_xprops);
     }
     $events = $ai1ec_events_helper->get_matching_events($start, $end, $filter);
     foreach ($events as $event) {
         $ai1ec_exporter_helper->insert_event_in_calendar($event, $c, $export = true);
     }
     $str = ltrim($c->createCalendar());
     header('Content-type: text/calendar; charset=utf-8');
     echo $str;
     exit;
 }