Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
137 changes: 79 additions & 58 deletions script/package-version/package-version.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,81 +9,102 @@

class PackageVersion
{
static function available_platforms()
{
private $mssql;

static function available_platforms() {
return ['android', 'ios', 'linux', 'mac', 'web', 'windows'];
}

function execute($mssql, $params, $platform)
{
// TODO: params should be expanded to keyboards, models
function __construct($mssql) {
$this->mssql = $mssql;
}

function execute($keyboards, $models, $platform, $keymanVersion) {
// Prepare results

$json = [];

if (isset($params['keyboard'])) {
if (count($keyboards) > 0) {
$json['keyboards'] = [];

foreach ($params['keyboard'] as $keyboard) {
$stmt = $mssql->prepare(
'SELECT
k.version, k.package_filename,
k.platform_android, k.platform_linux, k.platform_macos, k.platform_ios, k.platform_web, k.platform_windows,
kr.keyboard_id deprecated_by_keyboard_id
FROM
t_keyboard k LEFT JOIN
t_keyboard_related kr ON k.keyboard_id = kr.related_keyboard_id AND kr.deprecates = 1
WHERE
k.keyboard_id = ?'
);
$stmt->bindParam(1, $keyboard);
$stmt->execute();
$data = $stmt->fetchAll();
if (count($data) == 0) {
$json["keyboards"][$keyboard] = ['error' => 'not found'];
} else {

$json["keyboards"][$keyboard] = [
'version' => $data[0][0]
];

if (!empty($platform) && !$data[0][array_search($platform, PackageVersion::available_platforms()) + 2]) {
$json["keyboards"][$keyboard]['error'] = 'not available for platform';
}

if(!empty($data[0][1])) {
$json["keyboards"][$keyboard]['kmp'] = KeymanUrls::keyboard_download_url($keyboard, $data[0][0], $data[0][1]);
} else {
$json["keyboards"][$keyboard]['error'] = 'not available as package';
}

if(!empty($data[0]['deprecated_by_keyboard_id'])) {
$json["keyboards"][$keyboard]['deprecatedBy'] = $data[0]['deprecated_by_keyboard_id'];
}
}
foreach ($keyboards as $keyboard) {
$json["keyboards"][$keyboard] = $this->getKeyboard($keyboard, $platform, $keymanVersion);
}
}

if (isset($params['model'])) {
if (count($models) > 0) {
$json['models'] = [];

foreach ($params['model'] as $model) {
$stmt = $mssql->prepare('SELECT version, package_filename FROM t_model WHERE model_id = ?');
$stmt->bindParam(1, $model);
$stmt->execute();
$data = $stmt->fetchAll();
if (count($data) == 0) {
$json["models"][$model] = ['error' => 'not found'];
} else {
// Note: we don't currently test platform for models
$json["models"][$model] = [
'version' => $data[0][0],
'kmp' => KeymanUrls::model_download_url($model, $data[0][0], $data[0][1])
];
}
foreach ($models as $model) {
$json["models"][$model] = $this->getModel($model, $platform, $keymanVersion);
}
}

return $json;
}

function getKeyboard($keyboard, $platform, $keymanVersion) {
$stmt = $this->mssql->prepare(
'SELECT
k.version, k.package_filename,
k.platform_android, k.platform_linux, k.platform_macos, k.platform_ios, k.platform_web, k.platform_windows,
kr.keyboard_id deprecated_by_keyboard_id, k.min_keyman_version
FROM
t_keyboard k LEFT JOIN
t_keyboard_related kr ON k.keyboard_id = kr.related_keyboard_id AND kr.deprecates = 1
WHERE
k.keyboard_id = ?'
);
$stmt->bindParam(1, $keyboard);
$stmt->execute();
$data = $stmt->fetchAll();

$jsonKeyboard = [];

if (count($data) == 0) {
$jsonKeyboard['error'] = 'not found';
} else {
$dataKeyboard = $data[0];

if (!empty($platform) && !$dataKeyboard[array_search($platform, PackageVersion::available_platforms()) + 2]) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nothing new, but the order of the fields in the SELECT statement and in available_patforms() is different (k.platform_android, k.platform_linux, k.platform_macos, k.platform_ios, k.platform_web, k.platform_windows vs 'android', 'ios', 'linux', 'mac', 'web', 'windows'), so the results will be wrong for Linux, Mac and iOS (flagged by devin.ai).

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And I had fixed one of the issues but missed this one, thanks

$jsonKeyboard['error'] = "Not available for platform $platform";
}
else if(!empty($keymanVersion) && version_compare($keymanVersion, $dataKeyboard['min_keyman_version'], '<')) {
$jsonKeyboard['error'] = "Keyman version {$dataKeyboard['min_keyman_version']}+ required";
}
else if(empty($dataKeyboard['package_filename'])) {
$jsonKeyboard['error'] = 'not available as package';
} else {
$jsonKeyboard['version'] = $dataKeyboard['version'];
$jsonKeyboard['kmp'] = KeymanUrls::keyboard_download_url($keyboard, $dataKeyboard['version'], $dataKeyboard['package_filename']);
if(!empty($dataKeyboard['deprecated_by_keyboard_id'])) {
$jsonKeyboard['deprecatedBy'] = $dataKeyboard['deprecated_by_keyboard_id'];
}
}
}
return $jsonKeyboard;
}

function getModel($model, $platform, $keymanVersion) {
$stmt = $this->mssql->prepare('SELECT version, package_filename, min_keyman_version FROM t_model WHERE model_id = ?');
$stmt->bindParam(1, $model);
$stmt->execute();
$data = $stmt->fetchAll();

$jsonModel = [];

if (count($data) == 0) {
$jsonModel["error"] = 'not found';
} else {
$dataModel = $data[0];
// Note: we don't currently test platform for models
if(!empty($keymanVersion) && version_compare($keymanVersion, $dataModel['min_keyman_version'], '<')) {
$jsonModel['error'] = "Keyman version {$dataModel['min_keyman_version']}+ required";
} else {
$jsonModel['version'] = $dataModel['version'];
$jsonModel['kmp'] = KeymanUrls::model_download_url($model, $dataModel['version'], $dataModel['package_filename']);
}
}
return $jsonModel;
}
}
40 changes: 27 additions & 13 deletions script/package-version/package-version.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,16 @@
*
* https://api.keyman.com/schemas/package-version.json is JSON schema for valid responses
*
* @param keyboard Optional. keyboard id, can be repeated (either with comma or repeated param).
* @param model Optional. model id, can be repeated (either with comma or repeated param).
* @param platform Optional. Filter by platform support for keyboards:
* android, ios, linux, mac, [web], windows (web does not currently support .kmp)
* This stops the API returning keyboard packages that are invalid for the target
* platform. If not supplied, does not filter by platform support.
* @return JSON blob or HTTP/400 (with JSON error) on invalid parameters
* The valid blob will contain latest version and url for the keyboards/lexical models.
* @param keyboard Optional. keyboard id, can be repeated (either with comma or repeated param).
* @param model Optional. model id, can be repeated (either with comma or repeated param).
* @param platform Optional. Filter by platform support for keyboards:
* android, ios, linux, mac, [web], windows (web does not currently support .kmp)
* This stops the API returning keyboard packages that are invalid for the target
* platform. If not supplied, does not filter by platform support.
* @param keyman-version Optional. Version of Keyman requesting the keyboard, will filter out keyboards
* that depend on a newer version of Keyman.
* @return JSON blob or HTTP/400 (with JSON error) on invalid parameters
* The valid blob will contain latest version and url for the keyboards/lexical models.
*/

require_once('../../tools/util.php');
Expand All @@ -39,22 +41,34 @@
$available_platforms = PackageVersion::available_platforms();

foreach($params as $param => $value) {
if(!in_array($param, ['keyboard', 'model', 'platform'])) {
fail("Invalid parameter $param");
if(!in_array($param, ['keyboard', 'model', 'platform', 'keyman-version'])) {
fail("Unrecognized parameter '$param'");
}
}

if(isset($params['platform'])) {
$platform = $params['platform'];
if(!in_array($platform, $available_platforms)) {
fail("Invalid platform $platform");
fail("Invalid platform' $platform'");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
fail("Invalid platform' $platform'");
fail("Invalid platform '$platform'");

}
}
else $platform = null;

// Prepare results

$PackageVersion = new Keyman\Site\com\keyman\api\PackageVersion();
$json = $PackageVersion->execute($mssql, $params, $platform);
if(isset($params['keyman-version'])) {
$keymanVersion = $params['keyman-version'];
if(!preg_match('/^(\d+)\.(\d+)\.(\d+)$/', $keymanVersion)) {
fail("Invalid keyman-version '$keymanVersion', expected a.b.c format");
}
}
else $keymanVersion = null;

$keyboards = isset($params['keyboard']) ? $params['keyboard'] : [];
$models = isset($params['model']) ? $params['model'] : [];

$PackageVersion = new Keyman\Site\com\keyman\api\PackageVersion($mssql);
$json = $PackageVersion->execute($keyboards, $models, $platform, $keymanVersion);

echo json_encode($json, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT);

Expand Down
4 changes: 2 additions & 2 deletions tests/PackageVersionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ public function testSimpleResultValidatesAgainstSchema(): void
$schema = TestUtils::LoadJSONSchema(PackageVersionTest::SchemaFilename);
$mssql = \Keyman\Site\com\keyman\api\Tools\DB\DBConnect::Connect();

$pv = new \Keyman\Site\com\keyman\api\PackageVersion();
$json = $pv->execute($mssql, [ 'keyboard' => ['khmer_angkor', 'bar', 'us', 'european2'], ['model' => 'zoo','nrc.en.mtnt'] ], 'windows');
$pv = new \Keyman\Site\com\keyman\api\PackageVersion($mssql);
$json = $pv->execute(['khmer_angkor', 'bar', 'us', 'european2'], ['zoo','nrc.en.mtnt'], 'windows', '1.0');

// TODO(lowpri): find a way to skip this by emitting clean JSON object from execute()
$json = json_decode(json_encode($json));
Expand Down