Skip to content

Commit

Permalink
made array of attributes encoding/decoding better
Browse files Browse the repository at this point in the history
  • Loading branch information
vatsake committed May 2, 2024
1 parent af83be0 commit b5609b7
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 55 deletions.
20 changes: 12 additions & 8 deletions src/Api/Cups/AttributeGroup.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ abstract class AttributeGroup
protected int $tag;

/**
* @var array<string, \Rawilk\Printing\Api\Cups\Type>
* @var array<string, \Rawilk\Printing\Api\Cups\Type|array<int, \Rawilk\Printing\Api\Cups\Type>>
*/
protected array $attributes = [];

Expand All @@ -29,7 +29,7 @@ public function __construct(array $attributes = [])
}

/**
* @var array<string, \Rawilk\Printing\Api\Cups\Type>
* @var array<string, \Rawilk\Printing\Api\Cups\Type|array<int, \Rawilk\Printing\Api\Cups\Type>>
*/
public function getAttributes()
{
Expand All @@ -40,7 +40,7 @@ public function encode(): string
{
$binary = pack('c', $this->tag);
foreach ($this->attributes as $name => $value) {
if (gettype($value->value) === 'array') {
if (gettype($value) === 'array') {
$binary .= $this->handleArrayEncode($name, $value);
continue;
}
Expand All @@ -56,23 +56,27 @@ public function encode(): string

/**
* If attribute is an array, the attribute name after the first element is empty
* @param string $name
* @param array<int, \Rawilk\Printing\Api\Cups\Type> $values
*/
private function handleArrayEncode(string $name, \Rawilk\Printing\Api\Cups\Type $value): string
private function handleArrayEncode(string $name, array $values): string
{
$str = '';
for ($i = 0; $i < sizeof($value->value); $i++) {
if (get_class($values[0]) === \Rawilk\Printing\Api\Cups\Types\RangeOfInteger::class) {
\Rawilk\Printing\Api\Cups\Types\RangeOfInteger::checkOverlaps($values);
}
for ($i = 0; $i < sizeof($values); $i++) {
$_name = $name;
if ($i !== 0) {
$_name = '';
}
$nameLen = strlen($_name);

$str .= pack('c', $value->getTag()); // Value tag
$str .= pack('c', $values[$i]->getTag()); // Value tag
$str .= pack('n', $nameLen); // Attribute key length
$str .= pack('a' . $nameLen, $_name); // Attribute key

$class = $value::class;
$str .= (new $class($value->value[$i]))->encode();
$str .= $values[$i]->encode();
}
return $str;
}
Expand Down
4 changes: 2 additions & 2 deletions src/Api/Cups/Request.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public function setRequestId(int $requestId)
}

/**
* @param array<string, \Rawilk\Printing\Api\Cups\Type> $attributes
* @param array<string, \Rawilk\Printing\Api\Cups\Type|\Rawilk\Printing\Api\Cups\Type[]>> $attributes
*/
public function addOperationAttributes(array $attributes)
{
Expand All @@ -71,7 +71,7 @@ public function addOperationAttributes(array $attributes)
}

/**
* @param array<string, \Rawilk\Printing\Api\Cups\Type> $attributes
* @param array<string, \Rawilk\Printing\Api\Cups\Type|\Rawilk\Printing\Api\Cups\Type[]> $attributes
*/
public function addJobAttributes(array $attributes)
{
Expand Down
13 changes: 5 additions & 8 deletions src/Api/Cups/Response.php
Original file line number Diff line number Diff line change
Expand Up @@ -84,17 +84,14 @@ private function extractAttributes(string $binary, int &$offset, mixed &$nextTag

// Array of values
if ($attrName === '') {
$lastAttr = $attributes[array_key_last($attributes)];
$index = array_key_last($attributes);
$lastAttr = $attributes[$index];

if ($typeTag !== TypeTag::RANGEOFINTEGER->value && gettype($lastAttr->value) !== 'array') {
$lastAttr->value = [$lastAttr->value];
if (!is_array($lastAttr)) {
$attributes[$index] = [$lastAttr];
}

if ($typeTag == TypeTag::RANGEOFINTEGER->value) {
$lastAttr->value[] = $attribute->value[0];
} else {
$lastAttr->value[] = $attribute->value;
}
$attributes[$index][] = $attribute;
} else {
$attributes[$attrName] = $attribute;
}
Expand Down
38 changes: 14 additions & 24 deletions src/Api/Cups/Types/RangeOfInteger.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Rawilk\Printing\Api\Cups\Types;

use Rawilk\Printing\Api\Cups\Exceptions\RangeOverlap;
use Rawilk\Printing\Api\Cups\Type;
use Rawilk\Printing\Api\Cups\TypeTag;

Expand All @@ -12,12 +13,10 @@ class RangeOfInteger extends Type
protected int $tag = TypeTag::RANGEOFINTEGER->value;

/**
* @param array<int, int[]>|int[] $value
* @param int[] $value - Array of 2 integers
*/
public function __construct(public mixed $value)
{
parent::__construct($value);
$this->checkOverlaps();
}

public function encode(): string
Expand All @@ -28,36 +27,27 @@ public function encode(): string
public static function fromBinary(string $binary, ?int $length = null): self
{
$value = unpack('Nl/Nu', $binary);
return new static([[$value['l'], $value['u']]]);
return new static([$value['l'], $value['u']]);
}

public function addRange($lower, $upper)
{
$this->value[] = [$lower, $upper];
$this->checkOverlaps();
}

private function sortValues()
/**
* Sorts and checks the array for overlaps
*
* @param array<int, RangeOfInteger> $values
* @throws RangeOverlap
*/
public static function checkOverlaps(array &$values)
{
usort(
$this->value,
$values,
function ($a, $b) {
return $a[0] - $b[0];
return $a->value[0] - $b->value[0];
}
);
}

private function checkOverlaps()
{
if (gettype($this->value[0]) !== 'array') {
return;
}
$this->sortValues();
$ranges = $this->value;

$count = count($ranges);
$count = count($values);
for ($i = 0; $i < $count - 1; $i++) {
if ($ranges[$i][1] >= $ranges[$i + 1][0]) {
if ($values[$i]->value[1] >= $values[$i + 1]->value[0]) {
throw new \Rawilk\Printing\Api\Cups\Exceptions\RangeOverlap('Range overlap is not allowed!');
}
}
Expand Down
34 changes: 24 additions & 10 deletions src/Drivers/Cups/Cups.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,19 @@ public function printJob($jobId = null): ?PrintJob
$request = new Request();
$request->setVersion(Version::V1_1)
->setOperation(Operation::GET_JOB_ATTRIBUTES)
->addOperationAttributes(
[
->addOperationAttributes([
'job-uri' => new Uri($jobId),
'requested-attributes' => new Keyword(['job-uri', 'job-state', 'number-of-documents', 'job-name', 'document-format', 'date-time-at-creation', 'job-printer-state-message', 'job-printer-uri']),
]
);
'requested-attributes' => [
new Keyword('job-uri'),
new Keyword('job-state'),
new Keyword('number-of-documents'),
new Keyword('job-name'),
new Keyword('document-format'),
new Keyword('date-time-at-creation'),
new Keyword('job-printer-state-message'),
new Keyword('job-printer-uri')
],
]);

return $this->api->makeRequest($request)->getJobs()->first();
}
Expand All @@ -82,13 +89,20 @@ public function printerPrintJobs($printerId, ?int $limit = null, ?int $offset =
$request = new Request();
$request->setVersion(Version::V1_1)
->setOperation(Operation::GET_JOBS)
->addOperationAttributes(
[
->addOperationAttributes([
'printer-uri' => new Uri($printerId),
'which-jobs' => new Keyword('not-completed'),
'requested-attributes' => new Keyword(['job-uri', 'job-state', 'number-of-documents', 'job-name', 'document-format', 'date-time-at-creation', 'job-printer-state-message', 'job-printer-uri']),
]
);
'requested-attributes' => [
new Keyword('job-uri'),
new Keyword('job-state'),
new Keyword('number-of-documents'),
new Keyword('job-name'),
new Keyword('document-format'),
new Keyword('date-time-at-creation'),
new Keyword('job-printer-state-message'),
new Keyword('job-printer-uri')
],
]);

return $this->api->makeRequest($request)->getJobs();
}
Expand Down
9 changes: 6 additions & 3 deletions src/Drivers/Cups/PrintTask.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ public function orientation(string $value): self

/**
* @param string $key
* @param Type $value
* @param Type|Type[] $value
*/
public function option(string $key, $value): self
{
Expand All @@ -84,9 +84,12 @@ public function copies(int $copies): self
public function range($start, $end = null): self
{
if (!array_key_exists('page-ranges', $this->options)) {
$this->options['page-ranges'] = new RangeOfInteger([[$start, $end]]);
$this->options['page-ranges'] = new RangeOfInteger([$start, $end]);
} else {
$this->options['page-ranges']->addRange($start, $end);
if (!is_array($this->options['page-ranges'])) {
$this->options['page-ranges'] = [$this->options['page-ranges']];
}
$this->options['page-ranges'][] = new RangeOfInteger([$start, $end]);
}
return $this;
}
Expand Down

0 comments on commit b5609b7

Please sign in to comment.