Files
spot/inc/spot.php
2018-04-15 14:59:39 +02:00

341 lines
11 KiB
PHP
Executable File

<?php
class Spot extends Main
{
//Spot Mode
const MODE_HISTO = 'histo';
const MODE_BLOG = 'blog';
//Spot feed
const FEED_ID = '0Y5LrvigElWeAieBGnFol0KBEuOTkFJmm';
const FEED_HOOK = 'https://api.findmespot.com/spot-main-web/consumer/rest-api/2.0/public/feed/';
const FEED_TYPE_XML = '/message.xml';
const FEED_TYPE_JSON = '/message.json';
//Database
const MSG_TABLE = 'messages';
const FEED_TABLE = 'feeds';
const SPOT_TABLE = 'spots';
const POST_TABLE = 'posts';
const FORMAT_TIME = 'd/m/Y à H:i';
const FEED_CHUNK_SIZE = 15;
public function __construct($oClassManagement, $sProcessPage)
{
parent::__construct($oClassManagement, $sProcessPage);
}
protected function install()
{
//Install DB
$this->oDb->install();
//Add feed
//$this->oDb->insertRow(self::FEED_TABLE, array('ref_feed_id'=>self::FEED_ID));
}
protected function getSqlOptions()
{
return array
(
'tables' => array
(
self::MSG_TABLE => array('ref_msg_id', Db::getId(self::FEED_TABLE), 'type', 'latitude', 'longitude', 'timestamp', 'unix_timestamp', 'content', 'battery_state'),
self::FEED_TABLE => array('ref_feed_id', Db::getId(self::SPOT_TABLE), 'name', 'description', 'status'),
self::SPOT_TABLE => array('ref_spot_id', 'name', 'model'),
self::POST_TABLE => array('name', 'content')
),
'types' => array
(
'ref_msg_id' => "INT",
'type' => "VARCHAR(20)",
'latitude' => "DECIMAL(7,5)",
'longitude' => "DECIMAL(8,5)",
'timestamp' => "DATETIME",
'unix_timestamp'=> "INT",
'content' => "LONGTEXT",
'battery_state' => "VARCHAR(10)",
'ref_spot_id' => "VARCHAR(10)",
'name' => "VARCHAR(100)",
'model' => "VARCHAR(20)",
'ref_feed_id' => "VARCHAR(40)",
'description' => "VARCHAR(100)",
'status' => "VARCHAR(10)",
),
'constraints' => array
(
self::MSG_TABLE => "UNIQUE KEY `uni_ref_msg_id` (`ref_msg_id`)",
self::FEED_TABLE => "UNIQUE KEY `uni_ref_feed_id` (`ref_feed_id`)",
self::SPOT_TABLE => "UNIQUE KEY `uni_ref_spot_id` (`ref_spot_id`)",
self::MSG_TABLE => "INDEX(`ref_msg_id`)",
self::FEED_TABLE => "INDEX(`ref_feed_id`)",
self::SPOT_TABLE => "INDEX(`ref_spot_id`)",
),
'cascading_delete' => array
(
self::SPOT_TABLE=>array(self::MSG_TABLE)
)
);
}
public function getMainPage($asGlobalVars = array(), $sMainPage = 'index', $asMainPageTags=array())
{
return parent::getMainPage(
array(
'vars' => array(
'feed_id' => self::FEED_ID,
'chunk_size'=> self::FEED_CHUNK_SIZE,
'mode' => Settings::MODE,
'google_api'=> Settings::GOOGLE_MAPS_API_KEY
)
),
'index',
array('GOOGLE_MAPS_API_KEY' => Settings::GOOGLE_MAPS_API_KEY)
);
}
/* Getting & Storing messages */
private function getFeed($sRefFeedId=self::FEED_ID)
{
$sUrl = self::FEED_HOOK.$sRefFeedId.self::FEED_TYPE_JSON;
$sContent = file_get_contents($sUrl);
return json_decode($sContent, true);
}
private function updateFeed($sRefFeedId=self::FEED_ID)
{
$asData = $this->getFeed($sRefFeedId);
$asMsgs = $asData['response']['feedMessageResponse']['messages'];
$asFeed = $asData['response']['feedMessageResponse']['feed'];
if(!empty($asMsgs))
{
//Update Spot Info
$asFirstMsg = array_values($asMsgs)[0];
$asSpotInfo = array('ref_spot_id'=>$asFirstMsg['messengerId'], 'name'=>$asFirstMsg['messengerName'], 'model'=>$asFirstMsg['modelId']);
$iSpotId = $this->oDb->insertUpdateRow(self::SPOT_TABLE, $asSpotInfo, array('ref_spot_id'));
//Update Feed Info
$asFeedInfo = array(
'ref_feed_id' => $sRefFeedId,
Db::getId(self::SPOT_TABLE) => $iSpotId,
'name' => $asFeed['name'],
'description' => $asFeed['description'],
'status' => $asFeed['status'],
'led' => date(Db::MYSQL_TIMESTAMP) //update with current time
);
$iFeedId = $this->oDb->insertUpdateRow(self::FEED_TABLE, $asFeedInfo, array('ref_feed_id'));
//Update Messages
foreach($asMsgs as $asMsg)
{
$asMsg = array(
'ref_msg_id' => $asMsg['id'],
Db::getId(self::FEED_TABLE) => $iFeedId,
'type' => $asMsg['messageType'],
'latitude' => $asMsg['latitude'],
'longitude' => $asMsg['longitude'],
'timestamp' => date(Db::MYSQL_TIMESTAMP, strtotime($asMsg['dateTime'])), //Stored in Local Time
'unix_timestamp' => $asMsg['unixTime'], //Stored in UNIX time
'content' => $asMsg['messageContent'],
'battery_state' => $asMsg['batteryState']
);
$this->oDb->insertUpdateRow(self::MSG_TABLE, $asMsg, array('ref_msg_id'));
}
}
}
public function getMessages($sRefFeedId=self::FEED_ID)
{
//Adding another point to test
/*
$test = $this->oDb->selectRow(self::MSG_TABLE, 1);
unset($test['id_message']);
$test['ref_msg_id'] = $test['ref_msg_id'] + 1;
$test['latitude'] = '-41.4395';
$test['longitude'] = '172.1936';
$this->oDb->insertUpdateRow(self::MSG_TABLE, $test, array('ref_msg_id'));
*/
//Check last message & update feed if necessary (max once a day)
$sLastMsg = $this->oDb->selectValue(self::FEED_TABLE, 'led', array('ref_feed_id'=>$sRefFeedId));
if(Settings::MODE!=self::MODE_HISTO && mb_substr($sLastMsg, 0, 10) != date('Y-m-d')) $this->updateFeed($sRefFeedId);
//Extract messages
$asMessages = $this->getSpotMessages();
$bSuccess = !empty($asMessages);
$sDesc = $bSuccess?'':self::NO_DATA;
return self::getJsonResult($bSuccess, $sDesc, $asMessages);
}
private function getSpotMessages()
{
$asInfo = array('from'=>self::MSG_TABLE, 'orderBy'=>array('timestamp'=>'ASC'));
if(Settings::MODE==self::MODE_HISTO) {
$asInfo['constraint'] = array('timestamp'=>Settings::HISTO_SPAN);
$asInfo['constOpe'] = array('timestamp'=>"BETWEEN");
}
$asMessages = $this->oDb->selectRows($asInfo);
foreach($asMessages as $iKey=>$asMessage)
{
$iUnixTimeStamp = strtotime($asMessage['timestamp']);
$asMessages[$iKey]['latitude'] = floatval($asMessages[$iKey]['latitude']);
$asMessages[$iKey]['longitude'] = floatval($asMessages[$iKey]['longitude']);
$asMessages[$iKey]['relative_time'] = Toolbox::getDateTimeDesc($iUnixTimeStamp);
$asMessages[$iKey]['formatted_time'] = date(self::FORMAT_TIME, $iUnixTimeStamp);
}
return $asMessages;
}
private function getPictures()
{
$asPicPaths = glob('files/*.{jpg,JPG,jpeg,JPEG,png,PNG}', GLOB_BRACE);
$asPics = array();
foreach($asPicPaths as $sPicPath)
{
//Finding picture timestamp
$asPicInfo = self::getPicInfo($sPicPath);
$iPicTimeStamp = $asPicInfo['timestamp'];
//Preparing pictures sorting key and related info
if( Settings::MODE != self::MODE_HISTO ||
($iPicTimeStamp >= strtotime(Settings::HISTO_SPAN['from']) && $iPicTimeStamp <= strtotime(Settings::HISTO_SPAN['to']))) {
$asPics[] = array(
'path' => $sPicPath,
'rotate' => $asPicInfo['rotate'],
'timestamp' => $iPicTimeStamp,
'formatted_time'=> date(self::FORMAT_TIME, $iPicTimeStamp),
'relative_time' => Toolbox::getDateTimeDesc($iPicTimeStamp)
);
}
}
return $asPics;
}
private function getPosts()
{
$asInfo = array('from'=>self::POST_TABLE);
if(Settings::MODE==self::MODE_HISTO) {
$asInfo['constraint'] = array('led'=>Settings::HISTO_SPAN);
$asInfo['constOpe'] = array('led'=>"BETWEEN");
}
$asPosts = $this->oDb->selectRows($asInfo);
foreach($asPosts as &$asPost) {
$iUnixTimeStamp = strtotime($asPost['led']);
$asPost['relative_time'] = Toolbox::getDateTimeDesc($iUnixTimeStamp);
$asPost['formatted_time'] = date(self::FORMAT_TIME, $iUnixTimeStamp);
$asPost['formatted_name'] = Toolbox::mb_ucwords($asPost['name']);
}
return $asPosts;
}
private static function getJsonId($iTimeStamp, $sPriority='0', $iDbId=0)
{
return ($iTimeStamp * -1).'.'.$sPriority.$iDbId;
}
public function getNewsFeed($iChunk=0)
{
$asFeed = array();
//Messages
$asMessages = $this->getSpotMessages();
foreach($asMessages as $asMessage)
{
$iMsgId = $asMessage[Db::getId(self::MSG_TABLE)];
$iId = self::getJsonId($asMessage['unix_timestamp'], '0', $iMsgId);
$asFeed[$iId] = $asMessage;
$asFeed[$iId]['type'] = 'message';
$asFeed[$iId]['displayed_id'] = $iMsgId;
}
//Pictures
$asPics = $this->getPictures();
foreach($asPics as $iKey=>$asPic)
{
$iId = self::getJsonId($asPic['timestamp'], '1', $iKey);
$asFeed[$iId] = $asPic;
$asFeed[$iId]['type'] = 'picture';
}
//Post
$asPosts = $this->getPosts();
foreach($asPosts as $asPost)
{
$iId = self::getJsonId(strtotime($asPost['led']), '2', $asPost[Db::getId(self::POST_TABLE)]);
$asFeed[$iId] = $asPost;
$asFeed[$iId]['type'] = 'post';
}
//Sort by key
ksort($asFeed);
//Split chunks
$asFeed = array_slice($asFeed, $iChunk*self::FEED_CHUNK_SIZE, self::FEED_CHUNK_SIZE);
return self::getJsonResult(true, '', $asFeed);
}
public function addPost($sName, $sPost)
{
$asData = array('name'=>mb_strtolower(trim($sName)), 'content'=>trim($sPost));
$iPostId = $this->oDb->insertRow(self::POST_TABLE, $asData);
return self::getJsonResult(($iPostId > 0), '');
}
public function upload()
{
$this->oClassManagement->incClass('uploader', true);
$oUploader = new Uploader(array('image_versions'=>array(), 'accept_file_types'=>'/\.(gif|jpe?g|png)$/i'));
$oUploader->init();
return $oUploader->getBody();
}
public static function getPicInfo($sPicPath)
{
$iPicTimeStamp = $iPicTakenTimeStamp = $iPicFileTimeStamp = 0;
$asExif = @exif_read_data($sPicPath, 0, true);
if(!$asExif) $asExif['FILE']['FileDateTime'] = filemtime($sPicPath);
//Timestamps
if(array_key_exists('EXIF', $asExif) && array_key_exists('DateTimeOriginal', $asExif['EXIF'])) $iPicTakenTimeStamp = strtotime($asExif['EXIF']['DateTimeOriginal']);
if(array_key_exists('FILE', $asExif) && array_key_exists('FileDateTime', $asExif['FILE'])) $iPicFileTimeStamp = $asExif['FILE']['FileDateTime'];
//Merge timestamps
$iPicTimeStamp = ($iPicTakenTimeStamp > 0)?$iPicTakenTimeStamp:$iPicFileTimeStamp;
//Time Zone
//if($iPicTimeStamp >= self::HONEYMOON_DATE_BEG && $iPicTimeStamp <= self::HONEYMOON_DATE_END) $iPicTimeStamp -= 60*60*(12+1); //timezone + daylight saving
//Orientation
if(array_key_exists('IFD0', $asExif) && array_key_exists('Orientation', $asExif['IFD0'])) {
switch($asExif['IFD0']['Orientation'])
{
case 1: $sRotate = '0'; break; //None
case 3: $sRotate = '180'; break; //Flip over
case 6: $sRotate = '90'; break; //Clockwise
case 8: $sRotate = '-90'; break; //Trigo
default: $sRotate = $asExif['IFD0']['Orientation'];
}
}
else $sRotate = '0';
return array(
'timestamp' => $iPicTimeStamp,
'taken_ts' => $iPicTimeStamp,
'file_ts' => $iPicTimeStamp,
'rotate' => $sRotate
);
}
}
?>