Merge branch 'master' into ES6

This commit is contained in:
Bartek Fabiszewski 2019-05-23 11:14:41 +02:00
commit 3dd5c14273
17 changed files with 262 additions and 74 deletions

View File

@ -10,8 +10,13 @@ chown nginx:nginx /run/nginx
sed -i "s/^nobody:.*$/nobody:x:1000:50::nobody:\/:\/sbin\/nologin/" /etc/passwd sed -i "s/^nobody:.*$/nobody:x:1000:50::nobody:\/:\/sbin\/nologin/" /etc/passwd
sed -i "s/^nobody:.*$/nobody:x:50:/" /etc/group sed -i "s/^nobody:.*$/nobody:x:50:/" /etc/group
sed -i "s/^\$dbuser = .*$/\$dbuser = \"ulogger\";/" /var/www/html/config.php if [ "$ULOGGER_DB_DRIVER" = "sqlite" ]; then
sed -i "s/^\$dbpass = .*$/\$dbpass = \"${DB_USER_PASS}\";/" /var/www/html/config.php sed -i "s/^\$dbuser = .*$//" /var/www/html/config.php
sed -i "s/^\$dbpass = .*$//" /var/www/html/config.php
else
sed -i "s/^\$dbuser = .*$/\$dbuser = \"ulogger\";/" /var/www/html/config.php
sed -i "s/^\$dbpass = .*$/\$dbpass = \"${DB_USER_PASS}\";/" /var/www/html/config.php
fi
if [ "$ULOGGER_DB_DRIVER" = "pgsql" ]; then if [ "$ULOGGER_DB_DRIVER" = "pgsql" ]; then
export PGDATA=/data export PGDATA=/data

17
.github/stale.yml vendored Normal file
View File

@ -0,0 +1,17 @@
# Number of days of inactivity before an issue becomes stale
daysUntilStale: 60
# Number of days of inactivity before a stale issue is closed
daysUntilClose: 7
# Issues with these labels will never be considered stale
exemptLabels:
- pinned
- security
# Label to use when marking an issue as stale
staleLabel: wontfix
# Comment to post when marking an issue as stale. Set to `false` to disable
markComment: >
This issue has been automatically marked as stale because it has not had
recent activity. It will be closed if no further activity occurs. Thank you
for your contributions.
# Comment to post when closing a stale issue. Set to `false` to disable
closeComment: false

View File

@ -35,8 +35,8 @@ class UloggerAPITestCase extends BaseDatabaseTestCase {
/** /**
* Authenticate on server * Authenticate on server
* @param string $user Login * @param string|null $user Login (defaults to test user)
* * @param string|null $pass Optional password (defaults to test password)
* @return bool true on success, false otherwise * @return bool true on success, false otherwise
*/ */
public function authenticate($user = NULL, $pass = NULL) { public function authenticate($user = NULL, $pass = NULL) {

63
.tests/tests/DbTest.php Normal file
View File

@ -0,0 +1,63 @@
<?php
use PHPUnit\Framework\TestCase;
if (!defined("ROOT_DIR")) { define("ROOT_DIR", __DIR__ . "/../.."); }
require_once(__DIR__ . "/../../helpers/db.php");
class DbTest extends TestCase {
public function testGetDbNameValidNames() {
$testDbName = "testDbName";
$defaultDSNs = [
"mysql:host=db.example.com;port=3306;dbname=$testDbName",
"mysql:host=db.example.com;dbname=$testDbName;port=3306",
"mysql:dbname=$testDbName;host=db.example.com;port=3306",
"mysql:unix_socket=/tmp/mysql.sock;dbname=$testDbName;charset=utf8",
"pgsql:host=localhost;port=5432;dbname=$testDbName;user=myuser;password=mypass",
"pgsql:host=db.example.com port=31075 dbname=$testDbName",
"pgsql:host=db.example.com port=31075 dbname=$testDbName user=myuser password=mypass",
"sqlite:$testDbName",
"sqlite2:$testDbName",
"sqlite3:$testDbName"
];
foreach ($defaultDSNs as $dsn) {
$this->assertEquals($testDbName, uDb::getDbName($dsn));
}
}
public function testGetDbNameEmptyNames() {
$testDbName = "";
$defaultDSNs = [
"mysql:host=db.example.com;port=3306;dbname=",
"mysql:host=db.example.com;port=3306",
"",
null,
"unsupported:host=localhost;port=5432;dbname=;user=test;password=mypass",
"corrupt",
"pgsql:",
"sqlite",
"sqlite3",
"sqlite:"
];
foreach ($defaultDSNs as $dsn) {
$this->assertEquals($testDbName, uDb::getDbName($dsn));
}
}
public function testGetDbFilename() {
$testFileNames = [
"C:\\Program Files\\Database.db",
":memory:",
"/tmp/testdb.db3"
];
foreach ($testFileNames as $fileName) {
$this->assertEquals($fileName, uDb::getDbName("sqlite:$fileName"));
}
}
}
?>

View File

@ -1,5 +1,7 @@
<?php <?php
use Psr\Http\Message\ResponseInterface;
require_once(__DIR__ . "/../lib/UloggerAPITestCase.php"); require_once(__DIR__ . "/../lib/UloggerAPITestCase.php");
if (!defined("ROOT_DIR")) { define("ROOT_DIR", __DIR__ . "/../.."); } if (!defined("ROOT_DIR")) { define("ROOT_DIR", __DIR__ . "/../.."); }
require_once(ROOT_DIR . "/helpers/config.php"); require_once(ROOT_DIR . "/helpers/config.php");
@ -788,7 +790,10 @@ class ImportTest extends UloggerAPITestCase {
$this->assertEquals(0, $this->getConnection()->getRowCount("positions"), "Wrong row count"); $this->assertEquals(0, $this->getConnection()->getRowCount("positions"), "Wrong row count");
} }
/**
* @param ResponseInterface $response
* @return bool|SimpleXMLElement
*/
private function getXMLfromResponse($response) { private function getXMLfromResponse($response) {
$xml = false; $xml = false;
libxml_use_internal_errors(true); libxml_use_internal_errors(true);

View File

@ -1,5 +1,7 @@
<?php <?php
use Psr\Http\Message\ResponseInterface;
require_once(__DIR__ . "/../lib/UloggerAPITestCase.php"); require_once(__DIR__ . "/../lib/UloggerAPITestCase.php");
if (!defined("ROOT_DIR")) { define("ROOT_DIR", __DIR__ . "/../.."); } if (!defined("ROOT_DIR")) { define("ROOT_DIR", __DIR__ . "/../.."); }
require_once(ROOT_DIR . "/helpers/config.php"); require_once(ROOT_DIR . "/helpers/config.php");
@ -990,7 +992,10 @@ class InternalAPITest extends UloggerAPITestCase {
$this->assertEquals(1, $this->getConnection()->getRowCount("users"), "Wrong row count"); $this->assertEquals(1, $this->getConnection()->getRowCount("users"), "Wrong row count");
} }
/**
* @param ResponseInterface $response
* @return bool|SimpleXMLElement
*/
private function getXMLfromResponse($response) { private function getXMLfromResponse($response) {
$xml = false; $xml = false;
libxml_use_internal_errors(true); libxml_use_internal_errors(true);

View File

@ -133,7 +133,7 @@ class PositionTest extends UloggerDatabaseTestCase {
$this->assertEquals($trackId2, $position->trackId); $this->assertEquals($trackId2, $position->trackId);
break; break;
default: default:
$this->assert("Unexpected position: {$position->id}"); $this->assertTrue(false, "Unexpected position: {$position->id}");
} }
} }
} }

View File

@ -0,0 +1,49 @@
<?php
require_once(__DIR__ . "/../lib/UloggerAPITestCase.php");
class SetupTest extends UloggerAPITestCase {
private $script = "/scripts/setup.php";
public function testPrePhase() {
$response = $this->http->get($this->script);
$this->assertEquals(200, $response->getStatusCode(), "Unexpected status code");
$body = (string) $response->getBody();
$this->assertContains("<input type=\"hidden\" name=\"command\" value=\"setup\">", $body);
}
public function testSetupPhase() {
$options = [
"http_errors" => false,
"form_params" => [ "command" => "setup" ]
];
$response = $this->http->post($this->script, $options);
$this->assertEquals(200, $response->getStatusCode(), "Unexpected status code");
$body = (string) $response->getBody();
$this->assertContains("<input type=\"hidden\" name=\"command\" value=\"adduser\">", $body);
}
public function testAdduserPhase() {
$options = [
"http_errors" => false,
"form_params" => [
"command" => "adduser",
"login" => $this->testUser,
"pass" => $this->testPass,
"pass2" => $this->testPass
]
];
$response = $this->http->post($this->script, $options);
$this->assertEquals(200, $response->getStatusCode(), "Unexpected status code");
$body = (string) $response->getBody();
$this->assertContains("<span class=\"ok\">", $body);
$this->assertEquals(2, $this->getConnection()->getRowCount("users"), "Wrong row count");
$expected = [ "id" => 2, "login" => $this->testUser ];
$actual = $this->getConnection()->createQueryTable("users", "SELECT id, login FROM users WHERE id = 2");
$this->assertTableContains($expected, $actual, "Wrong actual table data");
$this->assertTrue(password_verify($this->testPass, $this->pdoGetColumn("SELECT password FROM users WHERE id = 2")), "Wrong actual password hash");
}
}
?>

