plugin = $plugin; $this->menuPage = $menuPage; } /** * render the admin page */ public function render() { ?>

Import Events

importEvents($format); } $url = admin_url('edit.php') . "?post_type=event&page={$this->menuPage}"; ?>

Import a file of events exported from Events Manager Import/Export plugin on another website.

File format:
File:
 
\n"; break; case UPLOAD_ERR_INI_SIZE: case UPLOAD_ERR_FORM_SIZE: $errmsg .= "# error uploading file - file too big.
\n"; break; default: $errmsg .= "# error uploading file.
\n"; break; } } else { $errmsg .= "# no upload file selected.
\n"; } if (empty($errmsg)) { try { set_time_limit(600); switch ($format) { case 'xCal': $this->importEventsXCal($filepath); break; case 'csv': $this->importEventsCSV($filepath); break; } } catch (Exception $e) { $errmsg .= "# error importing events: " . htmlspecialchars($e->getMessage()) . "
\n"; } } if (!empty($errmsg)) { $this->plugin->showError($errmsg); } } /** * import events from xCal upload * @param string $filepath */ protected function importEventsXCal($filepath) { global $wpdb; $xml = new XMLReader(); if (!$xml->open($filepath, 'UTF-8')) { throw new EM_ImpExpImportException("error opening xCal file."); } $text = ''; $haveRecord = FALSE; $haveLocation = FALSE; $records = 0; $attrs = array(); $eventCategories = self::getEventCategories(); while ($xml->read()) { switch ($xml->nodeType) { case XMLReader::ELEMENT: if ($xml->name === 'vevent') { $data = array( 'uid' => '', 'url' => '', 'summary' => '', 'dtstart' => '', 'dtend' => '', 'categories' => '', 'freq' => '', 'byday' => '', 'interval' => '', 'until' => '', 'x-post_content' => '', 'x-event_spaces' => '', 'x-location_name' => '', 'x-location_address' => '', 'x-location_town' => '', 'x-location_state' => '', 'x-location_postcode' => '', 'x-location_country' => '', 'x-location_region' => '', 'x-location_latitude' => '', 'x-location_longitude' => '', ); $attrs = array(); $haveRecord = TRUE; $haveLocation = FALSE; } $text = ''; break; case XMLReader::END_ELEMENT: if ($xml->name === 'vevent') { // end of vevent element, save record if ($haveRecord) { //~ error_log(__METHOD__ . "\n" . print_r($data,1)); //~ error_log(__METHOD__ . "\n" . print_r($attrs,1)); //~ exit; // if we have location, try to either retrieve it by name, or create a new location object $location = FALSE; if ($haveLocation) { if ($data['x-location_name']) { add_filter('em_locations_get_default_search', array(__CLASS__, 'filterLocationArgs'), 10, 2); add_filter('em_locations_build_sql_conditions', array(__CLASS__, 'filterLocationSQL'), 10, 2); $location = EM_Locations::get(array('location_name' => $data['x-location_name'])); $location = count($location) > 0 ? $location[0] : FALSE; remove_filter('em_locations_get_default_search', array(__CLASS__, 'filterLocationArgs'), 10, 2); remove_filter('em_locations_build_sql_conditions', array(__CLASS__, 'filterLocationSQL'), 10, 2); } if (!$location) { // must create a new location object $location = new EM_Location(); $location->location_name = $data['x-location_name']; $location->location_address = $data['x-location_address']; $location->location_town = $data['x-location_town']; $location->location_state = $data['x-location_state']; $location->location_postcode = $data['x-location_postcode']; $location->location_country = $data['x-location_country']; $location->location_region = $data['x-location_region']; $location->location_latitude = $data['x-location_latitude']; $location->location_longitude = $data['x-location_longitude']; $location->save(); } //~ error_log(__METHOD__ . "\n" . print_r($location,1)); //~ exit; } // try to find existing event with matching unique ID first, so can update it $event = FALSE; if ($data['uid']) { add_filter('em_events_get_default_search', array(__CLASS__, 'filterEventArgs'), 10, 2); add_filter('em_events_build_sql_conditions', array(__CLASS__, 'filterEventSQL'), 10, 2); $event = EM_Events::get(array('em_impexp_uid' => $data['uid'])); $event = count($event) > 0 ? $event[0] : FALSE; remove_filter('em_events_get_default_search', array(__CLASS__, 'filterEventArgs'), 10, 2); remove_filter('em_events_build_sql_conditions', array(__CLASS__, 'filterEventSQL'), 10, 2); } if (!$event) { // must create a new event $event = new EM_Event(); } $event->location_id = $location ? $location->location_id : 0; $event->event_attributes['em_impexp_uid'] = $data['uid']; $event->event_attributes['em_impexp_url'] = $data['url']; $event->event_name = $data['summary']; $event->post_content = $data['x-post_content']; if ($data['dtstart']) { $event->start = strtotime($data['dtstart']); $event->event_start_date = date('Y-m-d', $event->start); $event->event_start_time = date('H:i:s', $event->start); } if ($data['dtend']) { $event->end = strtotime($data['dtend']); $event->event_end_date = date('Y-m-d', $event->end); $event->event_end_time = date('H:i:s', $event->end); } $event->event_date_modified = current_time('mysql'); $event->event_all_day = ($event->event_start_time == '00:00:00' && $event->event_end_time == '00:00:00') ? 1 : 0; foreach ($attrs as $attrName => $value) { $event->event_attributes[$attrName] = $value; } // TODO: recurring events switch ($data['freq']) { case 'DAILY': break; case 'WEEKLY': //~ $event->freq = $data['freq']; //~ $event->byday = $data['byday']; //~ $event->interval = $data['interval']; //~ $event->until = $data['until']; break; case 'MONTHLY': break; } //~ error_log(__METHOD__ . "\n" . print_r($event,1)); if ($event) { $event->save(); $event->save_meta(); if ($data['categories']) { $categories = explode(',', $data['categories']); foreach ($categories as $category) { $category = trim($category); if (isset($eventCategories[$category])) { $cat = $eventCategories[$category]; } else { $cat = wp_insert_term($category, 'event-categories'); if (is_array($cat)) { $cat = new EM_Category($cat['term_id']); $eventCategories[$category] = $cat; } } if ($cat) { $event->categories->categories[$cat->id] = $cat; } } $event->categories->save(); } } $records++; } $haveRecord = FALSE; $haveLocation = FALSE; } elseif ($haveRecord) { // still inside a vevent element, record field value and move on $name = $xml->name; switch ($name) { case 'x-event_attribute': // add to attributes array $attrs[$xml->getAttribute('name')] = $text; break; default: if (array_key_exists($name, $data) && $text !== '') { // add to fields array $data[$name] = $text; // flag location fields that have data if (strpos($name, 'x-location') !== FALSE) { $haveLocation = TRUE; } } break; } } $text = ''; break; case XMLReader::TEXT: case XMLReader::CDATA: // record value (or part value) of text or cdata node $text .= (string) $xml->value; break; default: break; } } $this->plugin->showMessage($records === 1 ? '1 events loaded' : "$records events loaded"); } /** * import events from CSV upload * @param string $filepath */ protected function importEventsCSV($filepath) { global $wpdb; $fp = fopen($filepath, 'r'); if ($fp === FALSE) { throw new EM_ImpExpImportException('error opening CSV file'); } // read first line of CSV to make sure it's the correct format -- fgetscsv is fine for this simple task! $header = fgetcsv($fp); if ($header === FALSE) throw new EM_ImpExpImportException('error reading import file or file is empty'); if (is_null($header)) throw new EM_ImpExpImportException('import file handle is null'); if (!is_array($header)) throw new EM_ImpExpImportException('import file did not scan as CSV'); if (!in_array('summary', $header)) throw new EM_ImpExpImportException('import file does not contain a field "summary"'); $wpdb->query('start transaction'); $records = 0; $attrs = array(); $eventCategories = self::getEventCategories(); $eventCountries = self::getEventCountries(); $csv = new parseCSV(); $csv->fields = $header; while ($line = fgets($fp)) { $line = "\n$line\n"; // fix up line so that it can be parsed correctly $cols = $csv->parse_string($line); if ($cols) { $rows++; $cols = $cols[0]; // collect standard event properties $data = array( 'uid' => isset($cols['uid']) ? trim($cols['uid']) : '', 'url' => isset($cols['url']) ? self::safeURL($cols['url']) : '', 'summary' => isset($cols['summary']) ? $cols['summary'] : '', 'dtstart' => isset($cols['dtstart']) ? $cols['dtstart'] : '', 'dtend' => isset($cols['dtend']) ? $cols['dtend'] : '', 'categories' => isset($cols['categories']) ? $cols['categories'] : '', 'freq' => isset($cols['freq']) ? $cols['freq'] : '', 'byday' => isset($cols['byday']) ? $cols['byday'] : '', 'interval' => isset($cols['interval']) ? $cols['interval'] : '', 'until' => isset($cols['until']) ? $cols['until'] : '', 'post_content' => isset($cols['post_content']) ? $cols['post_content'] : '', 'event_spaces' => isset($cols['event_spaces']) ? $cols['event_spaces'] : '', 'location_name' => isset($cols['location_name']) ? $cols['location_name'] : '', 'location_address' => isset($cols['location_address']) ? $cols['location_address'] : '', 'location_town' => isset($cols['location_town']) ? $cols['location_town'] : '', 'location_state' => isset($cols['location_state']) ? $cols['location_state'] : '', 'location_postcode' => isset($cols['location_postcode']) ? $cols['location_postcode'] : '', 'location_country' => isset($cols['location_country']) ? $cols['location_country'] : '', 'location_region' => isset($cols['location_region']) ? $cols['location_region'] : '', 'location_latitude' => isset($cols['location_latitude']) ? $cols['location_latitude'] : '', 'location_longitude' => isset($cols['location_longitude']) ? $cols['location_longitude'] : '', ); if (isset($eventCountries[strtolower($data['location_country'])])) { $data['location_country'] = $eventCountries[strtolower($data['location_country'])]; } // collect custom event attributes, being columns not found in standard event properties $attrs = array(); foreach ($cols as $key => $value) { if (strlen($value) > 0 && !isset($data[$key])) { $attrs[$key] = $value; } } //~ error_log(__METHOD__ . "\n" . print_r($data,1)); //~ error_log(__METHOD__ . "\n" . print_r($attrs,1)); //~ exit; // if we have location, try to either retrieve it by name, or create a new location object $location = FALSE; if (self::hasLocation($data)) { if ($data['location_name']) { // try to find location by name $location = $this->getLocationByName($data['location_name']); } if (!$location) { // must create a new location object $location = new EM_Location(); $location->location_name = empty($data['location_name']) ? self::fudgeLocationName($data) : $data['location_name']; $location->location_address = empty($data['location_address']) ? $data['location_name'] : $data['location_address']; $location->location_town = $data['location_town']; $location->location_state = $data['location_state']; $location->location_postcode = $data['location_postcode']; $location->location_country = $data['location_country']; $location->location_region = $data['location_region']; $location->location_latitude = $data['location_latitude']; $location->location_longitude = $data['location_longitude']; $location->save(); } //~ echo "
", print_r($location,1), "
\n"; //~ exit; } // try to find existing event with matching unique ID first, so can update it $event = FALSE; if ($data['uid']) { add_filter('em_events_get_default_search', array(__CLASS__, 'filterEventArgs'), 10, 2); add_filter('em_events_build_sql_conditions', array(__CLASS__, 'filterEventSQL'), 10, 2); $event = EM_Events::get(array('em_impexp_uid' => $data['uid'])); $event = count($event) > 0 ? $event[0] : FALSE; remove_filter('em_events_get_default_search', array(__CLASS__, 'filterEventArgs'), 10, 2); remove_filter('em_events_build_sql_conditions', array(__CLASS__, 'filterEventSQL'), 10, 2); } if (!$event) { // must create a new event $event = new EM_Event(); } $event->location_id = $location ? $location->location_id : 0; $event->event_attributes['em_impexp_uid'] = $data['uid']; $event->event_attributes['em_impexp_url'] = $data['url']; $event->event_name = $data['summary']; $event->post_content = $data['post_content']; if (preg_match('@^\\d\\d/\\d\\d/\\d\\d\\d\\d \\d\\d:\\d\\d:\\d\\d$@', $data['dtstart'])) { // if (preg_match('@^\\d\\d/\\d\\d/\\d\\d\\d\\d$@', $data['dtstart'])) { //$data['dtstart'] .= ' 00:00:00'; $event->start = date_create_from_format('d/m/Y H:i:s', $data['dtstart'])->getTimestamp(); $event->event_start_date = date('Y-m-d', $event->start); $event->event_start_time = date('H:i:s', $event->start); } if (preg_match('@^\\d\\d/\\d\\d/\\d\\d\\d\\d \\d\\d:\\d\\d:\\d\\d$@', $data['dtend'])) { //$data['dtend'] .= ' 00:00:00'; $event->end = date_create_from_format('d/m/Y H:i:s', $data['dtend'])->getTimestamp(); $event->event_end_date = date('Y-m-d', $event->end); $event->event_end_time = date('H:i:s', $event->end); } else { $event->end = $event->start; $event->event_end_date = $event->event_start_date; $event->event_end_time = $event->event_start_time; } $event->event_date_modified = current_time('mysql'); $event->event_all_day = ($event->event_start_time == '00:00:00' && $event->event_end_time == '00:00:00') ? 1 : 0; foreach ($attrs as $attrName => $value) { $event->event_attributes[$attrName] = $value; } // TODO: recurring events switch ($data['freq']) { case 'DAILY': break; case 'WEEKLY': //~ $event->freq = $data['freq']; //~ $event->byday = $data['byday']; //~ $event->interval = $data['interval']; //~ $event->until = $data['until']; break; case 'MONTHLY': break; } //~ echo "
", print_r($event,1), "
\n"; if ($event) { $event->save(); $event->save_meta(); if ($data['categories']) { $categories = explode(',', $data['categories']); foreach ($categories as $category) { $category = trim($category); if (isset($eventCategories[$category])) { $cat = $eventCategories[$category]; } else { $cat = wp_insert_term($category, 'event-categories'); if (is_array($cat)) { $cat = new EM_Category($cat['term_id']); $eventCategories[$category] = $cat; } } if ($cat) { $event->categories->categories[$cat->id] = $cat; } } $event->categories->save(); } } $records++; } } $wpdb->query('commit'); $this->plugin->showMessage($records === 1 ? '1 events loaded' : "$records events loaded"); } /** * Is this web request a form post? * Checks to see whether the HTML input form was posted. * @return boolean */ protected static function isFormPost() { return ($_SERVER['REQUEST_METHOD'] == 'POST'); } /** * Read a field from form post input. * * Guaranteed to return a string, trimmed of leading and trailing spaces, and with sloshes stripped out. * * @param string $fieldname name of the field in the form post * @return string */ protected static function getPostValue($fieldname) { return isset($_POST[$fieldname]) ? stripslashes(trim($_POST[$fieldname])) : ''; } /** * ensure that URL has a protocol, give it http: if it doesn't * @param string $url * @return string */ protected static function safeURL($url) { if (!preg_match('@https?://@i', $url)) { $url = 'http://' . $url; } return $url; } /** * check CSV data to see if location is given * @param array $data columns from a CSV row * @return bool */ protected static function hasLocation($data) { // get location fields that have a value $location = array_filter(array ( $data['location_name'], $data['location_address'], $data['location_town'], $data['location_state'], $data['location_postcode'], $data['location_country'], $data['location_region'], $data['location_latitude'], $data['location_longitude'], ), 'strlen'); // if any were found, return true return count($location) > 0; } /** * find first non-empty location element for location name * @param array $data columns from a CSV row * @return string */ protected static function fudgeLocationName($data) { // get location fields that have a value $location = array_filter(array ( $data['location_name'], $data['location_address'], $data['location_town'], $data['location_state'], $data['location_postcode'], $data['location_country'], $data['location_region'], $data['location_latitude'], $data['location_longitude'], ), 'strlen'); // return the first element return array_shift($location[0]); } /** * get a location by name * @param string $location_name * @return EM_Location */ protected static function getLocationByName($location_name) { // add query filters to splice in our search term add_filter('em_locations_get_default_search', array(__CLASS__, 'filterLocationArgs'), 10, 2); add_filter('em_locations_build_sql_conditions', array(__CLASS__, 'filterLocationSQL'), 10, 2); $location = EM_Locations::get(array('location_name' => $location_name)); $location = count($location) > 0 ? $location[0] : FALSE; // remove our query filters remove_filter('em_locations_get_default_search', array(__CLASS__, 'filterLocationArgs'), 10, 2); remove_filter('em_locations_build_sql_conditions', array(__CLASS__, 'filterLocationSQL'), 10, 2); return $location; } /** * filter the search arguments for an events search, to restore the em_impexp_uid argument * @param array $filtered assoc. array of filtered arguments used for search * @param array $args assoc. array of original search arguments * @return array */ public static function filterEventArgs($filtered, $args) { if (isset($args['em_impexp_uid'])) { $filtered['em_impexp_uid'] = $args['em_impexp_uid']; } return $filtered; } /** * filter the SQL where clause conditions for an events search, to include em_impexp_uid * @param array $conditions where clause conditions * @param array $args assoc. array of search arguments * @return array */ public static function filterEventSQL($conditions, $args) { if (isset($args['em_impexp_uid'])) { $em_events_table = EM_EVENTS_TABLE; $uid = mysql_real_escape_string($args['em_impexp_uid']); $conditions[] = "($em_events_table.event_attributes regexp '\"em_impexp_uid\";s:\[0-9\]+:\"$uid\"')"; } return $conditions; } /** * filter the search arguments for a location search, to restore the location_name argument * @param array $filtered assoc. array of filtered arguments used for search * @param array $args assoc. array of original search arguments * @return array */ public static function filterLocationArgs($filtered, $args) { if (isset($args['location_name'])) { $filtered['location_name'] = $args['location_name']; } return $filtered; } /** * filter the SQL where clause conditions for a location search, to include location_name * @param array $conditions where clause conditions * @param array $args assoc. array of search arguments * @return array */ public static function filterLocationSQL($conditions, $args) { if (isset($args['location_name'])) { $conditions[] = "location_name='" . mysql_real_escape_string($args['location_name']) . "'"; } return $conditions; } /** * get a list of event categories, keyed by category name => category * @return array */ public static function getEventCategories() { $cats = EM_Categories::get(); $eventCats = array(); foreach ($cats as $cat) { $eventCats[$cat->name] = $cat; } return $eventCats; } /** * get a list of countries, keyed by lowercase name => code * @return array */ public static function getEventCountries() { $countries = em_get_countries(); $map = array(); foreach ($countries as $code => $name) { $map[strtolower($name)] = $code; } return $map; } }