Skip to content
Merged
53 changes: 1 addition & 52 deletions phpcs.xml
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,6 @@
</properties>
</rule>

<!-- All PHP files MUST end with a non-blank line, terminated with a single LF. -->
<rule ref="PSR2.Files.EndFileNewline"/>

<!-- The closing ?> tag MUST be omitted from files containing only PHP. -->
<rule ref="PSR2.Files.ClosingTag"/>

<!-- 2.3 Lines -->

<!--Lines SHOULD NOT be longer than 80 characters; lines longer than that SHOULD be split into multiple subsequent lines of no more than 80 characters each. -->
Expand Down Expand Up @@ -117,13 +111,6 @@

<!-- 4.1 Extends and Implements -->

<!-- The extends and implements keywords MUST be declared on the same line as the class name. -->
<!-- The opening brace for the class MUST go on its own line; the closing brace for the class MUST go on the next line after the body. -->
<!-- Opening braces MUST be on their own line and MUST NOT be preceded or followed by a blank line. -->
<!-- Closing braces MUST be on their own line and MUST NOT be preceded by a blank line. -->
<!-- Lists of implements and, in the case of interfaces, extends MAY be split across multiple lines, where each subsequent line is indented once. When doing so, the first item in the list MUST be on the next line, and there MUST be only one interface per line. -->
<!-- checked by PSR12.Classes.OpeningBraceSpace -->
<rule ref="PSR2.Classes.ClassDeclaration"/>

<!-- 4.2 Using traits -->

Expand All @@ -135,16 +122,8 @@

<!-- 4.3 Properties and Constants -->

<!-- Visibility MUST be declared on all properties. -->
<!-- The var keyword MUST NOT be used to declare a property. -->
<!-- There MUST NOT be more than one property declared per statement. -->
<!-- Property names MUST NOT be prefixed with a single underscore to indicate protected or private visibility.
That is, an underscore prefix explicitly has no meaning. -->
<!-- There MUST be a space between type declaration and property name. -->
<rule ref="PSR2.Classes.PropertyDeclaration"/>

<!-- Visibility MUST be declared on all constants if your project PHP minimum version supports constant visibilities (PHP 7.1 or later). -->
<!-- checked by PSR12.Properties.ConstantVisibility -->
<rule ref="PSR12.Properties.ConstantVisibility"/>

<!-- 4.4 Methods and Functions -->

Expand All @@ -155,15 +134,6 @@
<exclude name="Squiz.Commenting.FunctionComment.InvalidReturn"/>
<exclude name="Squiz.Commenting.FunctionComment.IncorrectParamVarName"/>

<!-- Method names MUST NOT be prefixed with a single underscore to indicate protected or private visibility. That is, an underscore prefix explicitly has no meaning. -->
<rule ref="PSR2.Methods.MethodDeclaration"/>
<rule ref="PSR2.Methods.MethodDeclaration.Underscore">
<type>error</type>
<message>Method name "%s" must not be prefixed with an underscore to indicate visibility</message>
</rule>

<!-- Method and function names MUST NOT be declared with space after the method name. The opening brace MUST go on its own line, and the closing brace MUST go on the next line following the body. There MUST NOT be a space after the opening parenthesis, and there MUST NOT be a space before the closing parenthesis. -->
<rule ref="PSR2.Methods.FunctionClosingBrace"/>
<rule ref="Squiz.Functions.FunctionDeclaration"/>
<rule ref="Squiz.Functions.LowercaseFunctionKeywords"/>

Expand Down Expand Up @@ -196,20 +166,12 @@

<!-- When present, the abstract and final declarations MUST precede the visibility declaration. -->
<!-- When present, the static declaration MUST come after the visibility declaration. -->
<!-- checked by PSR2.Methods.MethodDeclaration included above -->

<!-- 4.7 Method and Function Calls -->

<!-- When making a method or function call, there MUST NOT be a space between the method or function name and the opening parenthesis, there MUST NOT be a space after the opening parenthesis, and there MUST NOT be a space before the closing parenthesis. In the argument list, there MUST NOT be a space before each comma, and there MUST be one space after each comma. -->
<!-- Argument lists MAY be split across multiple lines, where each subsequent line is indented once. When doing so, the first item in the list MUST be on the next line, and there MUST be only one argument per line. A single argument being split across multiple lines (as might be the case with an anonymous function or array) does not constitute splitting the argument list itself. -->
<rule ref="Generic.Functions.FunctionCallArgumentSpacing"/>
<rule ref="PSR2.Methods.FunctionCallSignature"/>
<rule ref="PSR2.Methods.FunctionCallSignature.SpaceAfterCloseBracket">
<severity>0</severity>
</rule>
<rule ref="PSR2.Methods.FunctionCallSignature.OpeningIndent">
<severity>0</severity>
</rule>

