Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@
"guzzlehttp/psr7": "^2.6.2"
},
"require-dev": {
"mockery/mockery": "^1.6.7",
"nette/di": "^3.1.8",
"contributte/phpstan": "^0.2.0",
"contributte/qa": "^0.4",
"contributte/tester": "^0.4",
"contributte/phpstan": "^0.1"
"mockery/mockery": "^1.6.7",
"nette/di": "^3.1.8"
},
"autoload": {
"psr-4": {
Expand Down
1 change: 1 addition & 0 deletions phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,6 @@ parameters:
paths:
- src
- .docs
- tests/Cases

ignoreErrors:
2 changes: 1 addition & 1 deletion src/Entity/AbstractEntity.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ abstract class AbstractEntity
{

/**
* @return mixed[]
* @return array<string, mixed>
*/
abstract public function toArray(): array;

Expand Down
14 changes: 12 additions & 2 deletions src/Entity/AbstractPayment.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class AbstractPayment extends AbstractEntity

protected ?int $price = null;

/** @var string ISO 4217 */
/** @see https://cs.wikipedia.org/wiki/ISO_4217 */
protected ?string $curr = null;

protected ?string $label = null;
Expand Down Expand Up @@ -119,7 +119,17 @@ public function setName(string $name): void
}

/**
* @return mixed[]
* @return array{
* price: ?int,
* curr: ?string,
* label: ?string,
* refId: ?string,
* email: ?string,
* fullName: ?string,
* country: ?string,
* account: ?string,
* name: ?string,
* }
*/
public function toArray(): array
{
Expand Down
96 changes: 91 additions & 5 deletions src/Entity/Payment.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class Payment extends AbstractPayment

private string $method = PaymentMethodCode::ALL;

/** @var string ISO 639-1 */
/** @see https://cs.wikipedia.org/wiki/ISO_639-1 */
private string $lang = LangCode::CS;

private bool $prepareOnly = true;
Expand All @@ -26,6 +26,14 @@ class Payment extends AbstractPayment

private bool $embedded = false;

private bool $chargeUnregulatedCardFees;

private string $urlPaid;

private string $urlCancelled;

private string $urlPending;
Comment on lines +29 to +35
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Uninitialized typed properties will cause fatal errors.

The new properties are declared as non-nullable types without default values, creating uninitialized typed properties. Calling the getter methods (lines 132-170) before the setters will trigger: Error: Typed property must not be accessed before initialization.

This breaks the pattern established by existing properties like prepareOnly, preauth, etc., which all have default values.

Apply this diff to make properties nullable with safe defaults:

-	private bool $chargeUnregulatedCardFees;
+	private ?bool $chargeUnregulatedCardFees = null;
 
-	private string $urlPaid;
+	private ?string $urlPaid = null;
 
-	private string $urlCancelled;
+	private ?string $urlCancelled = null;
 
-	private string $urlPending;
+	private ?string $urlPending = null;

Then update getter return types to match:

public function isChargeUnregulatedCardFees(): ?bool
{
	return $this->chargeUnregulatedCardFees;
}

public function getUrlPaid(): ?string
{
	return $this->urlPaid;
}

public function getUrlCancelled(): ?string
{
	return $this->urlCancelled;
}

public function getUrlPending(): ?string
{
	return $this->urlPending;
}
🤖 Prompt for AI Agents
In src/Entity/Payment.php around lines 29 to 35, the new properties are declared
as non-nullable without defaults which creates uninitialized typed properties
and will throw if getters are called before setters; change the property
declarations to nullable types with safe defaults (e.g., ?bool
$chargeUnregulatedCardFees = null; ?string $urlPaid = null; ?string
$urlCancelled = null; ?string $urlPending = null) and update the corresponding
getter return types to nullable (isChargeUnregulatedCardFees(): ?bool,
getUrlPaid(): ?string, getUrlCancelled(): ?string, getUrlPending(): ?string) so
they safely return null until set.


Comment on lines +29 to +36
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Uninitialized typed properties will cause runtime errors.

These properties lack default values and are not initialized in the constructor. Calling their getters (lines 132-170) before their setters will throw a TypeError because PHP typed properties must be initialized before access.

Apply this diff to provide safe defaults:

-	private bool $chargeUnregulatedCardFees;
+	private ?bool $chargeUnregulatedCardFees = null;
 
-	private string $urlPaid;
+	private ?string $urlPaid = null;
 
-	private string $urlCancelled;
+	private ?string $urlCancelled = null;
 
-	private string $urlPending;
+	private ?string $urlPending = null;

Then update the getter return types accordingly:

-	public function isChargeUnregulatedCardFees(): bool
+	public function isChargeUnregulatedCardFees(): ?bool

-	public function getUrlPaid(): string
+	public function getUrlPaid(): ?string

-	public function getUrlCancelled(): string
+	public function getUrlCancelled(): ?string

-	public function getUrlPending(): string
+	public function getUrlPending(): ?string

Committable suggestion skipped: line range outside the PR's diff.

final private function __construct()
{
// Noop
Expand All @@ -39,7 +47,7 @@ public static function of(
string $fullName,
string $method = PaymentMethodCode::ALL,
string $country = CountryCode::ALL,
string $lang = LangCode::CS
string $lang = LangCode::CS,
): self
{
$p = new static();
Expand Down Expand Up @@ -121,20 +129,98 @@ public function setEmbedded(bool $embedded): void
$this->embedded = $embedded;
}

public function isChargeUnregulatedCardFees(): bool
{
return $this->chargeUnregulatedCardFees;
}

public function setChargeUnregulatedCardFees(bool $chargeUnregulatedCardFees): void
{
$this->chargeUnregulatedCardFees = $chargeUnregulatedCardFees;
}

public function getUrlPaid(): string
{
return $this->urlPaid;
}

public function setUrlPaid(string $urlPaid): void
{
$this->urlPaid = $urlPaid;
}

public function getUrlCancelled(): string
{
return $this->urlCancelled;
}

public function setUrlCancelled(string $urlCancelled): void
{
$this->urlCancelled = $urlCancelled;
}

public function getUrlPending(): string
{
return $this->urlPending;
}

public function setUrlPending(string $urlPending): void
{
$this->urlPending = $urlPending;
}

/**
* @return mixed[]
* @return array{
* price: ?int,
* curr: ?string,
* label: ?string,
* refId: ?string,
* email: ?string,
* fullName: ?string,
* country: ?string,
* account: ?string,
* name: ?string,
* method: string,
* lang: string,
* prepareOnly: string,
* preauth: string,
* initRecurring: string,
* verification: string,
* embedded: string,
* chargeUnregulatedCardFees?: string,
* url_paid?: string,
* url_cancelled?: string,
* url_pending?: string,
* }
*/
public function toArray(): array
{
return array_merge(parent::toArray(), [
$data = [
'method' => $this->method,
'lang' => $this->lang,
'prepareOnly' => $this->prepareOnly ? 'true' : 'false',
'preauth' => $this->preauth ? 'true' : 'false',
'initRecurring' => $this->initRecurring ? 'true' : 'false',
'verification' => $this->verification ? 'true' : 'false',
'embedded' => $this->embedded ? 'true' : 'false',
]);
];
if (isset($this->chargeUnregulatedCardFees)) {
$data['chargeUnregulatedCardFees'] = $this->chargeUnregulatedCardFees ? 'true' : 'false';
}

if (isset($this->urlPaid)) {
$data['url_paid'] = $this->urlPaid;
}

if (isset($this->urlCancelled)) {
$data['url_cancelled'] = $this->urlCancelled;
}

if (isset($this->urlPending)) {
$data['url_pending'] = $this->urlPending;
}

return array_merge(parent::toArray(), $data);
}

}
6 changes: 4 additions & 2 deletions src/Entity/PaymentStatus.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,10 @@ public function getTransId(): string
}

/**
* @return mixed[]
*/
* @return array{
* transId: string,
* }
**/
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix non-standard docblock closing syntax.

The docblock closing uses **/ instead of the standard */.

Apply this diff:

- **/
+ */
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
**/
*/
🤖 Prompt for AI Agents
In src/Entity/PaymentStatus.php around line 32, the docblock closing uses
non-standard "**/" instead of the correct "*/"; edit the file and replace the
incorrect closing token with the standard "*/" so the docblock is properly
terminated and tools/parser recognize it.

public function toArray(): array
{
return [
Expand Down
16 changes: 14 additions & 2 deletions src/Entity/RecurringPayment.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,20 @@ public function getInitRecurringId(): string
}

/**
* @return mixed[]
*/
* @return array{
* price: ?int,
* curr: ?string,
* label: ?string,
* refId: ?string,
* email: ?string,
* fullName: ?string,
* country: ?string,
* account: ?string,
* name: ?string,
* prepareOnly: string,
* initRecurringId: string,
* }
**/
public function toArray(): array
{
return array_merge(parent::toArray(), [
Expand Down
9 changes: 7 additions & 2 deletions src/Entity/Refund.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class Refund extends AbstractEntity

private int $amount;

/** @var string ISO 4217 */
/** @see https://cs.wikipedia.org/wiki/ISO_4217 */
private string $curr;

private string $transId;
Expand Down Expand Up @@ -58,7 +58,12 @@ public function getRefId(): ?string
}

/**
* @return mixed[]
* @return array{
* amount: float,
* curr: string,
* transId: string,
* refId: ?string
* }
Comment on lines 60 to +66
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Type mismatch in PHPDoc for amount field.

The docblock declares amount: float, but the property is typed as int (Line 11) and is returned as-is without conversion. This creates a documentation inconsistency.

Apply this diff to correct the documentation:

 /**
  * @return array{
- *     amount: float,
+ *     amount: int,
  *     curr: string,
  *     transId: string,
  *     refId: ?string
  * }
  */
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/**
* @return mixed[]
* @return array{
* amount: float,
* curr: string,
* transId: string,
* refId: ?string
* }
/**
* @return array{
* amount: int,
* curr: string,
* transId: string,
* refId: ?string
* }
🤖 Prompt for AI Agents
In src/Entity/Refund.php around lines 60 to 66, the PHPDoc declares amount as
float while the Refund::$amount property is typed int (line 11) and returned
without conversion; update the PHPDoc to declare amount: int to match the
property (or alternatively cast/convert the property to float at return),
ensuring the docblock and actual return type are consistent.

Comment on lines +61 to +66
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix type mismatch in PHPDoc.

The PHPDoc specifies amount: float but the property is declared as int (line 11) and returned as int (line 71). This inconsistency could cause confusion and PHPStan warnings.

Apply this diff to fix the type mismatch:

 	/**
 	 * @return array{
-	 *     amount: float,
+	 *     amount: int,
 	 *     curr: string,
 	 *     transId: string,
 	 *     refId: ?string
 	 * }
 	 */
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
* @return array{
* amount: float,
* curr: string,
* transId: string,
* refId: ?string
* }
* @return array{
* amount: int,
* curr: string,
* transId: string,
* refId: ?string
* }
🤖 Prompt for AI Agents
In src/Entity/Refund.php around lines 61 to 66, the PHPDoc return type declares
amount as float but the property (line 11) and the actual return value (line 71)
are ints; update the PHPDoc to use amount: int so the docblock matches the
property and returned type (ensure the rest of the return shape remains
unchanged).

*/
public function toArray(): array
{
Expand Down
4 changes: 3 additions & 1 deletion src/Entity/Storno.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ public function getTransId(): string
}

/**
* @return mixed[]
* @return array{
* transId: string,
* }
*/
public function toArray(): array
{
Expand Down
3 changes: 1 addition & 2 deletions tests/Cases/E2E/payments.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,10 @@ function createPayment(): void
);
$res1 = $payments->create($payment);
assert($res1->isOk() === true);
// var_dump($res->getData());

assert(array_key_exists('transId', $res1->getData()));
$res2 = $payments->status(PaymentStatus::of($res1->getData()['transId']));
assert($res2->isOk() === true);
// var_dump($res2->getData());
}

(function (): void {
Expand Down
34 changes: 34 additions & 0 deletions tests/Cases/Entity/Payment.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -138,3 +138,37 @@ Toolkit::test(function (): void {
$payment->setLang(LangCode::PL);
Assert::equal('pl', $payment->toArray()['lang']);
});

Toolkit::test(function (): void {
$payment = Payment::of(
Money::of(50, 'CZK'),
'Test item',
'order101',
'dev@contributte.org',
'John Doe',
);
$payment->setChargeUnregulatedCardFees(true);
Assert::hasKey('chargeUnregulatedCardFees', $payment->toArray());
Assert::equal('true', $payment->toArray()['chargeUnregulatedCardFees']);
});

Toolkit::test(function (): void {
$payment = Payment::of(
Money::of(50, 'CZK'),
'Test item',
'order101',
'dev@contributte.org',
'John Doe',
);
$payment->setUrlPaid('https://example.com/paid');
$payment->setUrlCancelled('https://example.com/cancelled');
$payment->setUrlPending('https://example.com/pending');

Assert::hasKey('url_paid', $payment->toArray());
Assert::hasKey('url_cancelled', $payment->toArray());
Assert::hasKey('url_pending', $payment->toArray());

Assert::equal('https://example.com/paid', $payment->toArray()['url_paid']);
Assert::equal('https://example.com/cancelled', $payment->toArray()['url_cancelled']);
Assert::equal('https://example.com/pending', $payment->toArray()['url_pending']);
});