Skip to content

Commit

Permalink
Merge branch 'release-0.11' into 0.11-feat-realtime; fix and adjust t…
Browse files Browse the repository at this point in the history
…ests to new auth system

Signed-off-by: Vinzenz Rosenkranz <[email protected]>
  • Loading branch information
v1r0x committed Nov 26, 2024
2 parents 9bb5307 + 0c63a82 commit 88552ab
Show file tree
Hide file tree
Showing 116 changed files with 3,141 additions and 928 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ phpunit.xml.bak
/public/hot
/public/storage
/storage/*.key
/tmp
/vendor
/.idea
/.vscode
Expand Down
29 changes: 28 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,35 @@
All notable changes to this project will be documented in this file.

## 0.10.1
### Fixed
### Added
- Option to display attributes in _Data Model Editor_ in groups
- Filter attributes in _Data Model Editor_
- Attributes in _Data Model Editor_ can now be sorted (by name or creation date)
- Pressing `Tab` key in _Single Choice Dropdowns_ now either:
- selects the first choice (if there is **only one choice** in the dropdown)*
- selects the exact match (**case insensitive**; e.g. "apple" + `Tab` will select the available choice "apple", but also "Apple")*
- nothing and focuses the next attribute (default)
- * Selected elements will be marked with a blue (Tab) badge
- Pressing `Delete` inside _Single Choice Dropdowns_ will clear the element
- Importer now automatically removes BOM if present
- Better readable format for error message on validation
- Renamed _fromImport_ to _parseImport_ on the attribute classses. The base class now by default imports the passed string, removing redundancies on the string-based classes.
- More elaborate type checking on attributes _parseImport_ method.
- Unit test for all attribute imports (except Table).
### Fixed
- Entity (Multiple-Choice) no longer removes all entries when a single one is deleted.
- Frontend errors due to wrong dayjs import
- Missing translation for _milligram_ in si-unit attribute
- Entity search now allows to display more than first 10 results
- `^` and `$` can be used in search query to match query only at the beginning/end of entity name
- Wrong behavior in validation/updating of _Integer_ values
- Entity tree header overflow on small screens
- Added tests for all attribute type imports
- Improved output in _Data Importer_ frontend
- Adding _Group Separator_ in _Data Model Editor_
### Changed
- Move switch to show hidden attributes in _Data Model Editor_ to dropdown
- Make tabular head _sticky_

## 0.10 - Jelling
### Added
Expand Down
5 changes: 2 additions & 3 deletions app/Attribute.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

use App\AttributeTypes\AttributeBase;
use Illuminate\Database\Eloquent\Model;
use MStaack\LaravelPostgis\Geometries\Geometry;
use Spatie\Activitylog\Traits\LogsActivity;
use Spatie\Activitylog\LogOptions;

Expand Down Expand Up @@ -59,7 +58,7 @@ public function getEntityAttributeValueName() {

public function getAttributeValueFromEntityPivot()
{
switch ($this->datatype) {
switch($this->datatype) {
case 'string-sc':
$this->pivot->thesaurus_val = ThConcept::where('concept_url', $this->pivot->thesaurus_val)->first();
break;
Expand All @@ -73,7 +72,7 @@ public function getAttributeValueFromEntityPivot()
$this->pivot->thesaurus_val ??
json_decode($this->pivot->json_val) ??
$this->pivot->dt_val ??
Geometry::fromWKB($this->pivot->geography_val)->toWKT();
Geodata::wkb2wkt($this->pivot->geography_val);
}

public function getSelection() {
Expand Down
26 changes: 22 additions & 4 deletions app/AttributeTypes/AttributeBase.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
use App\AttributeValue;
use App\Entity;
use App\EntityType;
use App\Exceptions\InvalidDataException;
use App\User;
use App\Utils\StringUtils;
use Illuminate\Support\Arr;

abstract class AttributeBase
Expand Down Expand Up @@ -61,7 +63,7 @@ public static function getTypes(bool $serialized = false, array $filters = []) :
} else if($on == "in_table") {
if($attr::getInTable() != $value) return false;
} else if($on == "field") {
if($attr::getField() != $value) return false;
if($attr::getField() != $value) return false;
} else if($on == "has_selection") {
if($attr::getHasSelection() != $value) return false;
}
Expand Down Expand Up @@ -128,16 +130,32 @@ public static function onCreateHandler(Entity $entity, User $user) : void {
$class::handleOnCreate($entity, $attr, $user);
}
}

}

public static function onAddHandler(Attribute $attr, EntityType $entityType, User $user) : void {
$class = self::getMatchingClass($attr->datatype);
if(method_exists($class, "handleOnAdd")) {
if($class !== false && method_exists($class, "handleOnAdd")) {
$class::handleOnAdd($attr, $entityType, $user);
}
}

public abstract static function fromImport(int|float|bool|string $data) : mixed;
private static function importDataIsEmpty(int|float|bool|string $data) : bool {
if(!is_string($data)) return false;
return trim($data) === "";
}

public static function fromImport(int|float|bool|string $data) : mixed {
if(self::importDataIsEmpty($data)) {
return null;
}
return static::parseImport($data);
}

public static function parseImport(int|float|bool|string $data) : mixed {
return StringUtils::useGuard(InvalidDataException::class)($data);
}

public abstract static function unserialize(mixed $data) : mixed;
public abstract static function serialize(mixed $data) : mixed;
}
22 changes: 15 additions & 7 deletions app/AttributeTypes/BooleanAttribute.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,29 @@

namespace App\AttributeTypes;

use App\Exceptions\InvalidDataException;

class BooleanAttribute extends AttributeBase {
protected static string $type = "boolean";
protected static bool $inTable = true;
protected static ?string $field = 'int_val';

public static function fromImport(int|float|bool|string $data): mixed {
public static function parseImport(int|float|bool|string $data) : mixed {
$boolean = false;

if (is_string($data)) {
$data = strtolower(trim($data));
if(is_bool($data)) {
$boolean = $data;
} else if(is_numeric($data)) {
$boolean = floatval($data) > 0;
} else if(is_string($data)) {
$truthy = ['true', 't', 'x', 'wahr', 'w'];
$string_val = strtolower(trim($data));
$boolean = in_array($string_val, $truthy, true);
} else {
throw InvalidDataException::requireBoolean($data);
}

return
$data == 1 || $data == '1' || $data == 'x' ||
$data == 'true' || $data == 't' ||
intval($data) > 0;
return $boolean;
}

public static function unserialize(mixed $data): mixed {
Expand Down
9 changes: 5 additions & 4 deletions app/AttributeTypes/DateAttribute.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace App\AttributeTypes;

use App\Exceptions\InvalidDataException;
use App\Utils\StringUtils;
use Carbon\Carbon;
use Carbon\Exceptions\InvalidFormatException;

Expand All @@ -14,21 +15,21 @@ class DateAttribute extends AttributeBase

private static string $format = "Y-m-d";

public static function fromImport(int|float|bool|string $data) : mixed {
$errmsg = "Your provided date ($data) does not match the required format of 'Y-m-d'";
public static function parseImport(int|float|bool|string $data) : mixed {
$data = StringUtils::useGuard(InvalidDataException::class)($data);

// have to do hasFormat and createFromFormat, because both allow dates the other does not
// e.g. 20222 is a valid year for hasFormat, but not createFromFormat
// on the other hand 13 is a valid month for createFromFormat (overflows to next year's january), but not hasFormat
if(!Carbon::hasFormat($data, self::$format)) {
throw new InvalidDataException($errmsg);
throw InvalidDataException::requiredFormat(self::$format, $data);
}

try {
$date = Carbon::createFromFormat(self::$format, $data);
return $date->format(self::$format);
} catch(InvalidFormatException $e) {
throw new InvalidDataException($errmsg);
throw InvalidDataException::requiredFormat(self::$format, $data);
}
}

Expand Down
20 changes: 14 additions & 6 deletions app/AttributeTypes/DaterangeAttribute.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace App\AttributeTypes;

use App\Exceptions\InvalidDataException;
use App\Utils\StringUtils;

class DaterangeAttribute extends AttributeBase
{
Expand All @@ -14,16 +15,23 @@ private static function toDate(string $date, string $format = "Y-m-d") : string
return date($format, strtotime($date));
}

public static function fromImport(int|float|bool|string $data) : mixed {
public static function parseImport(int|float|bool|string $data) : mixed {
$data = StringUtils::useGuard(InvalidDataException::class)($data);
$dates = explode(";", $data);

if(count($dates) != 2) {
throw new InvalidDataException("Given data does not match this datatype's format (START;END)");
throw InvalidDataException::requiredFormat("START;END", $data);
}

$start = DateAttribute::parseImport($dates[0]);
$end = DateAttribute::parseImport($dates[1]);

if($start > $end) {
throw InvalidDataException::requireBefore($start, $end);
}

return [
"start" => trim(self::toDate($dates[0])),
"end" => trim(self::toDate($dates[1])),
"start" => $start,
"end" => $end,
];
}

Expand All @@ -38,4 +46,4 @@ public static function unserialize(mixed $data) : mixed {
public static function serialize(mixed $data) : mixed {
return json_decode($data);
}
}
}
13 changes: 11 additions & 2 deletions app/AttributeTypes/DimensionAttribute.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,27 @@
namespace App\AttributeTypes;

use App\Exceptions\InvalidDataException;
use App\Utils\StringUtils;

class DimensionAttribute extends AttributeBase
{
protected static string $type = "dimension";
protected static bool $inTable = false;
protected static ?string $field = 'json_val';

public static function fromImport(int|float|bool|string $data) : mixed {
public static function parseImport(int|float|bool|string $data) : mixed {
$data = StringUtils::useGuard(InvalidDataException::class)($data);
$parts = explode(';', $data);

$format = "VAL1;VAL2;VAL3;UNIT";
if(count($parts) != 4) {
throw new InvalidDataException("Given data does not match this datatype's format (VAL1;VAL2;VAL3;UNIT)");
throw InvalidDataException::requiredFormat($format, $data);
}

for($i = 0; $i < 3; $i++) {
if(!is_numeric($parts[$i])) {
throw InvalidDataException::requiredFormat($format, $data);
}
}

return json_encode([
Expand Down
4 changes: 2 additions & 2 deletions app/AttributeTypes/DoubleAttribute.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ class DoubleAttribute extends AttributeBase
protected static bool $inTable = true;
protected static ?string $field = 'dbl_val';

public static function fromImport(int|float|bool|string $data) : mixed {
public static function parseImport(int|float|bool|string $data) : mixed {
if(!is_numeric($data)) {
throw new InvalidDataException("Given data is not a number");
throw InvalidDataException::requireNumeric($data);
}
return floatval($data);
}
Expand Down
10 changes: 6 additions & 4 deletions app/AttributeTypes/DropdownMultipleAttribute.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
namespace App\AttributeTypes;

use App\Attribute;
use App\ThConcept;
use App\Exceptions\InvalidDataException;
use App\ThConcept;
use App\Utils\StringUtils;

class DropdownMultipleAttribute extends AttributeBase
{
Expand All @@ -17,19 +18,20 @@ public static function getSelection(Attribute $a) {
return ThConcept::getChildren($a->thesaurus_root_url, $a->recursive);
}

public static function fromImport(int|float|bool|string $data) : mixed {
public static function parseImport(int|float|bool|string $data) : mixed {
$data = StringUtils::useGuard(InvalidDataException::class)($data);
$convValues = [];
$parts = explode(';', $data);
foreach($parts as $part) {
$trimmedPart = trim($part);
$concept = ThConcept::getByString($trimmedPart);
$concept = ThConcept::getByString($trimmedPart); // Discuss: Problematic when there is another concept with the same name AND also when the concept is NOT available in this dropdown.
if(isset($concept)) {
$convValues[] = [
'id' => $concept->id,
'concept_url' => $concept->concept_url,
];
} else {
throw new InvalidDataException("Given data part ($trimmedPart) is not a valid concept/label in the vocabulary");
throw InvalidDataException::invalidConcept($trimmedPart);
}
}
return json_encode($convValues);
Expand Down
6 changes: 4 additions & 2 deletions app/AttributeTypes/DropdownSingleAttribute.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use App\Attribute;
use App\ThConcept;
use App\Exceptions\InvalidDataException;
use App\Utils\StringUtils;

class DropdownSingleAttribute extends AttributeBase
{
Expand All @@ -17,12 +18,13 @@ public static function getSelection(Attribute $a) {
return ThConcept::getChildren($a->thesaurus_root_url, $a->recursive);
}

public static function fromImport(int|float|bool|string $data) : mixed {
public static function parseImport(int|float|bool|string $data) : mixed {
$data = StringUtils::useGuard(InvalidDataException::class)($data);
$concept = ThConcept::getByString($data);
if(isset($concept)) {
return $concept->concept_url;
} else {
throw new InvalidDataException("Given data is not a valid concept/label in the vocabulary");
throw InvalidDataException::invalidConcept($data);
}
}

Expand Down
13 changes: 11 additions & 2 deletions app/AttributeTypes/EntityAttribute.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
namespace App\AttributeTypes;

use App\Entity;
use App\Exceptions\InvalidDataException;
use App\Utils\StringUtils;

class EntityAttribute extends AttributeBase
{
Expand All @@ -11,8 +13,15 @@ class EntityAttribute extends AttributeBase
protected static ?string $field = 'entity_val';
protected static string $deleted_string = "error.deleted_entity";

public static function fromImport(int|float|bool|string $data) : mixed {
return Entity::getFromPath($data);
public static function parseImport(int|float|bool|string $data) : mixed {
// TODO: This does not check if the entity that is selected is actually valid!
$data = StringUtils::useGuard(InvalidDataException::class)($data);
$entityId = Entity::getFromPath($data);
if($entityId === null) {
throw InvalidDataException::invalidEntity($data);
}

return $entityId;
}

public static function unserialize(mixed $data) : mixed {
Expand Down
Loading

0 comments on commit 88552ab

Please sign in to comment.