Skip to content

Commit caeb3d7

Browse files
authored
Merge pull request #672 from DannyvdSluijs/add-phpstan
Add PHPStan
2 parents 05412be + 2952983 commit caeb3d7

File tree

10 files changed

+244
-41
lines changed

10 files changed

+244
-41
lines changed
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
name: Run static analysis
2+
3+
on: [pull_request]
4+
5+
jobs:
6+
static-analysis:
7+
name: Static analysis
8+
runs-on: ubuntu-latest
9+
10+
steps:
11+
- name: Checkout code
12+
uses: actions/checkout@v4
13+
14+
- name: Setup PHP
15+
uses: shivammathur/setup-php@v2
16+
with:
17+
php-version: 7.4
18+
19+
- name: Composer install
20+
run: composer install --prefer-dist --no-interaction --no-progress --no-suggest
21+
22+
- name: Run static analysis
23+
run: vendor/bin/phpstan

composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
"ext-json": "*"
2222
},
2323
"require-dev": {
24+
"phpstan/phpstan": "^2.1",
2425
"phpunit/phpunit": "^9.6"
2526
},
2627
"autoload": {

example/example.php

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,27 +8,28 @@
88
*
99
* @param string $key
1010
*
11-
* @return null|string
11+
* @return null|string|int
1212
*/
13-
function getValue($key)
13+
function getValue(string $key)
1414
{
15-
$storage = json_decode(file_get_contents('storage.json'), true);
15+
$storage = json_decode(file_get_contents('storage.json'), true, 512, JSON_THROW_ON_ERROR);
1616
if (array_key_exists($key, $storage)) {
1717
return $storage[$key];
1818
}
19+
20+
return null;
1921
}
2022

2123
/**
2224
* Function to persist some data for the example.
2325
*
24-
* @param string $key
25-
* @param string $value
26+
* @param string|int $value
2627
*/
27-
function setValue($key, $value)
28+
function setValue(string $key, $value)
2829
{
29-
$storage = json_decode(file_get_contents('storage.json'), true);
30+
$storage = json_decode(file_get_contents('storage.json'), true, 512, JSON_THROW_ON_ERROR);
3031
$storage[$key] = $value;
31-
file_put_contents('storage.json', json_encode($storage));
32+
file_put_contents('storage.json', json_encode($storage, JSON_THROW_ON_ERROR));
3233
}
3334

3435
/**
@@ -46,10 +47,8 @@ function authorize()
4647

4748
/**
4849
* Callback function that sets values that expire and are refreshed by Connection.
49-
*
50-
* @param \Picqer\Financials\Exact\Connection $connection
5150
*/
52-
function tokenUpdateCallback(\Picqer\Financials\Exact\Connection $connection)
51+
function tokenUpdateCallback(\Picqer\Financials\Exact\Connection $connection): void
5352
{
5453
// Save the new tokens for next connections
5554
setValue('accesstoken', $connection->getAccessToken());
@@ -63,10 +62,8 @@ function tokenUpdateCallback(\Picqer\Financials\Exact\Connection $connection)
6362
* Function to connect to Exact, this creates the client and automatically retrieves oAuth tokens if needed.
6463
*
6564
* @throws Exception
66-
*
67-
* @return \Picqer\Financials\Exact\Connection
6865
*/
69-
function connect()
66+
function connect(): \Picqer\Financials\Exact\Connection
7067
{
7168
$connection = new \Picqer\Financials\Exact\Connection();
7269
$connection->setRedirectUrl('__REDIRECT_URL__');
@@ -111,7 +108,7 @@ function connect()
111108
setValue('authorizationcode', $_GET['code']);
112109
}
113110

114-
// If we do not have a authorization code, authorize first to setup tokens
111+
// If we do not have an authorization code, authorize first to set up tokens
115112
if (getValue('authorizationcode') === null) {
116113
authorize();
117114
}

phpstan-baseline.neon

Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
parameters:
2+
ignoreErrors:
3+
-
4+
message: '#^PHPDoc tag @property for property Picqer\\Financials\\Exact\\AssemblyOrder\:\:\$PartItems contains unknown class Picqer\\Financials\\Exact\\PartItem\.$#'
5+
identifier: class.notFound
6+
count: 1
7+
path: src/Picqer/Financials/Exact/AssemblyOrder.php
8+
9+
-
10+
message: '#^PHPDoc tag @property for property Picqer\\Financials\\Exact\\BulkGoodsDelivery\:\:\$GoodsDeliveryLines contains unknown class Picqer\\Financials\\Exact\\goodsdeliverylines\.$#'
11+
identifier: class.notFound
12+
count: 1
13+
path: src/Picqer/Financials/Exact/BulkGoodsDelivery.php
14+
15+
-
16+
message: '#^PHPDoc tag @property for property Picqer\\Financials\\Exact\\BulkGoodsDeliveryLine\:\:\$BatchNumbers contains unknown class Picqer\\Financials\\Exact\\stockbatchnumbers\.$#'
17+
identifier: class.notFound
18+
count: 1
19+
path: src/Picqer/Financials/Exact/BulkGoodsDeliveryLine.php
20+
21+
-
22+
message: '#^PHPDoc tag @property for property Picqer\\Financials\\Exact\\BulkGoodsDeliveryLine\:\:\$SerialNumbers contains unknown class Picqer\\Financials\\Exact\\stockserialnumbers\.$#'
23+
identifier: class.notFound
24+
count: 1
25+
path: src/Picqer/Financials/Exact/BulkGoodsDeliveryLine.php
26+
27+
-
28+
message: '#^PHPDoc tag @property for property Picqer\\Financials\\Exact\\DigitalOrderPickingLine\:\:\$PickingLocations contains unknown class Picqer\\Financials\\Exact\\PickingLocation\.$#'
29+
identifier: class.notFound
30+
count: 1
31+
path: src/Picqer/Financials/Exact/DigitalOrderPickingLine.php
32+
33+
-
34+
message: '#^PHPDoc tag @property for property Picqer\\Financials\\Exact\\Division\:\:\$Class_01 contains unknown class Picqer\\Financials\\Exact\\divisionclasses\.$#'
35+
identifier: class.notFound
36+
count: 1
37+
path: src/Picqer/Financials/Exact/Division.php
38+
39+
-
40+
message: '#^PHPDoc tag @property for property Picqer\\Financials\\Exact\\Division\:\:\$Class_02 contains unknown class Picqer\\Financials\\Exact\\divisionclasses\.$#'
41+
identifier: class.notFound
42+
count: 1
43+
path: src/Picqer/Financials/Exact/Division.php
44+
45+
-
46+
message: '#^PHPDoc tag @property for property Picqer\\Financials\\Exact\\Division\:\:\$Class_03 contains unknown class Picqer\\Financials\\Exact\\divisionclasses\.$#'
47+
identifier: class.notFound
48+
count: 1
49+
path: src/Picqer/Financials/Exact/Division.php
50+
51+
-
52+
message: '#^PHPDoc tag @property for property Picqer\\Financials\\Exact\\Division\:\:\$Class_04 contains unknown class Picqer\\Financials\\Exact\\divisionclasses\.$#'
53+
identifier: class.notFound
54+
count: 1
55+
path: src/Picqer/Financials/Exact/Division.php
56+
57+
-
58+
message: '#^PHPDoc tag @property for property Picqer\\Financials\\Exact\\Division\:\:\$Class_05 contains unknown class Picqer\\Financials\\Exact\\divisionclasses\.$#'
59+
identifier: class.notFound
60+
count: 1
61+
path: src/Picqer/Financials/Exact/Division.php
62+
63+
-
64+
message: '#^PHPDoc tag @property for property Picqer\\Financials\\Exact\\Division\:\:\$HID contains unknown class Picqer\\Financials\\Exact\\int64\.$#'
65+
identifier: class.notFound
66+
count: 1
67+
path: src/Picqer/Financials/Exact/Division.php
68+
69+
-
70+
message: '#^PHPDoc tag @property for property Picqer\\Financials\\Exact\\ItemAssortment\:\:\$Properties contains unknown class Picqer\\Financials\\Exact\\Property\.$#'
71+
identifier: class.notFound
72+
count: 1
73+
path: src/Picqer/Financials/Exact/ItemAssortment.php
74+
75+
-
76+
message: '#^PHPDoc tag @property for property Picqer\\Financials\\Exact\\LogisticsReasonsCodes\:\:\$Types contains unknown class Picqer\\Financials\\Exact\\Type\.$#'
77+
identifier: class.notFound
78+
count: 1
79+
path: src/Picqer/Financials/Exact/LogisticsReasonsCodes.php
80+
81+
-
82+
message: '#^PHPDoc tag @property for property Picqer\\Financials\\Exact\\PayablesList\:\:\$Notes contains unknown class Picqer\\Financials\\Exact\\Note\.$#'
83+
identifier: class.notFound
84+
count: 1
85+
path: src/Picqer/Financials/Exact/PayablesList.php
86+
87+
-
88+
message: '#^PHPDoc tag @property for property Picqer\\Financials\\Exact\\PayablesListByAccount\:\:\$Notes contains unknown class Picqer\\Financials\\Exact\\Note\.$#'
89+
identifier: class.notFound
90+
count: 1
91+
path: src/Picqer/Financials/Exact/PayablesListByAccount.php
92+
93+
-
94+
message: '#^PHPDoc tag @property for property Picqer\\Financials\\Exact\\PayablesListByAccountAndAgeGroup\:\:\$Notes contains unknown class Picqer\\Financials\\Exact\\Note\.$#'
95+
identifier: class.notFound
96+
count: 1
97+
path: src/Picqer/Financials/Exact/PayablesListByAccountAndAgeGroup.php
98+
99+
-
100+
message: '#^PHPDoc tag @property for property Picqer\\Financials\\Exact\\PayablesListByAgeGroup\:\:\$Notes contains unknown class Picqer\\Financials\\Exact\\Note\.$#'
101+
identifier: class.notFound
102+
count: 1
103+
path: src/Picqer/Financials/Exact/PayablesListByAgeGroup.php
104+
105+
-
106+
message: '#^PHPDoc tag @property for property Picqer\\Financials\\Exact\\ProcessPayment\:\:\$PaymentIDs contains unknown class Picqer\\Financials\\Exact\\PaymentID\.$#'
107+
identifier: class.notFound
108+
count: 1
109+
path: src/Picqer/Financials/Exact/ProcessPayment.php
110+
111+
-
112+
message: '#^PHPDoc tag @property for property Picqer\\Financials\\Exact\\Project\:\:\$BudgetedHoursPerHourType contains unknown class Picqer\\Financials\\Exact\\BudgetedHoursPerHourType\.$#'
113+
identifier: class.notFound
114+
count: 1
115+
path: src/Picqer/Financials/Exact/Project.php
116+
117+
-
118+
message: '#^PHPDoc tag @property for property Picqer\\Financials\\Exact\\ReasonForLogistic\:\:\$Types contains unknown class Picqer\\Financials\\Exact\\Type\.$#'
119+
identifier: class.notFound
120+
count: 1
121+
path: src/Picqer/Financials/Exact/ReasonForLogistic.php
122+
123+
-
124+
message: '#^PHPDoc tag @property for property Picqer\\Financials\\Exact\\ReceivablesList\:\:\$Notes contains unknown class Picqer\\Financials\\Exact\\Note\.$#'
125+
identifier: class.notFound
126+
count: 1
127+
path: src/Picqer/Financials/Exact/ReceivablesList.php
128+
129+
-
130+
message: '#^PHPDoc tag @property for property Picqer\\Financials\\Exact\\ReceivablesListByAccount\:\:\$Notes contains unknown class Picqer\\Financials\\Exact\\Note\.$#'
131+
identifier: class.notFound
132+
count: 1
133+
path: src/Picqer/Financials/Exact/ReceivablesListByAccount.php
134+
135+
-
136+
message: '#^PHPDoc tag @property for property Picqer\\Financials\\Exact\\ReceivablesListByAccountAndAgeGroup\:\:\$Notes contains unknown class Picqer\\Financials\\Exact\\Note\.$#'
137+
identifier: class.notFound
138+
count: 1
139+
path: src/Picqer/Financials/Exact/ReceivablesListByAccountAndAgeGroup.php
140+
141+
-
142+
message: '#^PHPDoc tag @property for property Picqer\\Financials\\Exact\\ReceivablesListByAgeGroup\:\:\$Notes contains unknown class Picqer\\Financials\\Exact\\Note\.$#'
143+
identifier: class.notFound
144+
count: 1
145+
path: src/Picqer/Financials/Exact/ReceivablesListByAgeGroup.php
146+
147+
-
148+
message: '#^PHPDoc tag @property for property Picqer\\Financials\\Exact\\Schedule\:\:\$ScheduleEntries contains unknown class Picqer\\Financials\\Exact\\ScheduleEntry\.$#'
149+
identifier: class.notFound
150+
count: 1
151+
path: src/Picqer/Financials/Exact/Schedule.php
152+
153+
-
154+
message: '#^Class Picqer\\Financials\\Exact\\SalesOrderLine referenced with incorrect case\: Picqer\\Financials\\Exact\\SalesOrderline\.$#'
155+
identifier: class.nameCase
156+
count: 1
157+
path: src/Picqer/Financials/Exact/ShopOrder.php
158+
159+
-
160+
message: '#^PHPDoc tag @property for property Picqer\\Financials\\Exact\\ShopOrderRoutingStepPlan\:\:\$TimeTransactions contains unknown class Picqer\\Financials\\Exact\\TimeTransaction\.$#'
161+
identifier: class.notFound
162+
count: 1
163+
path: src/Picqer/Financials/Exact/ShopOrderRoutingStepPlan.php
164+
165+
-
166+
message: '#^PHPDoc tag @property for property Picqer\\Financials\\Exact\\User\:\:\$UserRoles contains unknown class Picqer\\Financials\\Exact\\UserRoles\.$#'
167+
identifier: class.notFound
168+
count: 1
169+
path: src/Picqer/Financials/Exact/User.php
170+
171+
-
172+
message: '#^Class Picqer\\Financials\\Exact\\VatPercentage referenced with incorrect case\: Picqer\\Financials\\Exact\\VATPercentage\.$#'
173+
identifier: class.nameCase
174+
count: 1
175+
path: src/Picqer/Financials/Exact/VatCode.php
176+
177+
-
178+
message: '#^Trait Picqer\\Financials\\Exact\\Webhook\\Authenticatable is used zero times and is not analysed\.$#'
179+
identifier: trait.unused
180+
count: 1
181+
path: src/Picqer/Financials/Exact/Webhook/Authenticatable.php

phpstan.dist.neon

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
includes:
2+
- phpstan-baseline.neon
3+
4+
parameters:
5+
level: 5
6+
paths:
7+
- example
8+
- src
9+
- tests
10+
phpVersion:
11+
min: 70400
12+
max: 80317

src/Picqer/Financials/Exact/Connection.php

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
use GuzzleHttp\HandlerStack;
1111
use GuzzleHttp\Psr7;
1212
use GuzzleHttp\Psr7\Request;
13-
use GuzzleHttp\Psr7\Response;
13+
use Psr\Http\Message\ResponseInterface;
1414

1515
/**
1616
* Class Connection.
@@ -72,29 +72,29 @@ class Connection
7272
private ?Client $client = null;
7373

7474
/**
75-
* @var callable(Connection)
75+
* @var callable(Connection): void|null
7676
*/
7777
private $tokenUpdateCallback;
7878

7979
/**
80-
* @var callable(Connection)
80+
* @var callable(Connection): void|null
8181
*/
8282
private $acquireAccessTokenLockCallback;
8383

8484
/**
85-
* @var callable(Connection)
85+
* @var callable(Connection): void|null
8686
*/
8787
private $acquireAccessTokenUnlockCallback;
8888

8989
/**
90-
* @var callable(Connection)
90+
* @var callable(Connection): void|null
9191
*/
9292
private $refreshAccessTokenCallback;
9393

9494
/**
95-
* @var callable[]
95+
* @var list<callable(callable): callable>
9696
*/
97-
protected $middleWares = [];
97+
protected array $middleWares = [];
9898

9999
public ?string $nextUrl = null;
100100

@@ -439,14 +439,11 @@ public function needsAuthentication(): bool
439439
}
440440

441441
/**
442-
* @param Response $response
443-
* @param bool $returnSingleIfPossible
444-
*
445442
* @throws ApiException
446443
*
447444
* @return mixed
448445
*/
449-
private function parseResponse(Response $response, $returnSingleIfPossible = true)
446+
private function parseResponse(ResponseInterface $response, bool $returnSingleIfPossible = true)
450447
{
451448
try {
452449
$this->extractRateLimits($response);
@@ -486,13 +483,11 @@ private function parseResponse(Response $response, $returnSingleIfPossible = tru
486483
}
487484

488485
/**
489-
* @param Response $response
490-
*
491486
* @throws ApiException
492487
*
493488
* @return mixed
494489
*/
495-
private function parseResponseXml(Response $response)
490+
private function parseResponseXml(ResponseInterface $response)
496491
{
497492
try {
498493
if ($response->getStatusCode() === 204) {
@@ -519,13 +514,11 @@ private function parseResponseXml(Response $response)
519514
}
520515

521516
/**
522-
* @param Response $response
523-
*
524517
* @throws ApiException
525518
*
526519
* @return mixed
527520
*/
528-
private function parseDownloadResponseXml(Response $response)
521+
private function parseDownloadResponseXml(ResponseInterface $response)
529522
{
530523
try {
531524
if ($response->getStatusCode() === 204) {
@@ -857,7 +850,7 @@ public function setTokenUrl(string $tokenUrl): void
857850
$this->tokenUrl = $tokenUrl;
858851
}
859852

860-
private function extractRateLimits(Response $response): void
853+
private function extractRateLimits(ResponseInterface $response): void
861854
{
862855
$this->dailyLimit = (int) $response->getHeaderLine('X-RateLimit-Limit');
863856
$this->dailyLimitRemaining = (int) $response->getHeaderLine('X-RateLimit-Remaining');

0 commit comments

Comments
 (0)