<!-- 5. Control Structures -->

Expand Down Expand Up @@ -251,8 +213,6 @@
<!-- else and elseif are on the same line as the closing brace from the earlier body. -->
<!-- checked by Squiz.ControlStructures.ControlSignature included above -->

<!-- The keyword elseif SHOULD be used instead of else if so that all control keywords look like single words. -->
<rule ref="PSR2.ControlStructures.ElseIfDeclaration"/>

<!-- Expressions in parentheses MAY be split across multiple lines, where each subsequent line is indented at least once. When doing so, the first condition MUST be on the next line. The closing parenthesis and opening brace MUST be placed together on their own line with one space between them. Boolean operators between conditions MUST always be at the beginning or at the end of the line, not a mix of both. -->
<!-- checked by PSR12.ControlStructures.ControlStructureSpacing -->
Expand All @@ -261,9 +221,6 @@

<!-- 5.2 switch, case -->

<!-- The case statement MUST be indented once from switch, and the break keyword (or other terminating keywords) MUST be indented at the same level as the case body. There MUST be a comment such as // no break when fall-through is intentional in a non-empty case body. -->
<rule ref="PSR2.ControlStructures.SwitchDeclaration"/>

<!-- Expressions in parentheses MAY be split across multiple lines, where each subsequent line is indented at least once. When doing so, the first condition MUST be on the next line. The closing parenthesis and opening brace MUST be placed together on their own line with one space between them. Boolean operators between conditions MUST always be at the beginning or at the end of the line, not a mix of both. -->
<!-- checked by PSR12.ControlStructures.ControlStructureSpacing -->
<!-- checked by PSR12.ControlStructures.BooleanOperatorPlacement -->
Expand Down Expand Up @@ -292,14 +249,6 @@

<!-- 5.5 foreach -->

<!-- exclude these messages as they are already checked by PSR2.ControlStructures.ControlStructureSpacing -->
<rule ref="Squiz.ControlStructures.ForEachLoopDeclaration.SpaceAfterOpen">
<severity>0</severity>
</rule>
<rule ref="Squiz.ControlStructures.ForEachLoopDeclaration.SpaceBeforeClose">
<severity>0</severity>
</rule>

<!-- 5.6 try, catch, finally -->