View File

@ -3,7 +3,9 @@
"ulrichsg/getopt-php": "^3.2", "ulrichsg/getopt-php": "^3.2",
"ext-json": "*", "ext-json": "*",
"ext-pdo": "*", "ext-pdo": "*",
"ext-xmlwriter": "*" "ext-xmlwriter": "*",
"ext-simplexml": "*",
"ext-libxml": "*"
}, },
"scripts": { "scripts": {
"test": "./vendor/bin/phpunit" "test": "./vendor/bin/phpunit"
@ -13,6 +15,5 @@
"vlucas/phpdotenv": "^3.3", "vlucas/phpdotenv": "^3.3",
"guzzlehttp/guzzle": "^6.3", "guzzlehttp/guzzle": "^6.3",
"phpunit/dbunit": "^2.0" "phpunit/dbunit": "^2.0"
} }
} }

View File

@ -29,7 +29,7 @@
/** @var bool Is user authenticated */ /** @var bool Is user authenticated */
private $isAuthenticated = false; private $isAuthenticated = false;
/** @var uUser|null User */ /** @var null|uUser */
public $user = null; public $user = null;
public function __construct() { public function __construct() {
@ -107,9 +107,11 @@
} }
/** /**
* Process log in request * Check valid pass for given login
* *
* @return boolean * @param $login
* @param $pass
* @return boolean True if valid
*/ */
public function checkLogin($login, $pass) { public function checkLogin($login, $pass) {
if (!is_null($login) && !is_null($pass)) { if (!is_null($login) && !is_null($pass)) {

View File

@ -101,6 +101,11 @@
return self::$tables[$name]; return self::$tables[$name];
} }
/**
* Returns function name for getting date-time column value as unix timestamp
* @param string $column
* @return string
*/
public function unix_timestamp($column) { public function unix_timestamp($column) {
switch (self::$driver) { switch (self::$driver) {
default: default:
@ -116,6 +121,11 @@
} }
} }
/**
* Returns function name for getting date-time column value as 'YYYY-MM-DD hh:mm:ss'
* @param string $column
* @return string
*/
public function from_unixtime($column) { public function from_unixtime($column) {
switch (self::$driver) { switch (self::$driver) {
default: default:
@ -131,10 +141,44 @@
} }
} }
/**
* Set character set
* @param string $charset
*/
private function setCharset($charset) { private function setCharset($charset) {
if (self::$driver == "pgsql" || self::$driver == "mysql") { if (self::$driver == "pgsql" || self::$driver == "mysql") {
$this->query("SET NAMES '$charset'"); $this->query("SET NAMES '$charset'");
} }
} }
/**
* Extract database name from DSN
* @param string $dsn
* @return string Empty string if not found
*/
static public function getDbName($dsn) {
$name = "";
if (strpos($dsn, ":") !== false) {
list($scheme, $dsnWithoutScheme) = explode(":", $dsn, 2);
switch ($scheme) {
case "sqlite":
case "sqlite2":
case "sqlite3":
$pattern = "/(.+)/";
break;
case "pgsql":
$pattern = "/dbname=([^; ]+)/";
break;
default:
$pattern = "/dbname=([^;]+)/";
break;
}
$result = preg_match($pattern, $dsnWithoutScheme, $matches);
if ($result === 1) {
$name = $matches[1];
}
}
return $name;
}
} }
?> ?>

View File

