/** * Populate this object with pre-existing data * @since Version 3.2 * @return boolean */ public function fetch() { if (!filter_var($this->id, FILTER_VALIDATE_INT)) { throw new Exception("Cannot fetch sighting - no ID given"); } $mckey = sprintf("railpage:sighting=%d", $this->id); if (!($row = $this->Memcached->fetch($mckey))) { $query = "SELECT s.id, s.date, s.date_added, s.lat, s.lon, s.text, s.user_id, s.timezone, u.username, s.loco_ids, s.meta\n FROM sighting AS s\n LEFT JOIN nuke_users AS u ON s.user_id = u.user_id\n WHERE s.id = ?"; $row = $this->db->fetchRow($query, $this->id); $this->Memcached->save($mckey, $row, 0); } if (!isset($row) || !is_array($row)) { return false; } $this->lat = $row['lat']; $this->lon = $row['lon']; $this->text = $row['text']; $this->user_id = $row['user_id']; $this->username = $row['username']; $this->timezone = $row['timezone']; $this->meta = json_decode($row['meta'], true); $this->loco_ids = json_decode($row['loco_ids'], true); $this->date = new DateTime($row['date'], new DateTimeZone($this->timezone)); $this->date_added = new DateTime($row['date_added'], new DateTimeZone($this->timezone)); $this->url = new Url("/sightings/view/" . $this->id); $this->Place = Place::Factory($this->lat, $this->lon); return true; }
/** * Get the geoplace for this photo * @since Version 3.10.0 * @return \Railpage\Place */ public function getPlace() { if (is_null($this->lat) || is_null($this->lon)) { return false; } return Place::Factory($this->lat, $this->lon); }
/** * Commit changes to the database * @since Version 3.0.1 * @version 3.7.5 * @return boolean */ public function commit() { /** * Fill in the gaps with the new Place object */ if (empty($this->region) || empty($this->country)) { $Place = Place::Factory($this->lat, $this->lon); if (!empty($Place->Country->code)) { $this->country = $Place->Country->code; } if (!empty($Place->Region->name)) { $this->region = $Place->Region->name; } } $find = array("@Victoria@i", "@New South Wales@i", "@Queensland@i", "@South Australia@i", "@Tasmania@i", "@Northern Territory@i", "@Western Australia@i", "@Australian Capital Territory@i"); $replace = array("VIC", "NSW", "QLD", "SA", "TAS", "NT", "WA", "ACT"); $this->region = preg_replace($find, $replace, $this->region); // Defaults for new locations if (empty($this->id)) { $this->active = 0; $this->date_added = time(); $this->date_modified = time(); } /** * Validate the data */ $this->validate(); $data = array("lat" => $this->lat, "long" => $this->lon, "country" => $this->country, "region" => $this->region, "region_slug" => $this->makeRegionSlug(), "locality" => $this->locality, "name" => trim($this->name), "desc" => $this->desc, "topicid" => $this->topicid, "zoom" => $this->zoom, "active" => $this->active, "date_added" => $this->date_added, "date_modified" => $this->date_modified, "user_id" => $this->user_id, "slug" => $this->slug, "traffic" => $this->traffic, "environment" => $this->environment, "directions_driving" => $this->directions_driving, "directions_parking" => $this->directions_parking, "directions_pt" => $this->directions_pt, "amenities" => $this->amenities); if (filter_var($this->id, FILTER_VALIDATE_INT) && $this->id > 0) { $where = array("id = ?" => $this->id); $this->db->update("location", $data, $where); $this->Memcached->delete($this->mckey); } else { $this->db->insert("location", $data); $this->id = $this->db->lastInsertId(); $this->Memcached->delete("railpage:locations.newest"); $this->mckey = sprintf("railpage:locations.location=%d", $this->id); } $this->updateGeoplace(); }
/** * Populate this image with fresh data * * @since Version 3.8.7 * @return $this * * @param boolean $force * @param int $option * * @throws \Exception if the photo cannot be found on the image provider * @todo Split this into utility functions */ public function populate($force = false, $option = null) { if ($force === false && !$this->isStale()) { return $this; } Debug::LogCLI("Fetching data from " . $this->provider . " for image ID " . $this->id . " (photo ID " . $this->photo_id . ")"); /** * Start the debug timer */ if (RP_DEBUG) { global $site_debug; $debug_timer_start = microtime(true); } /** * New and improved populator using image providers */ $Provider = $this->getProvider(); $data = false; try { $data = $Provider->getImage($this->photo_id, $force); } catch (Exception $e) { $expected = array(sprintf("Unable to fetch data from Flickr: Photo \"%s\" not found (invalid ID) (1)", $this->photo_id), "Unable to fetch data from Flickr: Photo not found (1)"); if (in_array($e->getMessage(), $expected)) { $where = ["image_id = ?" => $this->id]; $this->db->delete("image_link", $where); $where = ["id = ?" => $this->id]; $this->db->delete("image", $where); throw new Exception("Photo no longer available from " . $this->provider); } } if ($data) { $this->sizes = $data['sizes']; $this->title = empty($data['title']) ? "Untitled" : $data['title']; $this->description = $data['description']; $this->meta = array("dates" => array("posted" => $data['dates']['uploaded'] instanceof DateTime ? $data['dates']['uploaded']->format("Y-m-d H:i:s") : $data['dates']['uploaded']['date'], "taken" => $data['dates']['taken'] instanceof DateTime ? $data['dates']['taken']->format("Y-m-d H:i:s") : $data['dates']['taken']['date'])); $this->author = new stdClass(); $this->author->username = $data['author']['username']; $this->author->realname = !empty($data['author']['realname']) ? $data['author']['realname'] : $data['author']['username']; $this->author->id = $data['author']['id']; $this->author->url = "https://www.flickr.com/photos/" . $this->author->id; if ($user_id = UserUtility::findFromFlickrNSID($this->author->id)) { $data['author']['railpage_id'] = $user_id; } if (isset($data['author']['railpage_id']) && filter_var($data['author']['railpage_id'], FILTER_VALIDATE_INT)) { $this->author->User = UserFactory::CreateUser($data['author']['railpage_id']); } /** * Load the tags */ if (isset($data['tags']) && is_array($data['tags']) && count($data['tags'])) { foreach ($data['tags'] as $row) { $this->meta['tags'][] = $row['raw']; } } /** * Load the Place object */ if ($option != Images::OPT_NOPLACE && isset($data['location']) && !empty($data['location'])) { try { $this->Place = Place::Factory($data['location']['latitude'], $data['location']['longitude']); } catch (Exception $e) { // Throw it away. Don't care. } } $this->links = new stdClass(); $this->links->provider = isset($data['urls']['url'][0]['_content']) ? $data['urls']['url'][0]['_content'] : $data['urls'][key($data['urls'])]; $this->commit(); $this->cacheGeoData(); return true; } /** * Fetch data in various ways for different photo providers */ switch ($this->provider) { /** * Picasa */ case "picasaweb": if (empty($this->meta) && !is_null(filter_input(INPUT_SERVER, "HTTP_REFERER", FILTER_SANITIZE_URL)) && strpos(filter_input(INPUT_SERVER, "HTTP_REFERER", FILTER_SANITIZE_URL), "picasaweb.google.com")) { $album = preg_replace("@(http|https)://picasaweb.google.com/([a-zA-Z\\-\\.]+)/(.+)@", "\$2", filter_input(INPUT_SERVER, "HTTP_REFERER", FILTER_SANITIZE_URL)); if (is_string($album)) { $update_url = sprintf("https://picasaweb.google.com/data/feed/api/user/%s/photoid/%s?alt=json", $album, $this->photo_id); } } if (isset($update_url)) { $data = file_get_contents($update_url); $json = json_decode($data, true); $this->meta = array("title" => $json['feed']['subtitle']['$t'], "description" => $json['feed']['title']['$t'], "dates" => array("posted" => date("Y-m-d H:i:s", $json['feed']['gphoto$timestamp']['$t'])), "sizes" => array("original" => array("width" => $json['feed']['gphoto$width']['$t'], "height" => $json['feed']['gphoto$height']['$t'], "source" => str_replace(sprintf("/s%d/", $json['feed']['media$group']['media$thumbnail'][0]['width']), sprintf("/s%d/", $json['feed']['gphoto$width']['$t']), $json['feed']['media$group']['media$thumbnail'][0]['url'])), "largest" => array("width" => $json['feed']['gphoto$width']['$t'], "height" => $json['feed']['gphoto$height']['$t'], "source" => str_replace(sprintf("/s%d/", $json['feed']['media$group']['media$thumbnail'][0]['width']), sprintf("/s%d/", $json['feed']['gphoto$width']['$t']), $json['feed']['media$group']['media$thumbnail'][0]['url']))), "photo_id" => $json['feed']['gphoto$id']['$t'], "album_id" => $json['feed']['gphoto$albumid']['$t'], "updateurl" => sprintf("%s?alt=json", $json['feed']['id']['$t'])); foreach ($json['feed']['media$group']['media$thumbnail'] as $size) { if ($size['width'] <= 500 && $size['width'] > 200) { $this->meta['sizes']['small'] = array("width" => $size['width'], "height" => $size['height'], "source" => $size['url']); } if ($size['width'] <= 200) { $this->meta['sizes']['small'] = array("width" => $size['width'], "height" => $size['height'], "source" => $size['url']); } if ($size['width'] <= 1024 && $size['width'] > 500) { $this->meta['sizes']['large'] = array("width" => $size['width'], "height" => $size['height'], "source" => $size['url']); } } foreach ($json['feed']['link'] as $link) { if ($link['rel'] == "alternate" && $link['type'] == "text/html") { $this->meta['source'] = $link['href']; } } if ($option != Images::OPT_NOPLACE && isset($json['feed']['georss$where']['gml$Point']) && is_array($json['feed']['georss$where']['gml$Point'])) { $pos = explode(" ", $json['feed']['georss$where']['gml$Point']['gml$pos']['$t']); $this->Place = Place::Factory($pos[0], $pos[1]); } $this->title = $this->meta['title']; $this->description = $this->meta['description']; $this->author = new stdClass(); $this->author->username = $album; $this->author->id = $album; $this->author->url = sprintf("%s/%s", $json['feed']['generator']['uri'], $album); } $this->sizes = $this->meta['sizes']; $this->commit(); break; /** * Vicsig */ /** * Vicsig */ case "vicsig": if (strpos(filter_input(INPUT_SERVER, "HTTP_REFERER", FILTER_SANITIZE_URL), "vicsig.net/photo")) { $this->meta['source'] = filter_input(INPUT_SERVER, "HTTP_REFERER", FILTER_SANITIZE_STRING); $response = $this->GuzzleClient->get($this->meta['source']); if ($response->getStatusCode() != 200) { throw new Exception(sprintf("Failed to fetch image data from %s: HTTP error %s", $this->provider, $response->getStatusCode())); } /** * Start fetching it */ $data = $response->getBody(); $doc = new DomDocument(); $doc->loadHTML($data); $images = $doc->getElementsByTagName("img"); foreach ($images as $element) { if (!empty($element->getAttribute("src")) && !empty($element->getAttribute("alt"))) { #$image_title = $element->getAttribute("alt"); $this->sizes['original'] = array("source" => $element->getAttribute("src"), "width" => $element->getAttribute("width"), "height" => $element->getAttribute("height")); if (substr($this->sizes['original']['source'], 0, 1) == "/") { $this->sizes['original']['source'] = "http://www.vicsig.net" . $this->sizes['original']['source']; } break; } } $desc = $doc->getElementsByTagName("i"); foreach ($desc as $element) { if (!isset($image_desc)) { $text = trim($element->nodeValue); $text = str_replace("\r\n", "\n", $text); $text = explode("\n", $text); /** * Loop through the exploded text and remove the obvious date/author/etc */ foreach ($text as $k => $line) { // Get the author if (preg_match("@Photo: @i", $line)) { $this->author = new stdClass(); $this->author->realname = str_replace("Photo: ", "", $line); $this->author->url = filter_input(INPUT_SERVER, "HTTP_REFERER", FILTER_SANITIZE_STRING); unset($text[$k]); } // Get the date try { $this->meta['dates']['posted'] = (new DateTime($line))->format("Y-m-d H:i:s"); unset($text[$k]); } catch (Exception $e) { // Throw it away } } /** * Whatever's left must be the photo title and description */ foreach ($text as $k => $line) { if (empty($this->title)) { $this->title = $line; continue; } $this->description .= $line; } $this->links = new stdClass(); $this->links->provider = filter_input(INPUT_SERVER, "HTTP_REFERER", FILTER_SANITIZE_STRING); $this->commit(); } } } break; } /** * End the debug timer */ if (RP_DEBUG) { $site_debug[] = __CLASS__ . "::" . __FUNCTION__ . "() : completed in " . round(microtime(true) - $debug_timer_start, 5) . "s"; } return $this; }
/** * Populate this object * @since Version 3.9.1 * @return void * @param int|string $id */ private function populate($id) { $row = $this->load($id); if (!isset($row) || !is_array($row)) { return; } $this->title = $row['title']; $this->desc = $row['description']; $this->meta = json_decode($row['meta'], true); $this->slug = $row['slug']; $this->status = isset($row['status']) ? $row['status'] : Events::STATUS_APPROVED; if (!isset($row['user_id'])) { $row['user_id'] = 45; } $this->setAuthor(UserFactory::CreateUser($row['user_id'])); $this->flickr_tag = "railpage:event=" . $this->id; if (filter_var($row['category_id'], FILTER_VALIDATE_INT)) { $this->Category = Factory::CreateEventCategory($row['category_id']); } if (filter_var($row['organisation_id'], FILTER_VALIDATE_INT)) { $this->Organisation = OrganisationsFactory::CreateOrganisation($row['organisation_id']); } if (!empty($row['lat']) && round($row['lat'], 3) != "0.000" && !empty($row['lon']) && round($row['lon'], 3) != "0.000") { $this->Place = Place::Factory($row['lat'], $row['lon']); } $this->createUrls(); $this->Templates = new stdClass(); $this->Templates->view = sprintf("%s/event.tpl", $this->Module->Paths->html); }
/** * Constructor * @since Version 3.8.7 * @param int $id */ public function __construct($id = NULL) { parent::__construct(); $this->Module = new Module("events"); $this->namespace = $this->Module->namespace; if (!filter_var($id, FILTER_VALIDATE_INT)) { return; } if (!($row = $this->db->fetchRow("SELECT * FROM event_dates WHERE id = ?", $id))) { return; } $this->id = $id; $this->Event = Factory::CreateEvent($row['event_id']); $this->Date = new DateTime($row['date']); $this->meta = json_decode($row['meta'], true); $this->status = $row['status']; $this->url = new Url("/events?mode=event.date&event_id=" . $this->Event->id . "&date_id=" . $this->id); $this->url->approve = sprintf("/events?mode=event.date.setstatus&date_id=%d&status=%d", $this->id, self::STATUS_RUNNING); $this->url->reject = sprintf("/events?mode=event.date.setstatus&date_id=%d&status=%d", $this->id, self::STATUS_REJECTED); $this->url->cancel = sprintf("/events?mode=event.date.setstatus&date_id=%d&status=%d", $this->id, self::STATUS_CANCELLED); $this->url->export = sprintf("/events/export/date/%d.ics", $this->id); $this->setAuthor(UserFactory::CreateUser($row['user_id'])); if ($row['start'] != "00:00:00") { $this->Start = new DateTime($row['date'] . " " . $row['start']); } if ($row['end'] != "00:00:00") { $this->End = new DateTime($row['date'] . " " . $row['end']); } if (isset($this->meta['lat']) && empty($this->meta['lat'])) { unset($this->meta['lat']); } if (isset($this->meta['lon']) && empty($this->meta['lon'])) { unset($this->meta['lon']); } if (isset($this->meta['lat']) && isset($this->meta['lon'])) { $this->Place = Place::Factory($this->meta['lat'], $this->meta['lon']); } try { if ($this->Event->Place instanceof Place && !empty($this->Event->Place->Region->timezone)) { $this->Date->setTimezone(new DateTimeZone($this->Event->Place->Region->timezone)); if ($this->Start instanceof DateTime) { $this->Start->setTimezone(new DateTimeZone($this->Event->Place->Region->timezone)); } if ($this->End instanceof DateTime) { $this->End->setTimezone(new DateTimeZone($this->Event->Place->Region->timezone)); } } } catch (Exception $e) { printArray($e->getMessage()); printArray($this->Event->Place->Region->timezone); } }
/** * Get important EXIF information from the image * @since Version 3.10.0 * @return array * @param \Railpage\Gallery\Image $imageObject */ public static function PopulateExif($imageObject) { $imageSource = Album::ALBUMS_DIR . $imageObject->path; /** * Read the IPTC data */ #$size = getimagesize($imageSource, $info); if (is_array($info)) { $iptc = iptcparse($info["APP13"]); if (isset($iptc['2#005'])) { $imageObject->title = $iptc['2#005'][0]; } } /** * Read the EXIF data */ $exif = exif_read_data($imageSource, 0, true); if (isset($exif['IFD0']['ImageDescription'])) { $imageObject->caption = $exif['IFD0']['ImageDescription']; } if (isset($exif['EXIF']['DateTimeOriginal'])) { $imageObject->DateTaken = new DateTime($exif['EXIF']['DateTimeOriginal']); } if (isset($exif['GPS']['GPSLatitude']) && isset($exif['GPS']['GPSLongitude'])) { $lat = self::getGps($exif['GPS']['GPSLatitude'], $exif['GPS']['GPSLatitudeRef']); $lon = self::getGps($exif['GPS']['GPSLongitude'], $exif['GPS']['GPSLongitudeRef']); $imageObject->Place = Place::Factory($lat, $lon); } return $imageObject; }