<!-- 6. Operators -->
Expand Down
8 changes: 5 additions & 3 deletions src/Client.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@
*/
class Client
{
use CustomSleepMixin;

/**
* Default owner for API products.
*
Expand Down Expand Up @@ -463,7 +465,7 @@ public function enqueueAndParse(
);
error_log("Successfully enqueued document with job id: " . $enqueueResponse->job->id);

sleep($asyncOptions->initialDelaySec);
$this->customSleep($asyncOptions->initialDelaySec);
$retryCounter = 1;
$pollResults = $this->parseQueued($predictionType, $enqueueResponse->job->id, $options->endpoint);

Expand All @@ -473,7 +475,7 @@ public function enqueueAndParse(
}
error_log("Polling server for parsing result with job id: " . $enqueueResponse->job->id);
$retryCounter++;
sleep($asyncOptions->delaySec);
$this->customSleep($asyncOptions->delaySec);
$pollResults = $this->parseQueued($predictionType, $enqueueResponse->job->id, $options->endpoint);
}
if ($pollResults->job->status != "completed") {
Expand Down Expand Up @@ -540,7 +542,7 @@ public function parseQueued(
public function loadPrediction(
string $predictionType,
LocalResponse $localResponse
) {
): AsyncPredictResponse|PredictResponse {
try {
$json = $localResponse->toArray();
if (isset($json['job'])) {
Expand Down
6 changes: 4 additions & 2 deletions src/ClientV2.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
*/
class ClientV2
{
use CustomSleepMixin;

/**
* @var MindeeApiV2 Mindee API V2.
*/
Expand Down Expand Up @@ -96,7 +98,7 @@ public function enqueueAndGetInference(
$queueId = $enqueueResponse->job->id;
error_log("Successfully enqueued document with job id: " . $queueId);

sleep($pollingOptions->initialDelaySec);
$this->customSleep($pollingOptions->initialDelaySec);
$retryCounter = 1;
$pollResults = $this->getJob($queueId);

Expand All @@ -114,7 +116,7 @@ public function enqueueAndGetInference(
". Job status: " . $pollResults->job->status
);

sleep($pollingOptions->delaySec);
$this->customSleep($pollingOptions->delaySec);
$pollResults = $this->getJob($queueId);
$retryCounter++;
}
Expand Down
27 changes: 27 additions & 0 deletions src/CustomSleepMixin.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

namespace Mindee;

trait CustomSleepMixin
{
/**
* Waits for a custom amount of time from either a float or an integer.
* @param float|integer $delay Delay in seconds.
* @return void
*/
protected static function customSleep(float|int $delay): void
{
if ($delay <= 0) {
return;
}

$seconds = intval($delay);
$nanoseconds = abs($seconds - (float) $delay);
if (
strtoupper(substr(PHP_OS_FAMILY, 0, 7)) === 'WINDOWS'
) {
usleep(1000);
}
time_nanosleep($seconds, (int) ($nanoseconds * 1_000_000_000));
}
}
6 changes: 5 additions & 1 deletion src/Parsing/Common/Job.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ class Job
* @var array|null Information about an error that occurred during the job processing.
*/
public ?array $error;

/**
* @param array $rawResponse Raw prediction array.
* @throws MindeeApiException Throws if a date is faulty.
Expand All @@ -58,7 +59,10 @@ public function __construct(array $rawResponse)
}
$this->id = $rawResponse['id'];
$this->status = $rawResponse['status'];
if (array_key_exists('available_at', $rawResponse) && $rawResponse['available_at'] !== null && strtotime($rawResponse['available_at'])) {
if (
array_key_exists('available_at', $rawResponse) &&
$rawResponse['available_at'] !== null && strtotime($rawResponse['available_at'])
) {
try {
$this->availableAt = new DateTimeImmutable($rawResponse['available_at']);
} catch (\Exception $e) {
Expand Down
70 changes: 70 additions & 0 deletions tests/CustomSleepMixinTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<?php

use PHPUnit\Framework\TestCase;

/**
* Custom delay tests.
* Note: Timers are purposefully kept loose due to frequent CI issues.
*/
class CustomSleepMixinTest extends TestCase
{
use Mindee\CustomSleepMixin;

public function testCustomSleep1Second(): void {
$lowerBound = 1;
$upperBound = 1.1;

$start = microtime(true);
$this->customSleep(1);
$elapsed = microtime(true) - $start;
$this->assertGreaterThanOrEqual($lowerBound, $elapsed);
$this->assertLessThanOrEqual($upperBound, $elapsed);
}

public function testCustomSleep0dot33Seconds(): void {
$lowerBound = 0.33;
$upperBound = 0.43;

$start = microtime(true);
$this->customSleep(0.33);
$elapsed = microtime(true) - $start;
$this->assertGreaterThanOrEqual($lowerBound, $elapsed);
$this->assertLessThanOrEqual($upperBound, $elapsed);
}

public function testCustomSleep2Seconds(): void {
$lowerBound = 2;
$upperBound = 2.1;

$start = microtime(true);
$this->customSleep(2);
$elapsed = microtime(true) - $start;
$this->assertGreaterThanOrEqual($lowerBound, $elapsed);
$this->assertLessThanOrEqual($upperBound, $elapsed);
}

public function testCustomSleep1dot5Seconds(): void {
$lowerBound = 1.5;
$upperBound = 1.6;

$start = microtime(true);
$this->customSleep(1.5);
$elapsed = microtime(true) - $start;
$this->assertGreaterThanOrEqual($lowerBound, $elapsed);
$this->assertLessThanOrEqual($upperBound, $elapsed);
}

public function testCustomSleep0Seconds(): void {
$start = microtime(true);
$this->customSleep(0);
$elapsed = microtime(true) - $start;
$this->assertLessThanOrEqual(0.0001, $elapsed);
}

public function testCustomSleepMinus1Seconds(): void {
$start = microtime(true);
$this->customSleep(-1);
$elapsed = microtime(true) - $start;
$this->assertLessThanOrEqual(0.0001, $elapsed);
}
}
2 changes: 1 addition & 1 deletion tests/Input/URLInputSourceTestFunctional.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ protected function setUp(): void
$this->client = new Client();
$this->outputFilePath = (getenv('GITHUB_WORKSPACE') ?: ".") .
"/tests/resources/output/";
$this->referenceFilePath = "https://github.com/mindee/client-lib-test-data/blob/main/products/invoice_splitter/invoice_5p.pdf?raw=true";
$this->referenceFilePath = "https://github.com/mindee/client-lib-test-data/blob/main/v1/products/invoice_splitter/invoice_5p.pdf?raw=true";
}

public static function tearDownAfterClass(): void
Expand Down