@ -57,8 +57,6 @@
public $isValid = false; public $isValid = false;
private static $db;
/** /**
* Constructor * Constructor
* @param integer $positionId Position id * @param integer $positionId Position id

View File

@ -31,11 +31,6 @@
public $isValid = false; public $isValid = false;
/**
* @var uDb $db
*/
private static $db = null;
/** /**
* Constructor * Constructor
* *

View File

@ -34,8 +34,6 @@
public $isAdmin = false; public $isAdmin = false;
public $isValid = false; public $isValid = false;
private static $db = null;
/** /**
* Constructor * Constructor
* *

View File

@ -47,7 +47,7 @@ $getopt->addOptions([
Option::create('h', 'help') Option::create('h', 'help')
->setDescription('Show usage/help'), ->setDescription('Show usage/help'),
Option::create('u', 'user-id', \GetOpt\GetOpt::OPTIONAL_ARGUMENT) Option::create('u', 'user-id', GetOpt::OPTIONAL_ARGUMENT)
->setDescription('Which user to import the track(s) for (default: 1)') ->setDescription('Which user to import the track(s) for (default: 1)')
->setDefaultValue(1) ->setDefaultValue(1)
->setValidation('is_numeric', '%s has to be an integer'), ->setValidation('is_numeric', '%s has to be an integer'),
@ -60,7 +60,7 @@ $getopt->addOptions([
]); ]);
$getopt->addOperand( $getopt->addOperand(
Operand::create('gpx', \GetOpt\Operand::MULTIPLE + \GetOpt\Operand::REQUIRED) Operand::create('gpx', Operand::MULTIPLE + Operand::REQUIRED)
->setDescription('One or more GPX files to import') ->setDescription('One or more GPX files to import')
->setValidation('is_readable', '%s: %s is not readable') ->setValidation('is_readable', '%s: %s is not readable')
); );

View File

@ -24,50 +24,52 @@ $enabled = false;
/* -------------------------------------------- */ /* -------------------------------------------- */
/* no user modifications should be needed below */ /* no user modifications should be needed below */
if (version_compare(PHP_VERSION, '5.4.0', '<')) { if (version_compare(PHP_VERSION, "5.4.0", "<")) {
die("Sorry, ulogger will not work with PHP version lower than 5.4 (you have " . PHP_VERSION . ")"); die("Sorry, ulogger will not work with PHP version lower than 5.4 (you have " . PHP_VERSION . ")");
} }
define("ROOT_DIR", dirname(__DIR__)); define("ROOT_DIR", dirname(__DIR__));
require_once(ROOT_DIR . "/helpers/user.php"); require_once(ROOT_DIR . "/helpers/db.php");
require_once(ROOT_DIR . "/helpers/config.php"); require_once(ROOT_DIR . "/helpers/config.php");
require_once(ROOT_DIR . "/helpers/utils.php");
require_once(ROOT_DIR . "/helpers/lang.php"); require_once(ROOT_DIR . "/helpers/lang.php");
require_once(ROOT_DIR . "/helpers/user.php");
require_once(ROOT_DIR . "/helpers/utils.php");
$command = uUtils::postString('command'); $command = uUtils::postString("command");
$lang = (new uLang(uConfig::$lang))->getStrings(); $lang = (new uLang(uConfig::$lang))->getStrings();
$langSetup = (new uLang(uConfig::$lang))->getSetupStrings(); $langSetup = (new uLang(uConfig::$lang))->getSetupStrings();
$prefix = preg_replace('/[^a-z0-9_]/i', '', uConfig::$dbprefix); $prefix = preg_replace("/[^a-z0-9_]/i", "", uConfig::$dbprefix);
$tPositions = $prefix . "positions"; $tPositions = $prefix . "positions";
$tTracks = $prefix . "tracks"; $tTracks = $prefix . "tracks";
$tUsers = $prefix . "users"; $tUsers = $prefix . "users";
$dbDriver = null;
$messages = []; $messages = [];
switch ($command) { switch ($command) {
case "setup": case "setup":
$error = false; $error = false;
try { try {
$options = [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION ]; $pdo = getPdo();
$pdo = new PDO(uConfig::$dbdsn, uConfig::$dbuser, uConfig::$dbpass, $options);
$dbDriver = $pdo->getAttribute(PDO::ATTR_DRIVER_NAME);
} catch (PDOException $e) { } catch (PDOException $e) {
$messages[] = "<span class=\"warn\">{$langSetup["dbconnectfailed"]}</span>"; $messages[] = "<span class=\"warn\">{$langSetup["dbconnectfailed"]}</span>";
$messages[] = sprintf($langSetup["serversaid"], "<b>" . $e->getMessage() . "</b>"); $messages[] = sprintf($langSetup["serversaid"], "<b>" . htmlentities($e->getMessage()) . "</b>");
$messages[] = $langSetup["checkdbsettings"]; $messages[] = $langSetup["checkdbsettings"];
break; break;
} }
try { try {
$queries = getQueries(); $queries = getQueries($pdo->getAttribute(PDO::ATTR_DRIVER_NAME));
$pdo->beginTransaction();
foreach ($queries as $query) { foreach ($queries as $query) {
$pdo->query($query); $pdo->query($query);
} }
$pdo->commit();
} catch (PDOException $e) { } catch (PDOException $e) {
$pdo->rollBack();
$messages[] = "<span class=\"warn\">{$langSetup["dbqueryfailed"]}</span>"; $messages[] = "<span class=\"warn\">{$langSetup["dbqueryfailed"]}</span>";
$messages[] = sprintf($langSetup["serversaid"], "<b>" . $e->getMessage() . "</b>"); $messages[] = sprintf($langSetup["serversaid"], "<b>" . htmlentities($e->getMessage()) . "</b>");
$error = true; $error = true;
} }
$pdo = null; $pdo = null;
@ -85,8 +87,8 @@ switch ($command) {
break; break;
case "adduser": case "adduser":
$login = uUtils::postString('login'); $login = uUtils::postString("login");
$pass = uUtils::postPass('pass'); $pass = uUtils::postPass("pass");
if (uUser::add($login, $pass) !== false) { if (uUser::add($login, $pass) !== false) {
$messages[] = "<span class=\"ok\">{$langSetup["congratulations"]}</span>"; $messages[] = "<span class=\"ok\">{$langSetup["congratulations"]}</span>";
@ -107,7 +109,7 @@ switch ($command) {
$messages[] = "<form method=\"post\" action=\"setup.php\"><button>{$langSetup["restartbutton"]}</button></form>"; $messages[] = "<form method=\"post\" action=\"setup.php\"><button>{$langSetup["restartbutton"]}</button></form>";
break; break;
} }
if (!function_exists('password_hash')) { if (!function_exists("password_hash")) {
$messages[] = $langSetup["passfuncwarn"]; $messages[] = $langSetup["passfuncwarn"];
$messages[] = $langSetup["passfunchack"]; $messages[] = $langSetup["passfunchack"];
$messages[] = sprintf($langSetup["lineshouldread"], "<br><span class=\"warn\">//require_once(ROOT_DIR . \"/helpers/password.php\");</span><br>", "<br><span class=\"ok\">require_once(ROOT_DIR . \"/helpers/password.php\");</span>"); $messages[] = sprintf($langSetup["lineshouldread"], "<br><span class=\"warn\">//require_once(ROOT_DIR . \"/helpers/password.php\");</span><br>", "<br><span class=\"ok\">require_once(ROOT_DIR . \"/helpers/password.php\");</span>");
@ -121,18 +123,7 @@ switch ($command) {
$messages[] = "<form method=\"post\" action=\"setup.php\"><button>{$langSetup["restartbutton"]}</button></form>"; $messages[] = "<form method=\"post\" action=\"setup.php\"><button>{$langSetup["restartbutton"]}</button></form>";
break; break;
} }
if (empty(uConfig::$dbdsn) || ($dbDriver != "sqlite" && empty(uConfig::$dbuser))) { if (ini_get("session.auto_start") == "1") {
if ($dbDriver == "sqlite") {
$required = "\$dbdsn";
} else {
$required = "\$dbdsn, \$dbuser, \$dbpass";
}
$messages[] = sprintf($langSetup["nodbsettings"], $required);
$messages[] = $langSetup["dorestart"];
$messages[] = "<form method=\"post\" action=\"setup.php\"><button>{$langSetup["restartbutton"]}</button></form>";
break;
}
if (ini_get("session.auto_start") == '1') {
$messages[] = sprintf($langSetup["optionwarn"], "session.auto_start", "0 (off)"); $messages[] = sprintf($langSetup["optionwarn"], "session.auto_start", "0 (off)");
$messages[] = $langSetup["dorestart"]; $messages[] = $langSetup["dorestart"];
$messages[] = "<form method=\"post\" action=\"setup.php\"><button>{$langSetup["restartbutton"]}</button></form>"; $messages[] = "<form method=\"post\" action=\"setup.php\"><button>{$langSetup["restartbutton"]}</button></form>";
@ -144,14 +135,42 @@ switch ($command) {
$messages[] = "<form method=\"post\" action=\"setup.php\"><button>{$langSetup["restartbutton"]}</button></form>"; $messages[] = "<form method=\"post\" action=\"setup.php\"><button>{$langSetup["restartbutton"]}</button></form>";
break; break;
} }
$messages[] = sprintf($langSetup["scriptdesc"], "'$tPositions', '$tTracks', '$tUsers'", "<b>" . getDbname(uConfig::$dbdsn) . "</b>"); if (empty(uConfig::$dbdsn)) {
$messages[] = sprintf($langSetup["nodbsettings"], "\$dbdsn");
$messages[] = $langSetup["dorestart"];
$messages[] = "<form method=\"post\" action=\"setup.php\"><button>{$langSetup["restartbutton"]}</button></form>";
break;
}
try {
$pdo = getPdo();
} catch (PDOException $e) {
$isSqlite = stripos(uConfig::$dbdsn, "sqlite") === 0;
if (!$isSqlite && empty(uConfig::$dbuser)) {
$messages[] = sprintf($langSetup["nodbsettings"], "\$dbuser, \$dbpass");
} else {
$messages[] = $langSetup["dbconnectfailed"];
$messages[] = $langSetup["checkdbsettings"];
$messages[] = sprintf($langSetup["serversaid"], "<b>" . htmlentities($e->getMessage()) . "</b>");
}
$messages[] = $langSetup["dorestart"];
$messages[] = "<form method=\"post\" action=\"setup.php\"><button>{$langSetup["restartbutton"]}</button></form>";
break;
}
$pdo = null;
$dbName = uDb::getDbName(uConfig::$dbdsn);
$dbName = empty($dbName) ? '""' : "<b>" . htmlentities($dbName) . "</b>";
$messages[] = sprintf($langSetup["scriptdesc"], "'$tPositions', '$tTracks', '$tUsers'", $dbName);
$messages[] = $langSetup["scriptdesc2"]; $messages[] = $langSetup["scriptdesc2"];
$messages[] = "<form method=\"post\" action=\"setup.php\"><input type=\"hidden\" name=\"command\" value=\"setup\"><button>{$langSetup["startbutton"]}</button></form>"; $messages[] = "<form method=\"post\" action=\"setup.php\"><input type=\"hidden\" name=\"command\" value=\"setup\"><button>{$langSetup["startbutton"]}</button></form>";
break; break;
} }
function getQueries() { /**
global $tPositions, $tUsers, $tTracks, $dbDriver; * @param string $dbDriver
* @return array
*/
function getQueries($dbDriver) {
global $tPositions, $tUsers, $tTracks;
$queries = []; $queries = [];
switch ($dbDriver) { switch ($dbDriver) {
@ -284,26 +303,14 @@ function getQueries() {
return $queries; return $queries;
} }
function getDbname($dsn) { /**
if (strpos($dsn, ':') !== false) { * @return PDO
list($scheme, $dsnWithoutScheme) = explode(':', $dsn, 2); * @throws PDOException
switch ($scheme) { */
case 'sqlite': function getPdo() {
case 'sqlite2': $options = [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION];
case 'sqlite3': $pdo = new PDO(uConfig::$dbdsn, uConfig::$dbuser, uConfig::$dbpass, $options);
return $dsnWithoutScheme; return $pdo;
break;
default:
$pattern = '~dbname=([^;]*)(?:;|$)~';
$result = preg_match($pattern, $dsnWithoutScheme, $matches);
if ($result === 1 && !empty($matches[1])) {
return $matches[1];
}
break;
}
}
return "noname";
} }
?> ?>

View File

@ -123,7 +123,6 @@ if ($trackId && $userId) {
$totalSeconds = 0; $totalSeconds = 0;
$coordinate = []; $coordinate = [];
foreach ($positionsArr as $position) { foreach ($positionsArr as $position) {
/** @var uPosition $prevPosition */
$distance = isset($prevPosition) ? $position->distanceTo($prevPosition) : 0; $distance = isset($prevPosition) ? $position->distanceTo($prevPosition) : 0;
$seconds = isset($prevPosition) ? $position->secondsTo($prevPosition) : 0; $seconds = isset($prevPosition) ? $position->secondsTo($prevPosition) : 0;
$prevPosition = $position; $prevPosition = $position;