Skip to content

Commit

Permalink
Add Type and Format Processors (#6)
Browse files Browse the repository at this point in the history
* add format and type fields

* interpret type and format fields

* update schema and minor workflow  update

* fix standards
  • Loading branch information
husamAwadhi authored Apr 14, 2023
1 parent b98b925 commit fe5a54c
Show file tree
Hide file tree
Showing 12 changed files with 475 additions and 13 deletions.
6 changes: 0 additions & 6 deletions .github/workflows/main.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,6 @@ jobs:
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
restore-keys: ${{ runner.os }}-composer-

- name: Delete composer lock file
id: composer-lock
if: ${{ matrix.php-version == '8.1' || matrix.php-version == '8.2' }}
run: |
rm composer.lock
- name: Install dependencies
run: composer update --no-progress --prefer-dist --optimize-autoloader --ignore-platform-reqs

Expand Down
2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"yaml.schemas": {
"storage/schema.json": "file:///c%3A/html/power-parser/storage/tests/blueprints/*.yaml"
"storage/schema.json": "storage/tests/blueprints/*.yaml"
}
}
54 changes: 53 additions & 1 deletion src/Blueprint/Components/Fields.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@

use HusamAwadhi\PowerParser\Blueprint\BlueprintHelper;
use HusamAwadhi\PowerParser\Blueprint\ComponentInterface;
use HusamAwadhi\PowerParser\Blueprint\FieldFormat;
use HusamAwadhi\PowerParser\Blueprint\FieldType;
use HusamAwadhi\PowerParser\Blueprint\ValueObject\Field;
use HusamAwadhi\PowerParser\Blueprint\ValueObject\FieldFormat as FieldFormatObject;
use HusamAwadhi\PowerParser\Dictionary;
use HusamAwadhi\PowerParser\Exception\InvalidFieldException;
use Iterator;
Expand All @@ -31,7 +34,17 @@ protected function buildFields(array $fields): array
{
$objectFields = [];
foreach ($fields as $field) {
$objectFields[] = Field::from($field['name'], $field['position']);
$objectFields[] = Field::from(
$field['name'],
$field['position'],
(array_key_exists('type', $field) ? FieldType::from($field['type']) : null),
(array_key_exists('format', $field)
? FieldFormatObject::from(
FieldFormat::from(explode('%', $field['format'])[0]),
(int) explode('%', $field['format'])[1]
)
: null),
);
}

return $objectFields;
Expand All @@ -49,20 +62,59 @@ public static function from(array $fields, BlueprintHelper $helper): self
*/
public static function validation(array &$fields): void
{
$i = 0;
foreach ($fields as $field) {
if (
!array_key_exists('name', $field) ||
strlen($field['name']) == 0
) {
throw new InvalidFieldException('missing or invalid name');
}

if (
!isset($field['position']) ||
empty($field['position']) ||
!is_int($field['position'])
) {
throw new InvalidFieldException('missing or invalid position');
}

if (
isset($field['type']) &&
!empty($field['type'])
) {
if (!FieldType::tryFrom($field['type'])) {
throw new InvalidFieldException(
\sprintf(
'Blueprint %s field has invalid value (%s). Acceptable value(s) [%s]',
"type (#$i)",
$field['type'],
implode(', ', array_column(FieldType::cases(), 'value'))
)
);
}
}

if (
isset($field['format']) &&
!empty($field['format'])
) {
$format = explode('%', $field['format']);
if (
count($format) !== 2 ||
!FieldFormat::tryFrom($format[0]) ||
!is_numeric($format[1])
) {
throw new InvalidFieldException(
\sprintf(
'Blueprint format field has invalid value (%s). Acceptable value(s) {%s}%%{digits}',
$field['format'],
implode(',', array_column(FieldFormat::cases(), 'value'))
)
);
}
}
++$i;
}
}

Expand Down
9 changes: 9 additions & 0 deletions src/Blueprint/FieldFormat.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php

namespace HusamAwadhi\PowerParser\Blueprint;

enum FieldFormat: string
{
case STRING = 's';
case FLOAT = 'f';
}
11 changes: 11 additions & 0 deletions src/Blueprint/FieldType.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

namespace HusamAwadhi\PowerParser\Blueprint;

enum FieldType: string
{
case INT = 'int';
case FLOAT = 'float';
case BOOL = 'bool';
case BOOL_STRICT = 'bool-strict';
}
8 changes: 7 additions & 1 deletion src/Blueprint/ValueObject/Field.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,25 @@

namespace HusamAwadhi\PowerParser\Blueprint\ValueObject;

use HusamAwadhi\PowerParser\Blueprint\FieldType;

class Field
{
public function __construct(
public readonly string $name,
public readonly int $position,
public readonly ?FieldType $type,
public readonly ?FieldFormat $format,
) {
}

public static function from(string $name, int $position): self
public static function from(string $name, int $position, ?FieldType $type = null, ?FieldFormat $format = null): self
{
return new self(
name: $name,
position: $position,
type: $type,
format: $format,
);
}
}
22 changes: 22 additions & 0 deletions src/Blueprint/ValueObject/FieldFormat.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

namespace HusamAwadhi\PowerParser\Blueprint\ValueObject;

use HusamAwadhi\PowerParser\Blueprint\FieldFormat as FieldFormatEnum;

class FieldFormat
{
public function __construct(
public readonly FieldFormatEnum $type,
public readonly int $argument,
) {
}

public static function from(FieldFormatEnum $type, int $argument): self
{
return new self(
type: $type,
argument: $argument,
);
}
}
26 changes: 23 additions & 3 deletions src/Parser/Extension/BlueprintInterpreter.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

use HusamAwadhi\PowerParser\Blueprint\Blueprint;
use HusamAwadhi\PowerParser\Blueprint\Components\ConditionKeyword;
use HusamAwadhi\PowerParser\Blueprint\FieldFormat;
use HusamAwadhi\PowerParser\Blueprint\FieldType;
use HusamAwadhi\PowerParser\Blueprint\Type;
use HusamAwadhi\PowerParser\Blueprint\ValueObject\Component;
use HusamAwadhi\PowerParser\Blueprint\ValueObject\Condition;
Expand Down Expand Up @@ -112,7 +114,8 @@ protected function getFields(Component $component, array $row): array
if (!array_key_exists($field->position - 1, $row)) {
throw new InvalidFieldException("field {$field->name} does not exist in position #{$field->position}");
}
$filteredFields[$field->name] = $row[$field->position - 1];
$fieldValue = $row[$field->position - 1];
$filteredFields[$field->name] = $this->postProcessField($fieldValue, $field);
}

return $filteredFields;
Expand All @@ -131,14 +134,31 @@ protected function getTable(Component $component, array $rows, int &$index): arr

protected function matchCondition(Condition $condition, mixed $data): bool
{
$return = match ($condition->keyword) {
return match ($condition->keyword) {
ConditionKeyword::AnyOf => in_array($data, explode(',', $condition->value)),
ConditionKeyword::Is => $condition->value === $data,
ConditionKeyword::IsNot => $condition->value !== $data,
ConditionKeyword::NoneOf => !in_array($data, explode(',', $condition->value)),
};
}

protected function postProcessField(mixed $value, Field $field): mixed
{
if (null !== $field->type) {
$value = match ($field->type) {
FieldType::BOOL => strtolower((string) $value) == 'true' || $value == true || $value == '1',
FieldType::BOOL_STRICT => $value == true,
FieldType::INT => (int) $value,
FieldType::FLOAT => (float) $value,
};
} elseif (null !== $field->format) {
$value = match ($field->format->type) {
FieldFormat::STRING => substr($value, 0, $field->format->argument),
FieldFormat::FLOAT => round((float) $value, $field->format->argument, PHP_ROUND_HALF_UP),
};
}

return $return;
return $value;
}

public function getFiltered(): array
Expand Down
6 changes: 6 additions & 0 deletions storage/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,12 @@
},
"position": {
"type": "integer"
},
"type": {
"type": "string"
},
"format": {
"type": "string"
}
},
"required": [
Expand Down
63 changes: 63 additions & 0 deletions storage/tests/blueprints/valid_with_processors.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
version: "1.0"
meta:
file:
extension: xlsx
name: "sample"
blueprint:
- name: header_info
mandatory: true
type: hit
conditions:
- column: [1]
is: "Cashier Number"
fields:
- name: currency
position: 6
- name: cashier
position: 2
type: int
- name: balance_info
type: hit
mandatory: true
conditions:
- column: [4]
is: "Open Balance"
fields:
- name: opening_balance
position: 6
format: f%2
- name: transaction_table
type: hit
mandatory: true
table: true
conditions:
- column: [1]
isNot: "{null}"
fields:
- name: date
position: 1
- name: type
position: 2
- name: document_number
position: 3
type: int
- name: description
position: 4
- name: reference_number
position: 5
type: int
- name: credit
position: 6
format: f%2
- name: debit
position: 7
format: f%2
- name: total
type: next
fields:
- name: total_credit
position: 6
format: f%2
- name: total_debit
position: 7
format: f%2
27 changes: 27 additions & 0 deletions tests/Blueprint/Components/FieldsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@

use HusamAwadhi\PowerParser\Blueprint\BlueprintHelper;
use HusamAwadhi\PowerParser\Blueprint\Components\Fields;
use HusamAwadhi\PowerParser\Blueprint\FieldFormat as FieldFormatEnum;
use HusamAwadhi\PowerParser\Blueprint\FieldType;
use HusamAwadhi\PowerParser\Blueprint\ValueObject\Field;
use HusamAwadhi\PowerParser\Blueprint\ValueObject\FieldFormat;
use HusamAwadhi\PowerParser\Exception\InvalidFieldException;
use PHPUnit\Framework\TestCase;

Expand All @@ -29,10 +32,18 @@ public function validParametersDataProvider()
[
['name' => 'field1', 'position' => 2],
['name' => 'field2', 'position' => 3],
['name' => 'field3', 'position' => 25, 'type' => 'int'],
['name' => 'field4', 'position' => 4, 'type' => 'bool-strict'],
['name' => 'field5', 'position' => 4, 'format' => 's%5'],
['name' => 'field5', 'position' => 4, 'type' => 'bool', 'format' => 'f%2'],
],
[
Field::from('field1', 2),
Field::from('field2', 3),
Field::from('field3', 25, FieldType::INT),
Field::from('field4', 4, FieldType::BOOL_STRICT),
Field::from('field5', 4, null, FieldFormat::from(FieldFormatEnum::STRING, 5)),
Field::from('field5', 4, FieldType::BOOL, FieldFormat::from(FieldFormatEnum::FLOAT, 2)),
],
],
];
Expand Down Expand Up @@ -65,6 +76,22 @@ public function invalidParametersDataProvider()
[['position' => 'two'],],
InvalidFieldException::class,
],
[
[['name' => 'field1', 'position' => 2, 'type' => 'single'],],
InvalidFieldException::class,
],
[
[['name' => 'field1', 'position' => 2, 'format' => 's'],],
InvalidFieldException::class,
],
[
[['name' => 'field1', 'position' => 2, 'format' => 's%x'],],
InvalidFieldException::class,
],
[
[['name' => 'field1', 'position' => 2, 'format' => 's% '],],
InvalidFieldException::class,
],
];
}
}
Loading

0 comments on commit fe5a54c

Please sign in to comment.