From 5c8381d29e2d4f08d3f34cdb007e24a22aee0e12 Mon Sep 17 00:00:00 2001 From: Bartek Fabiszewski Date: Sat, 2 Mar 2019 23:53:45 +0100 Subject: [PATCH] Fix issues in last position of all users, add tests, closes #9 --- .tests/tests/InternalAPITest.php | 95 +++++++++++++++++++++++++++---- .tests/tests/PositionTest.php | 32 +++++++++++ helpers/position.php | 62 +++++++-------------- js/api_gmaps.js | 17 ++++-- js/api_openlayers.js | 9 ++- js/main.js | 96 +++++++++++++++----------------- lang/en.php | 8 +-- utils/getpositions.php | 11 ++-- 8 files changed, 212 insertions(+), 118 deletions(-) diff --git a/.tests/tests/InternalAPITest.php b/.tests/tests/InternalAPITest.php index 94c0550..8828954 100644 --- a/.tests/tests/InternalAPITest.php +++ b/.tests/tests/InternalAPITest.php @@ -150,6 +150,87 @@ class InternalAPITest extends UloggerAPITestCase { $this->assertEquals((string) $position->trackname, $this->testTrackName, "Wrong trackname"); } + public function testGetPositionsUserLatest() { + $this->assertTrue($this->authenticate(), "Authentication failed"); + + $trackId = $this->addTestTrack($this->testUserId); + $this->addTestPosition($this->testUserId, $trackId, $this->testTimestamp); + $this->addTestPosition($this->testUserId, $trackId, $this->testTimestamp + 3); + $this->assertEquals(1, $this->getConnection()->getRowCount("tracks"), "Wrong row count"); + $this->assertEquals(2, $this->getConnection()->getRowCount("positions"), "Wrong row count"); + + $userId = $this->addTestUser($this->testUser, password_hash($this->testPass, PASSWORD_DEFAULT)); + $trackId2 = $this->addTestTrack($userId); + $this->addTestPosition($userId, $trackId2, $this->testTimestamp + 2); + $this->addTestPosition($userId, $trackId2, $this->testTimestamp + 1); + $this->assertEquals(2, $this->getConnection()->getRowCount("tracks"), "Wrong row count"); + $this->assertEquals(4, $this->getConnection()->getRowCount("positions"), "Wrong row count"); + + $options = [ + "http_errors" => false, + "query" => [ "userid" => $this->testUserId, "last" => 1 ], + ]; + $response = $this->http->get("/utils/getpositions.php", $options); + $this->assertEquals(200, $response->getStatusCode(), "Unexpected status code"); + + $xml = $this->getXMLfromResponse($response); + $this->assertTrue($xml !== false, "XML object is false"); + $this->assertEquals($xml->position->count(), 1, "Wrong count of positions"); + + $position = $xml->position[0]; + $this->assertEquals((int) $position["id"], 2, "Wrong position id"); + $this->assertEquals((float) $position->latitude, $this->testLat, "Wrong latitude"); + $this->assertEquals((float) $position->longitude, $this->testLon, "Wrong longitude"); + $this->assertEquals((int) $position->timestamp, $this->testTimestamp + 3, "Wrong timestamp"); + $this->assertEquals((string) $position->username, $this->testAdminUser, "Wrong username"); + $this->assertEquals((string) $position->trackname, $this->testTrackName, "Wrong trackname"); + } + + public function testGetPositionsAllUsersLatest() { + $this->assertTrue($this->authenticate(), "Authentication failed"); + $userId = $this->addTestUser($this->testUser, password_hash($this->testPass, PASSWORD_DEFAULT)); + + $trackId = $this->addTestTrack($this->testUserId); + $this->addTestPosition($this->testUserId, $trackId, $this->testTimestamp); + $this->addTestPosition($this->testUserId, $trackId, $this->testTimestamp + 3); + $this->assertEquals(1, $this->getConnection()->getRowCount("tracks"), "Wrong row count"); + $this->assertEquals(2, $this->getConnection()->getRowCount("positions"), "Wrong row count"); + + $trackName = "Track 2"; + $trackId2 = $this->addTestTrack($userId, $trackName); + $this->addTestPosition($userId, $trackId2, $this->testTimestamp + 2); + $this->addTestPosition($userId, $trackId2, $this->testTimestamp + 1); + $this->assertEquals(2, $this->getConnection()->getRowCount("tracks"), "Wrong row count"); + $this->assertEquals(4, $this->getConnection()->getRowCount("positions"), "Wrong row count"); + + $options = [ + "http_errors" => false, + "query" => [ "last" => 1 ], + ]; + $response = $this->http->get("/utils/getpositions.php", $options); + $this->assertEquals(200, $response->getStatusCode(), "Unexpected status code"); + + $xml = $this->getXMLfromResponse($response); + $this->assertTrue($xml !== false, "XML object is false"); + $this->assertEquals($xml->position->count(), 2, "Wrong count of positions"); + + $position = $xml->position[0]; + $this->assertEquals((int) $position["id"], 2, "Wrong position id"); + $this->assertEquals((float) $position->latitude, $this->testLat, "Wrong latitude"); + $this->assertEquals((float) $position->longitude, $this->testLon, "Wrong longitude"); + $this->assertEquals((int) $position->timestamp, $this->testTimestamp + 3, "Wrong timestamp"); + $this->assertEquals((string) $position->username, $this->testAdminUser, "Wrong username"); + $this->assertEquals((string) $position->trackname, $this->testTrackName, "Wrong trackname"); + + $position = $xml->position[1]; + $this->assertEquals((int) $position["id"], 3, "Wrong position id"); + $this->assertEquals((float) $position->latitude, $this->testLat, "Wrong latitude"); + $this->assertEquals((float) $position->longitude, $this->testLon, "Wrong longitude"); + $this->assertEquals((int) $position->timestamp, $this->testTimestamp + 2, "Wrong timestamp"); + $this->assertEquals((string) $position->username, $this->testUser, "Wrong username"); + $this->assertEquals((string) $position->trackname, $trackName, "Wrong trackname"); + } + public function testGetPositionsNoTrackId() { $this->assertTrue($this->authenticate(), "Authentication failed"); @@ -169,15 +250,7 @@ class InternalAPITest extends UloggerAPITestCase { $xml = $this->getXMLfromResponse($response); $this->assertTrue($xml !== false, "XML object is false"); - $this->assertEquals($xml->position->count(), 1, "Wrong count of positions"); - - $position = $xml->position[0]; - $this->assertEquals((int) $position["id"], 2, "Wrong position id"); - $this->assertEquals((float) $position->latitude, $this->testLat, "Wrong latitude"); - $this->assertEquals((float) $position->longitude, $this->testLon, "Wrong longitude"); - $this->assertEquals((int) $position->timestamp, $this->testTimestamp + 1, "Wrong timestamp"); - $this->assertEquals((string) $position->username, $this->testAdminUser, "Wrong username"); - $this->assertEquals((string) $position->trackname, $this->testTrackName, "Wrong trackname"); + $this->assertEquals(0, $xml->position->count(), "Wrong count of positions"); } public function testGetPositionsNoUserId() { @@ -199,8 +272,8 @@ class InternalAPITest extends UloggerAPITestCase { $xml = $this->getXMLfromResponse($response); - $this->assertTrue($xml !== false, "XML object is not false"); - $this->assertEquals($xml->position->count(), 0, "Wrong count of positions"); + $this->assertTrue($xml !== false, "XML object is false"); + $this->assertEquals(0, $xml->position->count(), "Wrong count of positions"); } public function testGetPositionsNoAuth() { diff --git a/.tests/tests/PositionTest.php b/.tests/tests/PositionTest.php index 1aebb2b..72bf59f 100644 --- a/.tests/tests/PositionTest.php +++ b/.tests/tests/PositionTest.php @@ -106,6 +106,38 @@ class PositionTest extends UloggerDatabaseTestCase { $this->assertEquals($lastPosition->id, $pos4, "Wrong last position (user)"); } + public function testGetLastAllUsers() { + $userId = $this->addTestUser(); + $userId2 = $this->addTestUser($this->testUser2); + $trackId1 = $this->addTestTrack($userId); + $trackId2 = $this->addTestTrack($userId); + $pos1 = $this->addTestPosition($userId, $trackId1, $this->testTimestamp + 3); + $pos2 = $this->addTestPosition($userId2, $trackId2, $this->testTimestamp + 1); + $pos3 = $this->addTestPosition($userId, $trackId1, $this->testTimestamp); + $pos4 = $this->addTestPosition($userId2, $trackId2, $this->testTimestamp + 2); + $this->assertEquals(2, $this->getConnection()->getRowCount('tracks'), "Wrong row count"); + $this->assertEquals(4, $this->getConnection()->getRowCount('positions'), "Wrong row count"); + $posArr = uPosition::getLastAllUsers(); + $this->assertEquals(2, count($posArr), "Wrong row count"); + foreach ($posArr as $position) { + /** @var uPosition $position */ + switch ($position->id) { + case 1: + $this->assertEquals($this->testTimestamp + 3, $position->timestamp); + $this->assertEquals($userId, $position->userId); + $this->assertEquals($trackId1, $position->trackId); + break; + case 4: + $this->assertEquals($this->testTimestamp + 2, $position->timestamp); + $this->assertEquals($userId2, $position->userId); + $this->assertEquals($trackId2, $position->trackId); + break; + default: + $this->assert("Unexpected position: {$position->id}"); + } + } + } + public function testGetAll() { $userId = $this->addTestUser(); $userId2 = $this->addTestUser($this->testUser2); diff --git a/helpers/position.php b/helpers/position.php index b9d7149..08e43f3 100644 --- a/helpers/position.php +++ b/helpers/position.php @@ -202,54 +202,34 @@ return $position; } - /** - * Get last position data from database - * (for all users) + /** + * Get last positions for all users * * @return array|bool Array of uPosition positions, false on error */ public static function getLastAllUsers() { - $query = "SELECT - p.id, - UNIX_TIMESTAMP(p.time) AS tstamp, - p.user_id, - p.track_id, - p.latitude, - p.longitude, - p.altitude, - p.speed, - p.bearing, - p.accuracy, - p.provider, - p.comment, - p.image_id, - u.login - FROM - " . self::db()->table('positions') . " p - LEFT JOIN " . self::db()->table('users') . " u - ON ( p.user_id = u.id ) + $query = "SELECT p.id, " . self::db()->unix_timestamp('p.time') . " AS tstamp, p.user_id, p.track_id, + p.latitude, p.longitude, p.altitude, p.speed, p.bearing, p.accuracy, p.provider, + p.comment, p.image_id, u.login, t.name + FROM " . self::db()->table('positions') . " p + LEFT JOIN " . self::db()->table('users') . " u ON (p.user_id = u.id) + LEFT JOIN " . self::db()->table('tracks') . " t ON (p.track_id = t.id) WHERE p.id = ( - SELECT - p2.id - FROM - " . self::db()->table('positions') . " p2 - WHERE - p2.user_id = p.user_id - ORDER BY - p2.time DESC, - p2.id DESC - LIMIT 1 + SELECT p2.id FROM " . self::db()->table('positions') . " p2 + WHERE p2.user_id = p.user_id + ORDER BY p2.time DESC, p2.id DESC + LIMIT 1 )"; - - $result = self::db()->query($query); - if ($result === false) { - return false; - } $positionsArr = []; - while ($row = $result->fetch_assoc()) { - $positionsArr[] = self::rowToObject($row); + try { + $result = self::db()->query($query); + while ($row = $result->fetch()) { + $positionsArr[] = self::rowToObject($row); + } + } catch (PDOException $e) { + // TODO: handle exception + syslog(LOG_ERR, $e->getMessage()); } - $result->close(); return $positionsArr; } @@ -281,8 +261,8 @@ LEFT JOIN " . self::db()->table('tracks') . " t ON (p.track_id = t.id) $where ORDER BY p.time, p.id"; + $positionsArr = []; try { - $positionsArr = []; $result = self::db()->query($query); while ($row = $result->fetch()) { $positionsArr[] = self::rowToObject($row); diff --git a/js/api_gmaps.js b/js/api_gmaps.js index 0974ac1..76390e4 100755 --- a/js/api_gmaps.js +++ b/js/api_gmaps.js @@ -68,9 +68,9 @@ function displayTrack(xml, update) { var p = parsePosition(positions[i], i); totalMeters += p.distance; totalSeconds += p.seconds; - p['totalMeters'] = totalMeters; - p['totalSeconds'] = totalSeconds; - p['coordinates'] = new google.maps.LatLng(p.latitude, p.longitude); + p.totalMeters = totalMeters; + p.totalSeconds = totalSeconds; + p.coordinates = new google.maps.LatLng(p.latitude, p.longitude); // set marker setMarker(p, i, posLen); // update polyline @@ -126,7 +126,7 @@ function setMarker(p, i, posLen) { // marker var marker = new google.maps.Marker({ map: map, - position: p.coordinates, + position: new google.maps.LatLng(p.latitude, p.longitude), title: (new Date(p.timestamp * 1000)).toLocaleString() }); if (latest == 1) { marker.setIcon('images/marker-red.png') } @@ -179,6 +179,15 @@ function getBounds() { return [lon_sw, lat_sw, lon_ne, lat_ne]; } +function zoomToExtent() { + var latlngbounds = new google.maps.LatLngBounds(); + for (var i = 0; i < markers.length; i++) { + var coordinates = new google.maps.LatLng(markers[i].position.lat(), markers[i].position.lng()); + latlngbounds.extend(coordinates); + } + map.fitBounds(latlngbounds); +} + function zoomToBounds(b) { var sw = new google.maps.LatLng(b[1], b[0]); var ne = new google.maps.LatLng(b[3], b[2]); diff --git a/js/api_openlayers.js b/js/api_openlayers.js index 248c673..dd9e808 100755 --- a/js/api_openlayers.js +++ b/js/api_openlayers.js @@ -290,6 +290,7 @@ function cleanup() { document.getElementById('map-canvas').innerHTML = ''; } + function displayTrack(xml, update) { altitudes = {}; var totalMeters = 0; @@ -301,8 +302,8 @@ function displayTrack(xml, update) { var p = parsePosition(positions[i], i); totalMeters += p.distance; totalSeconds += p.seconds; - p['totalMeters'] = totalMeters; - p['totalSeconds'] = totalSeconds; + p.totalMeters = totalMeters; + p.totalSeconds = totalSeconds; // set marker setMarker(p, i, posLen); // update polyline @@ -409,6 +410,10 @@ function getBounds() { return [lon_sw, lat_sw, lon_ne, lat_ne]; } +function zoomToExtent() { + map.getView().fit(layerMarkers.getSource().getExtent()) +} + function zoomToBounds(b) { var bounds = ol.proj.transformExtent(b, 'EPSG:4326', 'EPSG:900913'); map.getView().fit(bounds); diff --git a/js/main.js b/js/main.js index aa996b1..f92da4f 100755 --- a/js/main.js +++ b/js/main.js @@ -134,16 +134,6 @@ function getXHR() { return xmlhttp; } -function reload(userid, trackid){ - var usersSelect = document.getElementsByName('user')[0]; - if (usersSelect[usersSelect.selectedIndex].text == lang['allusers']) { - loadLastPositionAllUsers(); - } - else{ - loadTrack(userid, trackid, 0); - } -} - function loadTrack(userid, trackid, update) { var title = document.getElementById('track').getElementsByClassName('menutitle')[0]; if (trackid < 0) { return; } @@ -170,7 +160,6 @@ function loadTrack(userid, trackid, update) { } function loadLastPositionAllUsers() { - if (latest == 1) { trackid = 0; } var xhr = getXHR(); xhr.onreadystatechange = function () { if (xhr.readyState == 4) { @@ -179,16 +168,22 @@ function loadLastPositionAllUsers() { var xml = xhr.responseXML; var positions = xml.getElementsByTagName('position'); var posLen = positions.length; + var timestampMax = 0; for (var i = 0; i < posLen; i++) { var p = parsePosition(positions[i], i); // set marker setMarker(p, i, posLen); + if (p.timestamp > timestampMax) { + timestampMax = p.timestamp; + } } + zoomToExtent(); + updateSummary(timestampMax); } xhr = null; } } - xhr.open('GET', 'utils/getpositions.php?trackid=' + trackid + '&userid=' + userid + '&last=' + latest, true); + xhr.open('GET', 'utils/getpositions.php?last=' + latest, true); xhr.send(); } @@ -264,15 +259,6 @@ function getPopupHtml(p, i, count) { '' + lang['tdistance'] + ' ' + (p.totalMeters.toKm() * factor_km).toFixed(2) + ' ' + unit_km + '
' + ''; } - if (p.username == null){ - p.username = lang["nousername"]; - } - if (p.trackname == null){ - p.trackname = lang["notrackname"]; - } - if (p.comments == null){ - p.comments = lang["nocomment"]; - } var popup = '