zeg1jeux/lib/Gchange.class.php

746 lines
14 KiB
PHP

<?php
/**
* https://github.com/duniter-gchange/gchange-pod/blob/master/src/site/markdown/REST_API.md
*/
require_once('DAO.class.php');
require_once('GchangeUser.class.php');
require_once('GchangeRecord.class.php');
require_once('GchangeRating.class.php');
require_once('ErrorsHandler.class.php');
class Gchange {
private $dao;
private $cacheDir = __DIR__ . '/../cache/';
private $isActivatedCache = true;
private $cacheLongevity = array(
'placesNearby' => 604800, // 3 jours
'placeDetails' => 2116800, // 7 jours
'placeVisitors' => 2116800, // 7 jours
'usersNearby' => 43200, // 12 heures
'users' => 2116800, // 12 heures
'userRecords' => 900 // 15 min
);
public function __construct () {
$this->dao = DAO::getInstance();
}
public function fetchJson ($uri, $queryParams = null) {
try {
$json = $this->dao->fetchJson($uri, 'gchange', $queryParams);
} catch (Exception $errorMsgs) {
throw $errorMsgs;
}
return $json;
}
private function getJsonFromCache ($dir, $file, $cacheLongevity = null) {
if (!$this->isActivatedCache) {
return NULL;
}
$json = null;
$jsonFullPath = $this->cacheDir . $dir . $file;
if (!file_exists($jsonFullPath)) {
throw new Exception("Le fichier de cache suivant n'existe pas : " . $jsonFullPath);
}
if ($cacheLongevity !== null and (time() - filemtime($jsonFullPath) > $cacheLongevity)) {
throw new Exception("Le fichier de cache est expiré.");
}
try {
$json = file_get_contents($jsonFullPath);
} catch (Exception $errorMsgs) {
throw new Exception($jsonFullPath . " n'a pas été trouvé");
} finally {
return $json;
}
}
private function cacheJson ($dir, $file, $json) {
if (!$this->isActivatedCache) {
return NULL;
}
$jsonCacheDir = $this->cacheDir . $dir;
$jsonFullPath = $jsonCacheDir . $file;
if (!file_exists($jsonCacheDir)) {
mkdir($jsonCacheDir, 0777, true);
}
file_put_contents($jsonFullPath, $json);
}
public function getUser ($pubkey) {
$usersCacheDir = 'users/';
$usersCacheFile = $pubkey . '.json';
try {
$json = $this->getJsonFromCache($usersCacheDir, $usersCacheFile, $this->cacheLongevity['users']);
} catch (Exception $errorMsgs) {
try {
$json = $this->fetchJson('/user/profile/'. $pubkey);
$this->cacheJson($usersCacheDir, $usersCacheFile, $json);
} catch (Exception $errorMsgs) {
try {
$json = $this->getJsonFromCache($usersCacheDir, $usersCacheFile, null);
} catch (Exception $errorMsgs) {
throw new Exception("L'utilisateur " . $pubkey . " n'a été trouvé nulle part.");
}
}
}
$result = json_decode($json);
return new GchangeUser($result);
}
public function getNearbyUsers ($lat, $lon, $maxDistance, $minDistance = NULL) {
$nearbyUsersCacheDir = 'users-nearby/geopoint/' . $maxDistance . 'km/';
$nearbyUsersCacheFile = $lat . ',' . $lon . '.json';
try {
$json = $this->getJsonFromCache($nearbyUsersCacheDir, $nearbyUsersCacheFile, $this->cacheLongevity['usersNearby']);
} catch (Exception $errorMsgs) {
$n = 20;
$queryParams = [
'size' => $n,
'query' => [
'bool' => [
'filter' => [
[
'geo_distance' => [
"distance" => $maxDistance . 'km',
"geoPoint"=> [
"lat" => $lat,
"lon" => $lon
]
]
]
]
]
]
];
try {
$json = $this->fetchJson('/users/record/_search', $queryParams);
$this->cacheJson($nearbyUsersCacheDir, $nearbyUsersCacheFile, $json);
} catch (Exception $errorMsgs) {
$json = $this->getJsonFromCache($nearbyUsersCacheDir, $nearbyUsersCacheFile, null);
}
}
$result = json_decode($json);
return $result->hits->hits;
}
public function getPlacesNearUser ($user, $radius, $maxPlacesNb) {
return $this->getNearbyPlaces($user->getLat(), $user->getLon(), $radius, null, $maxPlacesNb);
}
public function getNearbyPlaces ($lat, $lon, $maxDistance, $minDistance = NULL, $maxPlacesNb = 15) {
$placesCacheDir = 'places-nearby/geopoint/' . $maxDistance . 'km/';
$placesCacheFile = $lat . ',' . $lon . '.json';
$placeDetailsCacheDir = 'place/details/';
$nearbyPlaces = [];
try {
$json = $this->getJsonFromCache($placesCacheDir, $placesCacheFile, $this->cacheLongevity['placesNearby']);
$places = json_decode($json);
foreach ($places->hits->hits as $place) {
try {
$p = $this->getPlaceDetails($place->_id);
$nearbyPlaces[] = $p;
} catch (Exception $errorMsgs) {
// place not found
}
}
} catch (Exception $errorMsgs) {
try {
$n = (string) $maxPlacesNb;
$queryParams = [
'size' => $n,
'query' => [
'bool' => [
'filter' => [
[
'geo_distance' => [
"distance" => $maxDistance . 'km',
"geoPoint"=> [
"lat" => $lat,
"lon" => $lon
]
]
]
]
]
]
];
$json = $this->fetchJson('/page/record/_search', $queryParams);
$result = json_decode($json);
$resultClone = $this->filterIds($result);
// cache nearby places index
$this->cacheJson($placesCacheDir, $placesCacheFile, json_encode($resultClone));
// cache each nearby place details
// ob_get_clean();
// echo '<pre>'; print_r($resultClone); echo '</pre>';
// echo '<pre>'; print_r($result); echo '</pre>';
foreach ($result->hits->hits as $place) {
$nearbyPlaces[] = $place;
$placeDetailsCacheFile = $place->_id . '.json';
$this->cacheJson($placeDetailsCacheDir, $placeDetailsCacheFile, json_encode($place));
}
} catch (Exception $errorMsgs) {
try {
$json = $this->getJsonFromCache($placesCacheDir, $placesCacheFile, null);
$result = json_decode($json);
foreach ($result->hits->hits as $place) {
try {
$p = $this->getPlaceDetails($place->_id);
$nearbyPlaces[] = $p;
} catch (Exception $errorMsgs) {
// place not found
}
}
} catch (Exception $errorMsgs) {
throw new Exception('Pas pu récupérer la liste des lieux : ' . $errorMsgs);
}
}
}
return $nearbyPlaces;
}
private function filterIds ($r) {
// $result = clone $r;
$result = new stdClass;
$result->took = $r->took;
$result->timed_out = $r->timed_out;
$result->_shards = new stdClass;
$result->_shards->total = $r->_shards->total;
$result->_shards->successful = $r->_shards->successful;
$result->_shards->failed = $r->_shards->failed;
$result->hits = new stdClass;
$result->hits->total = $r->hits->total;
$result->hits->max_score = $r->hits->max_score;
$result->hits->hits = array();
$rHitsNb = count($r->hits->hits);
for ($i = 0; $i < $rHitsNb; $i++) {
$result->hits->hits[$i] = new stdClass;
$result->hits->hits[$i]->_id = $r->hits->hits[$i]->_id;
}
return $result;
}
/*
private function filterIds (&$item) {
$itemId = $item->_id;
$item = new stdClass;
$item->_id = $itemId;
}
*/
public function getPlaceDetails ($placeId) {
$placeDetailsCacheDir = 'place/details/';
$placeDetailsCacheFile = $placeId . '.json';
try {
$json = $this->getJsonFromCache($placeDetailsCacheDir, $placeDetailsCacheFile, $this->cacheLongevity['placeDetails']);
} catch (Exception $errorMsgs) {
try {
$json = $this->fetchJson('/page/record/' + $placeId);
$this->cacheJson($placeDetailsCacheDir, $placeDetailsCacheFile, $json);
} catch (Exception $errorMsgs) {
try {
$json = $this->getJsonFromCache($placeDetailsCacheDir, $placeDetailsCacheFile, null);
} catch (Exception $errorMsgs) {
throw new Exception('Pas pu trouver les détails pour la page ' . $placeId);
}
}
}
return json_decode($json);
}
/*
public function getNearbyRecords ($lat, $lon, $maxDistance, $minDistance = NULL) {
$n = 20;
$queryParams = [
'size' => $n,
'query' => [
'bool' => [
'must' => [
[
'geo_distance' => [
"distance" => $maxDistance . 'km',
"geoPoint"=> [
"lat" => $lat,
"lon" => $lon
]
]
], [
'range' => [
'stock' => [
'gte' => 1
]
]
]
]
]
]
];
$json = $this->fetchJson('/market/record/_search?pretty', $queryParams);
$result = json_decode($json);
$records = [];
foreach ($result->hits->hits as $hit) {
$records[] = new GchangeRecord($hit);
}
return $records;
}
*/
public function getUsersInDaPlace ($placeId) {
$users = [];
$cacheDir = 'place/visitors/';
$cacheFile = $placeId . '.json';
$usersCacheDir = 'users/';
try {
$json = $this->getJsonFromCache($cacheDir, $cacheFile, $this->cacheLongevity['placeVisitors']);
$result = json_decode($json);
foreach ($result->hits->hits as $hit) {
$user = null;
try {
$user = null;
$user = $this->getUser($hit->_id);
$users[] = $user;
} catch (Exception $errorMsgs) {
// Utilisateur non trouvé
}
}
} catch (Exception $errorMsgs) {
try {
$n = 20;
$queryParams = [
'size' => $n
// ,'fields' => ['_id']
,'query' => [
'nested' => [
'path' => 'socials',
'query' => [
'bool' => [
'filter' => [
'term' => [
'socials.url' => 'https://www.gchange.fr/#/app/page/view/'. $placeId .'/'
]
]
]
]
]
]
];
$json = $this->fetchJson('/user/profile/_search', $queryParams);
$result = json_decode($json);
foreach ($result->hits->hits as $hit) {
$user = new GchangeUser($hit);
$users[] = $user;
$this->cacheJson($usersCacheDir, $hit->_id . '.json', $user->jsonify());
}
} catch (Exception $errorMsgs) {
try {
$json = $this->getJsonFromCache($cacheDir, $cacheFile, null);
$result = json_decode($json);
foreach ($result->hits->hits as $hit) {
$user = null;
try {
$user = null;
$user = $this->getUser($hit->_id);
$users[] = $user;
} catch (Exception $errorMsgs) {
// Utilisateur non trouvé
}
}
} catch (Exception $errorMsgs) {
throw new Exception('Visiteurs trouvés nulle part.');
}
}
}
return $users;
}
public function getRecordsByIssuer ($issuer) {
$recordsCacheDir = 'records/user/';
$recordsCacheFile = $issuer . '.json';
try {
$json = $this->getJsonFromCache($recordsCacheDir, $recordsCacheFile, $this->cacheLongevity['userRecords']);
} catch (Exception $errorMsgs) {
try {
$n = 20;
$queryParams = [
'size' => $n,
'query' => [
'bool' => [
'filter' => [
'term' => [
'issuer' => $issuer
]
/*
, 'range' => [
'stock' => [
'gte' => 1
]
]
*/
]
/*
, 'filter' => [
]
*/
, 'must_not' => [
[ "term" => ["stock" => 0] ]
]
]
],
'sort' => [
['time' => 'desc']
]
];
$json = $this->fetchJson('/market/record/_search', $queryParams);
$this->cacheJson($recordsCacheDir, $recordsCacheFile, $json);
} catch (Exception $errorMsgs) {
try {
$json = $this->getJsonFromCache($recordsCacheDir, $recordsCacheFile, null);
} catch (Exception $errorMsgs) {
throw new Exception ("Aucune annonce trouvée pour l'utilisateur " . $issuer);
}
}
}
$result = json_decode($json);
$records = [];
foreach ($result->hits->hits as $hit) {
$records[] = new GchangeRecord($hit);
}
return $records;
}
public function getRatingsSentBy ($issuer) {
$n = 20;
$queryParams = [
'size' => $n,
'query' => [
'bool' => [
'must' => [
'term' => ['kind' => 'STAR']
],
'filter' => [
'term' => ['issuer' => $issuer]
]
]
]
];
$json = $this->fetchJson('/like/record/_search', $queryParams);
$result = json_decode($json);
$ratings = [];
foreach ($result->hits->hits as $hit) {
$ratings[] = new GchangeRating($hit);
}
return $ratings;
}
public function getRatingsReceivedBy ($receiver) {
$n = 20;
$queryParams = [
'size' => $n,
'query' => [
'bool' => [
'must' => [
'term' => ['kind' => 'STAR']
],
'filter' => [
'term' => ['id' => $receiver]
]
]
]
];
$json = $this->fetchJson('/like/record/_search', $queryParams);
$result = json_decode($json);
$ratings = [];
foreach ($result->hits->hits as $hit) {
$ratings[] = new GchangeRating($hit);
}
return $ratings;
}
public function getShippable () {
$n = 20;
$queryParams = [
'size' => $n,
'query' => [
'match' => [
'description' => 'envoi possible'
]
]
];
$json = $this->fetchJson('/market/record/_search?pretty', $queryParams);
$result = json_decode($json);
$records = [];
foreach ($result->hits->hits as $hit) {
$records[] = new GchangeRecord($hit);
}
return $records;
}
public function getImmaterialRecords () {
$n = 20;
$queryParams = [
'size' => $n,
'query' => [
'nested' => [
'path' => 'category',
'query' => [
'bool' => [
'should' => [
[ 'term' => [ 'category.parent' => 'cat31' ] ],
[ 'term' => [ 'category.id' => 'cat31' ] ],
[ 'term' => [ 'category.parent' => 'cat74' ] ],
[ 'term' => [ 'category.id' => 'cat74' ] ]
],
'must_not' => [
[ "term" => ["category.id" => "cat65"] ]
]
]
]
]
]
];
$json = $this->fetchJson('/market/record/_search?pretty', $queryParams);
$result = json_decode($json);
$records = [];
foreach ($result->hits->hits as $hit) {
$records[] = new GchangeRecord($hit);
}
return $records;
}
public function getHousingOffers () {
}
}