Skip to content

Commit 9213273

Browse files
Mike van den Hoekmvdhoek1
authored andcommitted
feat: cache responses from BRP by hashed bsn
1 parent 3966410 commit 9213273

8 files changed

Lines changed: 141 additions & 61 deletions

File tree

src/PrefillGravityForms/Controllers/BaseController.php

Lines changed: 41 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,14 @@
77
use DateTime;
88
use Exception;
99
use GF_Field;
10+
use function OWC\PrefillGravityForms\Foundation\Helpers\resolve_teams;
1011
use function OWC\PrefillGravityForms\Foundation\Helpers\view;
1112
use OWC\PrefillGravityForms\Foundation\TeamsLogger;
1213
use OWC\PrefillGravityForms\GravityForms\GravityFormsSettings;
14+
use OWC\PrefillGravityForms\Services\CacheService;
1315
use OWC\PrefillGravityForms\Traits\SessionTrait;
1416
use TypeError;
1517
use WP_Screen;
16-
use function Yard\DigiD\Foundation\Helpers\resolve;
1718

1819
abstract class BaseController
1920
{
@@ -31,7 +32,7 @@ abstract class BaseController
3132
public function __construct()
3233
{
3334
$this->settings = GravityFormsSettings::make();
34-
$this->teams = $this->resolveTeams();
35+
$this->teams = resolve_teams();
3536
}
3637

3738
abstract public function handle(array $form): array;
@@ -54,22 +55,9 @@ public function get(): array
5455

5556
abstract protected function makeRequest(): array;
5657

57-
public function resolveTeams(): TeamsLogger
58-
{
59-
try {
60-
if (! function_exists('Yard\DigiD\Foundation\Helpers\resolve')) {
61-
throw new Exception();
62-
}
63-
64-
return TeamsLogger::make(resolve('teams'));
65-
} catch (Exception $e) {
66-
return TeamsLogger::make(new \Psr\Log\NullLogger());
67-
}
68-
}
69-
7058
protected function logError(string $message, $status): void
7159
{
72-
$this->teams->addRecord('error', 'Prefill data', [
60+
$this->teams->addRecord('error', 'BRP Prefill GravityForms', [
7361
'message' => $message,
7462
'status' => $status,
7563
]);
@@ -309,13 +297,15 @@ protected function getCurlHeaders(string $doelBinding = ''): array
309297
return array_filter($headers);
310298
}
311299

312-
protected function handleCurl(array $args, ?string $transientKey = null): array
300+
protected function handleCurl(array $args, string $transientKey): array
313301
{
314-
if (is_string($transientKey) && 0 < strlen(trim($transientKey))) {
315-
$cachedResponse = get_transient($transientKey);
316-
if (is_array($cachedResponse) && [] !== $cachedResponse) {
317-
return $cachedResponse;
318-
}
302+
/**
303+
* IMPORTANT NOTE: when adjusting this piece of code, please make sure
304+
* that the transient key is unique per request. Otherwise, different requests
305+
* might return the same cached response.
306+
*/
307+
if ($cachedResponse = CacheService::getArrayFromTransient($transientKey)) {
308+
return $cachedResponse;
319309
}
320310

321311
$curl = curl_init();
@@ -343,17 +333,15 @@ protected function handleCurl(array $args, ?string $transientKey = null): array
343333
throw new Exception('Request failed', is_int($httpStatus) ? $httpStatus : 500);
344334
}
345335

346-
$decoded = json_decode($output, true);
336+
$response = json_decode($output, true);
347337

348-
if (! is_array($decoded) || [] === $decoded || json_last_error() !== JSON_ERROR_NONE) {
338+
if (! is_array($response) || [] === $response || json_last_error() !== JSON_ERROR_NONE) {
349339
throw new Exception('Something went wrong with decoding of the JSON output.', 500);
350340
}
351341

352-
if (is_string($transientKey) && 0 < strlen(trim($transientKey))) {
353-
set_transient($transientKey, $decoded, HOUR_IN_SECONDS);
354-
}
342+
$this->handleTransient($response, $transientKey);
355343

356-
return $decoded;
344+
return $response;
357345
} catch (Exception $e) {
358346
return [
359347
'message' => $e->getMessage(),
@@ -364,6 +352,31 @@ protected function handleCurl(array $args, ?string $transientKey = null): array
364352
}
365353
}
366354

355+
/**
356+
* Validates whether the necessary conditions are met before setting the transient.
357+
*
358+
* Ensures that:
359+
* - A valid BSN (burgerservicenummer) is present in the response.
360+
* - The transient key derived from that BSN matches the one generated from the current session.
361+
*/
362+
protected function handleTransient(array $response, string $transientKey): void
363+
{
364+
$responseBSN = (string) ($response['burgerservicenummer'] ?? '');
365+
366+
if ('' === $responseBSN) {
367+
throw new Exception('No burgerservicenummer found in the response.', 404);
368+
}
369+
370+
$transientKeyByResponse = CacheService::formatTransientKey($responseBSN);
371+
372+
// Ensure the transient keys generated from the BSN out of the response and current session match.
373+
if ($transientKeyByResponse !== $transientKey) {
374+
throw new Exception('Transient key mismatch.', 500);
375+
}
376+
377+
CacheService::setTransient($transientKey, $response);
378+
}
379+
367380
protected function timeoutOptionCURL(): int
368381
{
369382
$timeout = apply_filters('owc_prefill_gravity_forms_curl_timeout', 10);

src/PrefillGravityForms/Controllers/EnableUController.php

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
namespace OWC\PrefillGravityForms\Controllers;
66

7+
use OWC\PrefillGravityForms\Services\CacheService;
8+
79
class EnableUController extends BaseController
810
{
911
public function handle(array $form): array
@@ -14,7 +16,7 @@ public function handle(array $form): array
1416

1517
$bsn = $this->getBSN();
1618

17-
if (empty($bsn)) {
19+
if ('' === $bsn) {
1820
return $form;
1921
}
2022

@@ -40,7 +42,7 @@ protected function makeRequest(): array
4042
{
4143
$bsn = $this->getBSN();
4244

43-
if (empty($bsn)) {
45+
if ('' === $bsn) {
4446
return [];
4547
}
4648

@@ -73,9 +75,6 @@ protected function request(string $bsn = '', string $doelBinding = '', string $e
7375
CURLOPT_HTTPHEADER => $this->getCurlHeaders($doelBinding),
7476
];
7577

76-
$hash = md5($curlArgs[CURLOPT_URL]);
77-
$transientKey = (is_string($hash) && '' !== $hash) ? $hash : null;
78-
79-
return $this->handleCurl($curlArgs, $transientKey);
78+
return $this->handleCurl($curlArgs, CacheService::formatTransientKey($bsn));
8079
}
8180
}

src/PrefillGravityForms/Controllers/PinkRoccadeController.php

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
namespace OWC\PrefillGravityForms\Controllers;
66

7+
use OWC\PrefillGravityForms\Services\CacheService;
8+
79
class PinkRoccadeController extends BaseController
810
{
911
public function handle(array $form): array
@@ -14,7 +16,7 @@ public function handle(array $form): array
1416

1517
$bsn = $this->getBSN();
1618

17-
if (empty($bsn)) {
19+
if ('' === $bsn) {
1820
return $form;
1921
}
2022

@@ -40,7 +42,7 @@ protected function makeRequest(): array
4042
{
4143
$bsn = $this->getBSN();
4244

43-
if (empty($bsn)) {
45+
if ('' === $bsn) {
4446
return [];
4547
}
4648

@@ -75,9 +77,6 @@ protected function request(string $bsn = '', string $doelBinding = '', string $e
7577
CURLOPT_SSLKEY => $this->settings->getPrivateCertificate(),
7678
];
7779

78-
$hash = md5($curlArgs[CURLOPT_URL]);
79-
$transientKey = (is_string($hash) && '' !== $hash) ? $hash : null;
80-
81-
return $this->handleCurl($curlArgs, $transientKey);
80+
return $this->handleCurl($curlArgs, CacheService::formatTransientKey($bsn));
8281
}
8382
}

src/PrefillGravityForms/Controllers/VrijBRPController.php

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
namespace OWC\PrefillGravityForms\Controllers;
66

7+
use OWC\PrefillGravityForms\Services\CacheService;
8+
79
class VrijBRPController extends BaseController
810
{
911
public function handle(array $form): array
@@ -14,7 +16,7 @@ public function handle(array $form): array
1416

1517
$bsn = $this->getBSN();
1618

17-
if (empty($bsn)) {
19+
if ('' === $bsn) {
1820
return $form;
1921
}
2022

@@ -40,7 +42,7 @@ protected function makeRequest(): array
4042
{
4143
$bsn = $this->getBSN();
4244

43-
if (empty($bsn)) {
45+
if ('' === $bsn) {
4446
return [];
4547
}
4648

@@ -75,9 +77,6 @@ protected function request(string $bsn = '', string $doelBinding = '', string $e
7577
CURLOPT_SSLKEY => $this->settings->getPrivateCertificate(),
7678
];
7779

78-
$hash = md5($curlArgs[CURLOPT_URL]);
79-
$transientKey = (is_string($hash) && '' !== $hash) ? $hash : null;
80-
81-
return $this->handleCurl($curlArgs, $transientKey);
80+
return $this->handleCurl($curlArgs, CacheService::formatTransientKey($bsn));
8281
}
8382
}

src/PrefillGravityForms/Controllers/WeAreFrankController.php

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
namespace OWC\PrefillGravityForms\Controllers;
66

7+
use OWC\PrefillGravityForms\Services\CacheService;
8+
79
class WeAreFrankController extends BaseController
810
{
911
public function handle(array $form): array
@@ -14,14 +16,14 @@ public function handle(array $form): array
1416

1517
$bsn = $this->getBSN();
1618

17-
if (empty($bsn)) {
19+
if ('' === $bsn) {
1820
return $form;
1921
}
2022

2123
$expand = rgar($form, 'owc-iconnect-expand', '');
2224
$preparedData = $this->prepareData($bsn, $expand);
2325

24-
$firstPerson = $this->fetchPersonData($preparedData);
26+
$firstPerson = $this->fetchPersonData($preparedData, $bsn);
2527

2628
if (empty($firstPerson)) {
2729
return $form;
@@ -36,13 +38,13 @@ protected function makeRequest(): array
3638
{
3739
$bsn = $this->getBSN();
3840

39-
if (empty($bsn)) {
41+
if ('' === $bsn) {
4042
return [];
4143
}
4244

4345
$preparedData = $this->prepareData($bsn);
4446

45-
return $this->fetchPersonData($preparedData) ?? [];
47+
return $this->fetchPersonData($preparedData, $bsn);
4648
}
4749

4850
/**
@@ -99,9 +101,9 @@ protected function getExpandFields(string $expand): array
99101
return array_filter(explode(',', $expand));
100102
}
101103

102-
protected function fetchPersonData(array $preparedData): array
104+
protected function fetchPersonData(array $preparedData, string $bsn): array
103105
{
104-
$apiResponse = $this->request($preparedData);
106+
$apiResponse = $this->request($preparedData, $bsn);
105107
$personData = $apiResponse['personen'] ?? [];
106108
$firstPerson = reset($personData); // Response is in a multidimensional array which differs from other suppliers.
107109

@@ -120,7 +122,7 @@ protected function fetchPersonData(array $preparedData): array
120122
return $firstPerson;
121123
}
122124

123-
protected function request(array $data = []): array
125+
protected function request(array $data = [], string $bsn = ''): array
124126
{
125127
$curlArgs = [
126128
CURLOPT_URL => $this->settings->getBaseURL(),
@@ -132,10 +134,7 @@ protected function request(array $data = []): array
132134
],
133135
];
134136

135-
$hash = md5(json_encode($data));
136-
$transientKey = (is_string($hash) && '' !== $hash) ? $hash : null;
137-
138-
return $this->handleCurl($curlArgs, $transientKey);
137+
return $this->handleCurl($curlArgs, CacheService::formatTransientKey($bsn));
139138
}
140139

141140
protected function getDefaultCurlArgs(): array

src/PrefillGravityForms/Foundation/Helpers.php

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22

33
namespace OWC\PrefillGravityForms\Foundation\Helpers;
44

5+
use Exception;
56
use OWC\PrefillGravityForms\Foundation\Plugin;
7+
use OWC\PrefillGravityForms\Foundation\TeamsLogger;
68

79
function app(): Plugin
810
{
@@ -31,7 +33,7 @@ function encrypt($string): string
3133
{
3234
try {
3335
$encrypted = resolve(\OWC\PrefillGravityForms\Foundation\Cryptor::class)->encrypt($string);
34-
} catch (\Exception $e) {
36+
} catch (Exception $e) {
3537
$encrypted = '';
3638
}
3739

@@ -45,7 +47,7 @@ function decrypt($string): string
4547
{
4648
try {
4749
$decrypted = resolve(\OWC\PrefillGravityForms\Foundation\Cryptor::class)->decrypt($string);
48-
} catch (\Exception $e) {
50+
} catch (Exception $e) {
4951
$decrypted = '';
5052
}
5153

@@ -91,3 +93,25 @@ function get_supplier(array $form, bool $getKey = false): string
9193

9294
return $allowed[$supplier] ?? '';
9395
}
96+
97+
/**
98+
* Use teams definition from Yard | GravityForms DigiD plugin.
99+
*/
100+
function resolve_teams(): TeamsLogger
101+
{
102+
try {
103+
if (! function_exists('Yard\DigiD\Foundation\Helpers\resolve')) {
104+
throw new Exception();
105+
}
106+
107+
$logger = \Yard\DigiD\Foundation\Helpers\resolve('teams');
108+
109+
if (! $logger instanceof \Psr\Log\LoggerInterface) {
110+
throw new Exception();
111+
}
112+
113+
return TeamsLogger::make($logger);
114+
} catch (Exception $e) {
115+
return TeamsLogger::make(new \Psr\Log\NullLogger());
116+
}
117+
}

0 commit comments

Comments
 (0)