function pect_get_google_timezone($lat, $lng) { $url = "https://maps.googleapis.com/maps/api/timezone/json?location=" . $lat . "," . $lng . "×tamp=" . time() . "&key=" . GOOGLE_API_TIMEZONE_KEY; $html = pect_cache_get_file('timezone', $url, PECT_CACHE_MAP_TIME, true, false); $json = json_decode($html, true); if (isset($json['status'])) { // We're allowed 2,500 requests per day. As this is now public on Virbank, this means // the number of requests shot up exponentially. This prevents over limit errors from // from being cached - the resulting calendar will still be cached so the address will // get tried again automatically within 24 hours assuming someone subcribed to that // calendar (and if they didn't we don't really care if it isn't up to date!) if ($json['status'] == 'OVER_QUERY_LIMIT') { $timezone = ''; pect_cache_del_file('timezone', $url); } elseif (isset($json['timeZoneId'])) { $timezone = $json['timeZoneId']; } else { $timezone = ''; } } return $timezone; }
if ($distanceFromCity == 1000) { $distanceFromCity = 99999; $countryFilter = $PECT_ISO_PKMN_3TO2[$country]; $sortByDistance = 1; } else { $countryFilter = ''; $sortByDistance = 0; } if (isset($_GET['nocache'])) { $searchUrl = pect_build_url($productType, $eventType, $city, $countryCode, $distanceFromCity, $daysBack, $daysForward, 100, $sortByDistance); $eventList = pect_get_events($searchUrl, $countryFilter); echo pect_events_to_ical($eventList, $city); } else { $url = str_replace('?t=1&', '?', "http://{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}"); $url = str_replace('&t=1', '', $url); echo pect_cache_get_file('calendar', $url . '&nocache', PECT_CACHE_CAL_TIME, true, false); } } } elseif ($country == '' || $city == '') { pect_html_header(); pect_html_menu($country); pect_html_footer(); } elseif (isset($_POST['country']) && isset($_POST['city'])) { $country = preg_replace('/[&=]/', '', substr($_POST['country'], 0, 3)); $city = trim(preg_replace('/[&=]/', '', ucwords(strtolower($_POST['city'])))); $productType = isset($_POST['tcg']) ? PECT_PRODUCT_TCG : 0; $productType |= isset($_POST['vgc']) ? PECT_PRODUCT_VGC : 0; $eventType = isset($_POST['premier']) ? PECT_EVENT_PREMIER : 0; $eventType |= isset($_POST['tournament']) ? PECT_EVENT_TOURNAMENT : 0; $eventType |= isset($_POST['league']) ? PECT_EVENT_LEAGUE : 0; $distanceFromCity = isset($_POST['distance']) ? $_POST['distance'] : -1;
function pect_get_events($searchUrl, $countryFilter) { $baseHtml = str_get_html(pect_cache_get_file('search', $searchUrl, PECT_CACHE_SEARCH_TIME, true, false)); if (!$baseHtml) { return; } $dataTable = $baseHtml->find('table[id=table-1]', 0); $eventList = array(); $eventListText = array(); $eventListId = 0; if (!$dataTable) { return; } foreach ($dataTable->find('tr') as $row) { if ($row->parent->tag == 'tbody') { $productTypeDesc = $row->find('td', 0)->find('span', 0)->innertext; $eventTypeDesc = $row->find('td', 1)->find('span', 0)->innertext; $eventUrl = PECT_BASE_URL . $row->find('td', 2)->find('a', 0)->href; $productType = 0; if ($productTypeDesc == 'ALL' || $productTypeDesc == 'TCG') { $productType |= PECT_PRODUCT_TCG; } if ($productTypeDesc == 'ALL' || $productTypeDesc == 'VG') { $productType |= PECT_PRODUCT_VGC; } if ($productTypeDesc == 'Video Game') { $productType |= PECT_PRODUCT_VGC; } if (substr($productTypeDesc, -3, 3) == 'TCG') { $productType |= PECT_PRODUCT_TCG; } // The event type is prefixed with a space, and there aren't any that use multiple words at the moment, // so we'll just remove any whitepsace from the string before we check it. $eventType = 0; $eventTypeDesc = str_replace(' ', '', $eventTypeDesc); $eventTypeDesc = preg_replace('/.*League/', 'League', $eventTypeDesc); if ($eventTypeDesc == 'League') { $eventType |= PECT_EVENT_LEAGUE; } if ($eventTypeDesc == 'Tournament') { $eventType |= PECT_EVENT_TOURNAMENT; } if ($eventTypeDesc == 'Premier') { $eventType |= PECT_EVENT_PREMIER; } $eventCache = pect_cache_get_file('events', $eventUrl, PECT_CACHE_ITEM_TIME, true, false, 'ical'); $skipCountryEvent = false; if (!$eventCache) { $eventHtml = str_get_html(pect_cache_get_file('events', $eventUrl, PECT_CACHE_ITEM_TIME)); $eventLocationName = ''; $eventAddressLine1 = ''; $eventAddressLine2 = ''; $eventCity = ''; $eventState = ''; $eventPostcode = ''; $eventCountry = ''; $eventDates = array(); $eventLatitude = null; $eventLongitude = null; if ($eventHtml != null) { if ($eventType & PECT_EVENT_LEAGUE) { $eventLocationData = $eventHtml->find('dl[class=verysimpleDL2]', 0); $eventLocationName = str_replace('<label></label>', '', $eventLocationData->find('dd', 0)->plaintext); $eventAddressLine1 = $eventLocationData->find('dd', 1)->plaintext; $eventAddressLine2 = $eventLocationData->find('dd', 2)->plaintext; $eventCity = $eventLocationData->find('dd', 3)->plaintext; $eventState = $eventLocationData->find('dd', 4)->plaintext; $eventPostcode = $eventLocationData->find('dd', 5)->plaintext; $eventCountry = $eventLocationData->find('dd', 6)->plaintext; $eventOrgData = $eventHtml->find('div[id=league-details-contact]', 0); $eventOrganiser = ''; $eventContactNo = $eventOrgData->find('dd', 1)->plaintext; $eventWebsite = $eventOrgData->find('dd', 2)->plaintext; $eventDescription = ''; // Now we have to extract events. The upcoming events only shows the next three, so we'll go straight // to the calendar instead. The calendar uses a different class to highlight days with events on, so // we'll search for those cells. $eventDateData = $eventHtml->find('div[class=right-content]', 0); // First we need to process the top month, then the second month. $eventDatesId = 0; for ($x = 0; $x < 2; $x++) { $eventMonth = $eventDateData->find('h6[class=cufon]', $x)->plaintext; $eventCalendar = $eventDateData->find('table', $x); foreach ($eventCalendar->find('td[class=calendar-playtime-season]') as $eventCalendarDay) { $eventDay = $eventCalendarDay->plaintext; $eventDate = $eventMonth . ' ' . $eventDay; $eventNameFull = $eventCalendarDay->getAttribute('title'); $eventName = preg_replace('/\\(([^\\)]*)\\).*/', '\\1', $eventNameFull); $eventRegistrationTime = preg_replace('/.*\\(\\(([^\\)]*)\\).*/', '\\1', $eventNameFull); $eventDates[$eventDatesId] = array(); $eventDates[$eventDatesId][0] = trim(str_replace('<label></label>', '', $eventName)); $eventDates[$eventDatesId][1] = ''; $eventDates[$eventDatesId][2] = ''; $eventDates[$eventDatesId][3] = trim(str_replace('<label></label>', '', $eventDate)); $eventDates[$eventDatesId][4] = trim(preg_replace('/(.*) - .*/', '\\1', $eventRegistrationTime)); $eventDates[$eventDatesId][5] = trim(preg_replace('/.* - (.*)/', '\\1', $eventRegistrationTime)); $eventDates[$eventDatesId][6] = ''; $eventDates[$eventDatesId][7] = ''; $eventDatesId++; } } } elseif ($eventType & PECT_EVENT_TOURNAMENT || $eventType & PECT_EVENT_PREMIER) { $eventLocationData = $eventHtml->find('div[class=pane]', 0)->find('form[class=list-text-only]', 2)->find('div[class=bot]', 0)->find('ol', 0); // We need to strip the labels out of the DOM to just get the correct address data. for ($x = 0; $x < 7; $x++) { $eventLocationData->find('label', $x)->innertext = ''; } $eventLocationName = str_replace('<label></label>', '', $eventLocationData->find('li', 0)->innertext); $eventAddressLine1 = $eventLocationData->find('li', 1)->innertext; $eventAddressLine2 = $eventLocationData->find('li', 2)->innertext; $eventCity = $eventLocationData->find('li', 3)->innertext; $eventState = $eventLocationData->find('li', 4)->innertext; $eventPostcode = $eventLocationData->find('li', 5)->innertext; $eventCountry = $eventLocationData->find('li', 6)->innertext; // If there is a map link, we'll pull the geo coordinates from there rather than make // a call to Google's mapping API. $eventMapUrl = $eventLocationData->find('li', 7)->find('a', 0)->href; $eventMapCoords = preg_replace('/.*q=([0-9\\-., ]*) \\(.*/', '\\1', $eventMapUrl); $eventLatitude = preg_replace('/([^,]*).*/', '\\1', $eventMapCoords); $eventLongitude = preg_replace('/.*, (.*)/', '\\1', $eventMapCoords); // Now we extract the event data. $eventDateData = $eventHtml->find('div[class=pane]', 0)->find('form[class=list-text-only]', 0)->find('div[class=bot]', 0)->find('ol', 0); for ($x = 0; $x < 8; $x++) { $eventDateData->find('label', $x)->innertext = ''; } $eventName = $eventDateData->find('li', 0)->innertext; $eventId = $eventDateData->find('li', 1)->innertext; $eventCategory = $eventDateData->find('li', 2)->innertext; $eventDate = $eventDateData->find('li', 3)->innertext; $eventRegistrationTime = $eventDateData->find('li', 4)->innertext; $eventPremierEvent = $eventDateData->find('li', 6)->plaintext; $eventStatus = $eventDateData->find('li', 7)->innertext; // We also grab the organiser information so we can display it in the calendar. $eventOrgData = $eventHtml->find('div[class=pane]', 0)->find('form[class=list-text-only]', 1)->find('div[class=bot]', 0)->find('ol', 0); $eventOrganiser = ''; $eventContactNo = ''; $eventWebsite = ''; // Not all the fields appear all the time, so we need to iterate through each li // item and check the label associated with it to determine the data content. foreach ($eventOrgData->find('li') as $eventOrgLine) { if ($eventOrgLine->find('label', 0)->innertext == 'Organizer Name') { $eventOrganiser = $eventOrgLine->find('span', 0)->innertext; } elseif ($eventOrgLine->find('label', 0)->innertext == 'Organizer Phone') { $eventContactNo = preg_replace('/<label>.*<\\/label>(.*)/', '\\1', $eventOrgData->find('li', 1)->innertext); } } // Finally, we grab the event description, if one exists. $eventDescData = $eventHtml->find('div[class=pane]', 0)->find('form[class=list-text-only]', 2)->find('div[class=bot]', 1)->find('ol', 0); $eventDescription = ''; foreach ($eventDescData->find('li') as $eventDescLine) { if ($eventDescLine->find('label', 0)->innertext == 'Details') { foreach ($eventDescLine->find('p') as $eventParagraph) { if ($eventParagraph->innertext != '') { $eventDescription .= $eventParagraph->innertext . "\\n\\n"; } } } } $eventDates[0] = array(); $eventDates[0][0] = trim(str_replace('<label></label>', '', $eventName)); $eventDates[0][1] = trim(str_replace('<label></label>', '', $eventId)); $eventDates[0][2] = trim(str_replace('<label></label>', '', $eventCategory)); $eventDates[0][3] = trim(str_replace('<label></label>', '', $eventDate)); $eventDates[0][4] = trim(preg_replace('/(.*) to .*/', '\\1', str_replace('<label></label>', '', $eventRegistrationTime))); $eventDates[0][5] = trim(preg_replace('/.* to (.*)/', '\\1', str_replace('<label></label>', '', $eventRegistrationTime))); $eventDates[0][6] = trim($eventPremierEvent); $eventDates[0][7] = trim(str_replace('<label></label>', '', $eventStatus)); } } $eventList[0] = $productType; $eventList[1] = $eventType; $eventList[2] = trim($eventUrl); $eventList[3] = trim($eventLocationName); $eventList[4] = trim($eventAddressLine1); $eventList[5] = trim($eventAddressLine2); $eventList[6] = trim($eventCity); $eventList[7] = trim($eventState); $eventList[8] = trim($eventPostcode); $eventList[9] = trim($eventCountry); $eventList[10] = $eventDates; $eventList[11] = trim($eventOrganiser); $eventList[12] = trim($eventContactNo); $eventList[13] = trim($eventWebsite); $eventList[14] = $eventLatitude; $eventList[15] = $eventLongitude; $eventList[16] = $eventDescription; $timezones = array(); $tzid = 0; $id = 0; $icalEvents = ''; $icalTimezones = ''; foreach ($eventList[10] as $eventData) { $startDate = strtotime($eventData[3] . ' ' . $eventData[4]); $endDate = strtotime($eventData[3] . ' ' . $eventData[5]); $address = $eventList[4] . ', ' . $eventList[5] . ', ' . $eventList[6] . ', ' . $eventList[7] . ', ' . $eventList[8] . ', ' . $eventList[9]; $address = str_replace(', ', '', $address); $address = str_replace('<label></label>', '', $address); $address = str_replace(', ,', ',', $address); $address = str_replace(', ,', ',', $address); $address = str_replace(',', '\\,', $address); $address = str_replace('&', '&', $address); $address = str_replace(';', '\\;', $address); if ($eventList[14] != '' && $eventList[15] != '') { $geoCoords = pect_get_google_coordinates('', $eventList[14], $eventList[15]); } else { $geoCoords = pect_get_google_coordinates($address); } // If we weren't able to geolocate the address, then we copy across the event // coordinates (if they exist, they default to null if they don't anyway) and // set the address to our previously parsed address. If we could, we apply // some formatting to it for iCal specs and then save it back to the $geoCoords // array. if ($geoCoords[0] == null) { $geoCoords[0] = $eventList[14]; $geoCoords[1] = $eventList[15]; $geoCoords[2] = ucwords($eventList[3] . ', ' . $address); $geoCoords[3] = ''; } else { $geoCoords[2] = ucwords($eventList[3]) . ', ' . $geoCoords[2]; } $geoCoords[2] = str_replace(',', '\\,', $geoCoords[2]); $geoCoords[2] = str_replace('&', '&', $geoCoords[2]); $geoCoords[2] = str_replace(';', '\\;', $geoCoords[2]); $skipCountryEvent = $countryFilter == '' ? false : true; if ($skipCountryEvent && $geoCoords[3] == $countryFilter) { $skipCountryEvent = false; } // Now if we didn't have coordinates, we weren't able to derive a timezone. As such // we'll default to the first timezone in the calendar if available, or leave it // blank if there isn't one. No timezone means the iCal client will interpret the // time based on it's own local timezone (which should in theory be the right one!) if ($geoCoords[0] == null || $geoCoords[1] == null) { if (isset($timezones[0])) { $timezone = $timezones[0]; } else { $timezone = ''; } } else { $timezone = pect_get_google_timezone($geoCoords[0], $geoCoords[1]); if (!in_array($timezone, $timezones)) { $tzdata = pect_cache_get_tz_data($timezone); if (strpos($tzdata, 'DOCTYPE HTML') === false) { $timezones[$tzid++] = $timezone; $icalTimezones .= pect_cache_get_tz_data($timezone); } } } if ($timezone == '') { $tzData = ''; } else { $tzData = ';TZID=' . $timezone; } $summary = $eventData[0]; $summary = str_replace(";", '\\;', $summary); $summary = str_replace("\\", '\\', $summary); $summary = str_replace(",", '\\,', $summary); $prefix = ''; $suffix = ''; if ($eventList[0] & PECT_PRODUCT_VGC) { $prefix = '[VG] '; } if ($eventList[0] & PECT_PRODUCT_TCG) { if ($prefix == '') { $prefix = '[TCG] '; } else { $prefix = '[VG/TCG] '; } } if ($eventList[1] & PECT_EVENT_LEAGUE) { $suffix = ' (Pokemon League)'; } if ($eventList[1] & PECT_EVENT_TOURNAMENT) { $suffix = ' (Tournament)'; } if ($eventList[1] & PECT_EVENT_PREMIER) { $suffix = ' (Premier Event)'; } if ($eventList[1] & PECT_EVENT_LEAGUE) { $uid = preg_replace('/.*\\/leagues\\/([0-9]*)\\//', '\\1', $eventList[2]); $uid = date('y\\-m\\-d', $startDate) . '-' . $uid; } else { $uid = preg_replace('/.*\\/([0-9][0-9]-[0-9][0-9]-[0-9]*)\\//', '\\1', $eventList[2]); } $uid .= '@codearoundcorners.com'; $notes = ''; if ($eventList[11] != '') { $notes .= ' * Organiser - ' . $eventList[11] . "\\n\r\n"; } if ($eventList[12] != '') { $notes .= ' * Phone - ' . pect_format_phone($eventList[12]) . "\\n\r\n"; } if ($eventList[13] != '') { $notes .= ' * Website - ' . $eventList[13] . "\\n\r\n"; } if ($notes != '' || $eventList[16] != '') { $eventText = str_replace("<br />", "\\n", $eventList[16]); $eventText = str_replace("'", '\'', $eventText); $eventText = str_replace(";", '\\;', $eventText); $eventText = str_replace("\\", '\\', $eventText); $eventText = str_replace(",", '\\,', $eventText); $eventText = iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', $eventText); $notes = "Additional information for this event:\\n\r\n" . $notes . " \\n" . $eventText . "\r\n"; } $icalEvents .= "BEGIN:VEVENT\r\n"; $icalEvents .= "UID:" . $uid . "\r\n"; $icalEvents .= "LAST-MODIFIED:" . pect_cache_get_last_modified('events', $eventList[2]) . "\r\n"; $icalEvents .= "DTSTAMP:" . date('Ymd\\THis', $startDate) . "\r\n"; $icalEvents .= "SUMMARY:" . $prefix . $summary . $suffix . "\r\n"; $icalEvents .= "DTSTART" . $tzData . ":" . date('Ymd\\THis', $startDate) . "\r\n"; $icalEvents .= "DTEND" . $tzData . ":" . date('Ymd\\THis', $endDate) . "\r\n"; $icalEvents .= "URL:" . $eventList[2] . "\r\n"; $icalEvents .= "LOCATION:" . $geoCoords[2] . "\r\n"; if ($geoCoords[0] != null && $geoCoords[1] != null) { $icalEvents .= "GEO:" . $geoCoords[0] . ";" . $geoCoords[1] . "\r\n"; } if ($notes != '') { $icalEvents .= "DESCRIPTION:" . $notes; } $icalEvents .= "END:VEVENT\r\n"; } $icalEvents .= "COUNTRY-CODE:" . $geoCoords[3]; if ($timezone != '') { pect_cache_put_file($icalTimezones . $icalEvents, 'events', $eventUrl, 'ical'); } if (!$skipCountryEvent) { $eventListText[$eventListId] = array(); $eventListText[$eventListId][0] = $icalTimezones; $eventListText[$eventListId][1] = $icalEvents; } } else { $splitPos1 = strpos($eventCache, 'BEGIN:VEVENT'); $splitPos2 = strpos($eventCache, 'COUNTRY-CODE:'); $skipCountryEvent = $countryFilter == '' ? false : true; if ($skipCountryEvent) { $countryCode = substr($eventCache, $splitPos2, strlen($eventCache) - $splitPos2); $countryCode = substr($countryCode, -2, 2); if ($countryCode == $countryFilter) { $skipCountryEvent = false; } } if (!$skipCountryEvent) { $eventListText[$eventListId] = array(); $eventListText[$eventListId][0] = substr($eventCache, 0, $splitPos1); $eventListText[$eventListId][1] = substr($eventCache, $splitPos1, $splitPos2 - $splitPos1); } } if (!$skipCountryEvent) { $eventListId++; } } } return $eventListText; }