Inheritance: extends BaseModel
 protected function loadMovieJSON($url)
 {
     \SystemLogger::debug("URL for Movie", $url);
     $json = file_get_contents($url, false, $this->context);
     \SystemLogger::debug("Response:", $json);
     return json_decode($json, true);
 }
 /**
  * @param GeocodeCached $geocode Previously stored geoLocation information
  * @param string $currentDate date for showtimes to load, advisable to pass it in
  * @param int $dateOffset number of days from the current dates
  * @return TheatreData[] an array of schema TheatreData, see below for description
  *
  * Organized in the format =>
  *
  * ```
  *
  *  TheatreData : [
  *      'theatre' => [
  *              ...fields from theatre table, MUST contain name and address...,
  *      ]
  *      'movies' => MovieData[]
  *  ]
  *
  * MovieData : [
  *     'movie' => [
  *          ...fields from movie table, MUST contain title...,
  *     ]
  *     'showtimes' => ShowtimeData[]
  * ]
  *
  * ShowtimeData: [
  *      ...fields from showtime table, must conatin show_date, show_time & type...
  * ]
  * ```
  */
 public function loadShowtimes(GeocodeCached $geocode, $currentDate = null, $dateOffset = 0)
 {
     $params = ['country' => $geocode->country_iso, 'event_date' => \Utilities::dateFromOffset($currentDate ?: date('Y-m-d'), $dateOffset)];
     \SystemLogger::debug('Begining API Request to Tripican');
     $start = microtime(true);
     $allCinemaMovieShowtimes = TripicanDataLoader::GetCinemaMovieShowtimes($this->apiClient, $params);
     \SystemLogger::debug('Request to API completed in :', microtime(true) - $start);
     $theatres = [];
     foreach ($allCinemaMovieShowtimes as $cinemaMovieShowtimes) {
         $theatre = $cinemaMovieShowtimes['cinema'];
         $id = $theatre['id'];
         if (!isset($theatres[$id])) {
             $theatres[$id] = ['theatre' => ['name' => $theatre['centre_name'], 'address' => $this->_getAddress($theatre), 'longitude' => $theatre['place']['long'], 'latitude' => $theatre['place']['lat']], 'movies' => []];
         }
         $theatreData =& $theatres[$id];
         foreach ($cinemaMovieShowtimes['movie_showtimes'] as $movieShowtimes) {
             $movie = $movieShowtimes['movie'];
             $mId = $movie['id'];
             if (!isset($theatreData['movies'][$mId])) {
                 $theatreData['movies'][$mId] = ['movie' => ['title' => $movie['title'], 'genre' => $movie['genre'][0], 'user_rating' => isset($movie['imdb_rating']) ? floatval($movie['imdb_rating'][0] / 10.0) : null, 'poster_url' => $movie['poster'], 'rated' => $movie['rated'][0], 'runtime' => $movie['duration']], 'showtimes' => []];
             }
             $movieData =& $theatreData['movies'][$mId];
             foreach ($movieShowtimes['showtimes'] as $showtime) {
                 $movieData['showtimes'][] = ['show_date' => $showtime['event_date'], 'show_time' => $showtime['event_time'], 'type' => $this->_getMapType($showtime['type']), 'url' => $showtime['online_ticketing'] ? $showtime['url'] : null];
             }
         }
     }
     array_walk($theatres, function (&$t) {
         $t['movies'] = array_values($t['movies']);
     });
     if (!empty($theatres)) {
         $this->overrideDistanceCompute();
     }
     return array_values($theatres);
 }
 /**
  *
  * @param string $token format requestId|deviceId|sign=sha1(requestId.deviceId.secretKey)
  * @param $requestId
  * @param bool $verifySign
  * @return UserDevice current device represented by token.
  * @throws \DbTableException
  */
 public static function validate($token, &$requestId, $verifySign = true)
 {
     list($requestId, $deviceId, $sign) = explode('|', $token);
     if (!($requestId && $deviceId && $sign)) {
         return null;
     }
     $instance = static::instance();
     $userDevice = $instance->getEntity($deviceId);
     if (!$userDevice) {
         \SystemLogger::warn("Invalid user device ID: [{$deviceId}]");
         return null;
     }
     if ($verifySign) {
         if ($sign != self::sign($requestId, $deviceId, $userDevice->secret_key)) {
             \SystemLogger::warn("Signature not valid: ", $sign);
             return null;
         }
         $tableWhere = (new \DbTableWhere())->where('user_device_id', $userDevice->id)->where('request_id', $requestId)->setLimitAndOffset(1);
         if (count(UserDeviceReqManager::instance()->getEntitiesWhere($tableWhere))) {
             \SystemLogger::warn("duplicate request id: ", $requestId);
             return null;
         }
     }
     return $userDevice;
 }
 /**
  * @param string $date date in yyyy-mm-dd form
  * @param string $time time in HH:MM form
  * @param int $offset in minutes
  * @return \DateTime
  */
 private function getDateTime($date, $time, $offset = 0)
 {
     $dateTime = new \DateTime("{$date} {$time}", $this->dateTimeZone);
     if ($offset) {
         $subtract = $offset < 0;
         $interval = new \DateInterval('PT' . abs($offset) . 'M');
         $dateTime = $subtract ? $dateTime->sub($interval) : $dateTime->add($interval);
     }
     \SystemLogger::info('Time: Generated', $date, $time, $dateTime->format('c'));
     return $dateTime;
 }
 public function lookupTimeZoneByGeoCode(GeoLocation $geoLocation)
 {
     foreach ($this->providers as $serviceProvier) {
         $timezone = $serviceProvier->getTimeZone($geoLocation);
         if ($timezone) {
             return $timezone;
         } else {
             if ($lastError = $serviceProvier->getLastError(true)) {
                 \SystemLogger::warn("Error... {$lastError->getMessage()} TYPE: {$lastError->getType()}");
             }
         }
     }
 }
 /**
  * @param Theatre $theatre
  * @return bool|mixed|\mysqli_result
  */
 public static function setTheatreLatLng(Theatre $theatre)
 {
     //51.4752267,-0.2396438
     \SystemLogger::info("Finding LongLat for: ", $theatre->name, $theatre->address);
     $geocode = LocationService::instance()->addressLookup($theatre->address, [], true);
     $saved = false;
     if ($geocode) {
         $geoLocation = $geocode->getGeocode();
         \SystemLogger::info("Found Geocode: ", strval($geoLocation));
         $saved = $theatre->update(['longitude' => $geoLocation->getLongitude(), 'latitude' => $geoLocation->getLatitude()], 'id');
     }
     return $saved;
 }
 private function computePhysicalDistance(GeoLocation $source, GeoLocation $destination, $shuffle = true)
 {
     if ($shuffle) {
         shuffle($this->serviceProviderList);
     }
     foreach ($this->serviceProviderList as $serviceProvier) {
         if (is_a($serviceProvier, '\\models\\services\\LocationDistanceCheckI')) {
             /* @var $serviceProvier LocationDistanceCheckI */
             $distance = $serviceProvier->distanceLookup($source, $destination);
             if ($distance >= 0) {
                 return $distance;
             } else {
                 if ($lastError = $serviceProvier->getLastError(true)) {
                     \SystemLogger::warn("Error... {$lastError->getMessage()} TYPE: {$lastError->getType()}");
                     if (!$lastError->isRateLimit()) {
                         break;
                     }
                 }
             }
         }
     }
     return -1;
 }
 public static function cleanPbis()
 {
     $staleDate = strtotime("-4 days");
     $files = glob(CACHE_DIR . "/*");
     $removed = 0;
     foreach ($files as $file) {
         \SystemLogger::info("Looking at: ", $file);
         if (filemtime($file) < $staleDate && unlink($file)) {
             \SystemLogger::info("\tRemoved file: ", $file);
             $removed++;
         }
     }
     return $removed;
 }
 public function logRequest($url, $response, array $headers, &$file = null)
 {
     $contentType = 'text/html';
     foreach ($headers as $header) {
         if (preg_match('/^Content-Type/', $header)) {
             //Content-Type: application/json; charset=utf-8
             $tmp1 = preg_split('/\\s*:\\s*/', $header);
             $contentType = trim(explode(';', $tmp1[1])[0]);
             break;
         }
     }
     if (preg_match('/html/i', $contentType)) {
         $ext = 'html';
     } elseif (preg_match('/json/i', $contentType)) {
         $ext = 'json';
     } elseif (preg_match('/xml/i', $contentType)) {
         $ext = 'xml';
     } else {
         $ext = 'txt';
     }
     $uriParts = parse_url($url);
     $fileDir = REQUESTS_LOG_DIR . $uriParts['host'] . DIRECTORY_SEPARATOR;
     if (!is_dir($fileDir) && !mkdir($fileDir, 0755, true)) {
         \SystemLogger::warn('Could not make directory:', $fileDir);
         return -1;
     }
     $file = $fileDir . join('.', [preg_replace('/[^A-Za-z0-9\\._\\-]+/', '', $uriParts['path']), microtime(true), $ext]);
     return file_put_contents($file, $response);
 }
 protected function extractShowtimes($pageData)
 {
     $startTime = microtime(true);
     \SystemLogger::debug('Extraction of page started, total length = ', strlen($pageData));
     \SystemLogger::debug('Loading into QueryPath');
     $imdbPage = QueryPath::withHTML($pageData);
     \SystemLogger::debug('Query Path done loading...');
     \SystemLogger::debug(__CLASS__, "Extracting theatres...");
     //$cinemasList = $imdbPage->find("#cinemas-at-list .list_item.odd, #cinemas-at-list .list_item.even");
     $cinemasList = $imdbPage->find("#cinemas-at-list > .list_item");
     \SystemLogger::debug(__CLASS__, "Found: ", $cinemasList->count(), "cinemas");
     $theatreMovieShowtimes = array();
     if ($cinemasList) {
         for ($i = 0; $i < ShowtimeService::THEATRE_LIMIT && $i < $cinemasList->count(); $i++) {
             \SystemLogger::debug('Processing theatre at position: ', $i);
             /* @var $cinemaDiv DOMQuery */
             $cinemaDiv = new DOMQuery($cinemasList->get($i));
             $theatreData = array();
             $theatreTitle = $cinemaDiv->find('h3')->first();
             \SystemLogger::info("{$i}. Theatre: ", $theatreTitle->text());
             if (!$theatreTitle) {
                 \SystemLogger::debug(__CLASS__, "No theatre found");
                 continue;
             }
             $theatreData['name'] = trim($theatreTitle->text());
             $addressSpanTmp = $cinemaDiv->find('.address div');
             $addressSpan = $addressSpanTmp ? preg_replace('/\\s+/', ' ', $addressSpanTmp->text()) : "";
             $theatreData['address'] = trim(explode('|', $addressSpan)[0]);
             $movieDomList = $cinemaDiv->find('.list_item');
             \SystemLogger::info(__CLASS__, "Number of Movies = ", $movieDomList->count());
             if (!count($movieDomList)) {
                 \SystemLogger::debug(__CLASS__, "No movies found");
                 continue;
             }
             $theatreMovieShowtimes[] = array('theatre' => $theatreData, 'movies' => $this->extractMovies($movieDomList));
             \SystemLogger::debug('--Theatre extraction completed---');
         }
     }
     \SystemLogger::debug('Showtimes extraction completed in :', microtime(true) - $startTime);
     //var_dump($theatreMovieShowtimes);exit;
     return $theatreMovieShowtimes;
 }
 private function extractTheatreMovieShowtimes($pageData, $limit, &$totalPages)
 {
     $startTime = microtime(true);
     \SystemLogger::debug("Begining extraction of data from file, size = ", strlen($pageData));
     if ($limit <= 0) {
         \SystemLogger::warn("Invalid limit was supplied: ", $limit);
         return array();
     }
     \SystemLogger::debug('Attempting to load into Query Path');
     /* @var $moviePage DOMQuery */
     $moviePage = \QueryPath::withHTML($pageData, null, array('convert_to_encoding' => "UTF-8", 'convert_from_encoding' => "UTF-8"));
     \SystemLogger::debug('Loaded into QueryPath');
     /* @var $theatersDom DOMQuery */
     $theatersDom = $moviePage->find("div.theater");
     //get total pages
     $paginationDom = $moviePage->find("#navbar td");
     $totalPages = $paginationDom->length ? $paginationDom->length - 2 : 1;
     \SystemLogger::debug("Found", $theatersDom->length, "theatres");
     $theatreCinemas = array();
     $foundTheatres = 0;
     \SystemLogger::debug('Loading data from Theatres DOM list');
     for ($i = 0; $i < $theatersDom->length && $foundTheatres < $limit; $i++) {
         $theatre = array();
         $theatreDom = new DOMQuery($theatersDom->get($i));
         $theatre['name'] = trim($theatreDom->find("h2.name")->first()->text());
         if (!$theatre['name']) {
             \SystemLogger::warn("Found no theatre at dom level: ", $i);
             continue;
         }
         \SystemLogger::debug("processing theatre: ", $theatre['name']);
         $addressText = $theatreDom->find(".info")->first()->text();
         //echo  $addressText, "<br>";
         $tmp = explode(" - ", trim($addressText));
         array_pop($tmp);
         $theatre['address'] = join(' ', $tmp);
         $theatreCinemas[] = array('theatre' => $theatre, 'movies' => $this->extractMovieShowtimes($theatreDom));
         $foundTheatres++;
     }
     \SystemLogger::info('Extraction done, completed in ', microtime(true) - $startTime, 'ms');
     return $theatreCinemas;
 }
 public function doPreload()
 {
     $version = $this->currentVersion;
     if ($this->geocode) {
         $status = $this->showtimeService->loadData($this->geocode, $this->currentDate, false, $this->dateOffset);
         \SystemLogger::info("PreloadStatus: ", $status);
     }
     $this->result['status'] = $status;
     $this->result['version'] = $version;
 }