Commit caca58ab authored by Volker Krause's avatar Volker Krause
Browse files

Add aggregation settings storage operations

parent 1be2b9bd
......@@ -13,6 +13,7 @@ set(server_config_srcs
)
set(server_shared_srcs
shared/aggregation.php
shared/analytics.php
shared/datastore.php
shared/product.php
......
<?php
/*
Copyright (C) 2016 Volker Krause <vkrause@kde.org>
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
require_once('datastore.php');
require_once('product.php');
/** Represents a product aggregation setting. */
class Aggregation
{
public $type;
public $elements = array();
/** Load aggregation settings for @p $product from storage. */
static public function aggregationsForProduct(DataStore $db, Product $product)
{
$sql = 'SELECT type, elements FROM aggregation WHERE productId = :productId ORDER BY id';
$stmt = $db->prepare($sql);
$db->execute($stmt, array(':productId' => $product->id()));
$aggrs = array();
foreach ($stmt as $row) {
$a = new Aggregation;
$a->type = strval($row['type']);
$a->elements = json_decode(strval($row['elements']));
array_push($aggrs, $a);
}
return $aggrs;
}
/** Update aggregation settings for @p $product to @p $aggregations. */
static public function update(DataStore $db, Product $product, $aggregations)
{
Aggregation::delete($db, $product);
$sql = 'INSERT INTO aggregation (productId, type, elements) VALUES (:productId, :type, :elements)';
$stmt = $db->prepare($sql);
foreach ($aggregations as $a) {
$db->execute($stmt, array(
':productId' => $product->id(),
':type' => $a->type,
':elements' => json_encode($a->elements)
));
}
}
/** Delete all aggregation settings for @p $product. */
static public function delete(DataStore $db, Product $product)
{
$sql = 'DELETE FROM aggregation WHERE productId = :productId';
$stmt = $db->prepare($sql);
$db->execute($stmt, array(':productId' => $product->id()));
}
/** Convert a JSON object into an array of Aggregation instances. */
static public function fromJson($jsonArray)
{
if (!is_array($jsonArray))
throw new RESTException('Wrong aggregation list format.', 400);
$aggrs = array();
foreach ($jsonArray as $jsonObj) {
if (!is_object($jsonObj))
throw new RESTException('Wrong aggregation format.', 400);
if (!property_exists($jsonObj, 'type'))
throw new RESTException('Incomplete aggregation object.', 400);
$a = new Aggregation;
$a->type = strval($jsonObj->type);
if (property_exists($jsonObj, 'elements'))
$a->elements = $jsonObj->elements;
array_push($aggrs, $a);
}
return $aggrs;
}
}
?>
......@@ -33,6 +33,11 @@
{
"version": 7,
"sql": ["CREATE TABLE schema_elements (id INTEGER PRIMARY KEY AUTOINCREMENT, schemaId INTEGER REFERENCES product_schema (id), name VARCHAR NOT NULL, type VARCHAR NOT NULL)" ]
},
{
"version": 8,
"sql": ["CREATE TABLE aggregation (id INTEGER PRIMARY KEY AUTOINCREMENT, productId INTEGER REFERENCES products (id) ON DELETE CASCADE, type VARCHAR NOT NULL, elements VARCHAR)" ]
}
]
}
......@@ -35,6 +35,7 @@ set(php_test_srcs
producttest.php
sampletest.php
surveytest.php
aggregationtest.php
)
php_lint(${php_test_srcs})
......
<?php
/*
Copyright (C) 2016 Volker Krause <vkrause@kde.org>
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
require_once('../../server/shared/aggregation.php');
require_once('../../server/shared/datastore.php');
class AggregationTest extends PHPUnit_Extensions_Database_TestCase
{
static private $db = null;
private $conn = null;
public function getConnection()
{
if (is_null($this->conn)) {
if (is_null(self::$db)) {
self::$db = new Datastore('sqlite::memory:');
self::$db->checkSchema();
}
$this->conn = $this->createDefaultDBConnection(self::$db->pdoHandle(), ':memory:');
}
return $this->conn;
}
public function getDataSet()
{
return $this->createXmlDataSet(__DIR__ . '/dataset.xml');
}
public function testFromJson()
{
$json = '[]';
$aggrs = Aggregation::fromJson(json_decode($json));
$this->assertCount(0, $aggrs);
$json = '[
{ "type": "category", "elements": [ { "type": "value", "schemaEntry": "entry1", "schemaEntryElement": "elem11" } ] },
{ "type": "numeric", "elements": [ { "type": "size", "schemaEntry": "entry2" } ] }
]';
$aggrs = Aggregation::fromJson(json_decode($json));
$this->assertCount(2, $aggrs);
$a = $aggrs[0];
$this->assertInstanceOf(Aggregation::class, $a);
$this->assertEquals('category', $a->type);
$this->assertCount(1, $a->elements);
$a = $aggrs[1];
$this->assertInstanceOf(Aggregation::class, $a);
$this->assertEquals('numeric', $a->type);
$this->assertCount(1, $a->elements);
}
public function testLoad()
{
$p = Product::productByName(self::$db, 'org.kde.UnitTest');
$this->assertNotNull($p);
$aggrs = Aggregation::aggregationsForProduct(self::$db, $p);
$this->assertCount(2, $aggrs);
$a = $aggrs[0];
$this->assertInstanceOf(Aggregation::class, $a);
$this->assertEquals('category', $a->type);
$this->assertCount(1, $a->elements);
$a = $aggrs[1];
$this->assertInstanceOf(Aggregation::class, $a);
$this->assertEquals('numeric', $a->type);
$this->assertCount(1, $a->elements);
}
public function testWrite()
{
$p = Product::productByName(self::$db, 'org.kde.UnitTest');
$this->assertNotNull($p);
$a = new Aggregation;
$a->type = 'xy';
$a->elements = json_decode('[
{ "type": "value", "schemaEntry": "entry2", "schemaEntryElement": "element21" },
{ "type": "value", "schemaEntry": "entry2", "schemaEntryElement": "element22" }
]');
Aggregation::update(self::$db, $p, array(0 => $a));
$aggrs = Aggregation::aggregationsForProduct(self::$db, $p);
$this->assertCount(1, $aggrs);
$a = $aggrs[0];
$this->assertInstanceOf(Aggregation::class, $a);
$this->assertEquals('xy', $a->type);
$this->assertCount(2, $a->elements);
}
public function testDelete()
{
$p = Product::productByName(self::$db, 'org.kde.UnitTest');
$this->assertNotNull($p);
$aggrs = Aggregation::aggregationsForProduct(self::$db, $p);
$this->assertNotEmpty($aggrs);
Aggregation::delete(self::$db, $p);
$aggrs = Aggregation::aggregationsForProduct(self::$db, $p);
$this->assertEmpty($aggrs);
}
public function testInvalidJson_data()
{
return [
'nothing' => [ '' ],
'object' => [ '{}' ],
'array of non-objects' => [ '[1, 2, 3]' ],
'missing type' => [ '[{ "elements": [] }]' ]
];
}
/**
* @dataProvider testInvalidJson_data
* @expectedException RESTException
* @exceptedExceptionCode 400
*/
public function testInvalidJson($input)
{
$aggrs = Aggregation::fromJson(json_decode($input));
}
}
......@@ -81,4 +81,22 @@
<value>0</value>
</row>
</table>
<table name="aggregation">
<column>id</column>
<column>productId</column>
<column>type</column>
<column>elements</column>
<row>
<value>201</value>
<value>2</value>
<value>category</value>
<value>[ { "type": "value", "schemaEntry": "entry1", "schemaEntryElement": "element11" } ]</value>
</row>
<row>
<value>202</value>
<value>2</value>
<value>numeric</value>
<value>[ { "type": "size", "schemaEntry": "entry2" } ]</value>
</row>
</table>
</dataset>
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment