Merge pull request #282 from copenhagentruckwash/codex/register-cvr-welcome-email-fix
[codex] Fix register CVR welcome email rendering
This commit is contained in:
@@ -2,7 +2,8 @@
|
||||
|
||||
namespace email\templates;
|
||||
|
||||
use email\helpers\email_template;use objects\users_o;
|
||||
use email\helpers\email_template;
|
||||
use objects\users_o;
|
||||
|
||||
class email_template_new_customer
|
||||
{
|
||||
@@ -52,6 +53,7 @@ class email_template_new_customer
|
||||
*/
|
||||
public function generate_html(): string
|
||||
{
|
||||
$customer_label = htmlspecialchars($this->getCustomerRegistrationLabel(), ENT_QUOTES, 'UTF-8');
|
||||
ob_start();
|
||||
# Start of the html
|
||||
?>
|
||||
@@ -73,7 +75,7 @@ class email_template_new_customer
|
||||
|
||||
<!-- Intro -->
|
||||
<p class="container-text-md" style="color:#000000;font-size:16px;line-height:1.5;margin:0 0 18px 0;mso-line-height-rule:exactly;">
|
||||
Tak for din registrering af <?=((new users_o())->getCustomerName((int)$this->customer_number))?><?=(((new users_o())->getCustomerEcocomicData((int)$this->customer_number)->economic_customer->corporateIdentificationNumber) ? ' (' . (new users_o())->getCustomerEcocomicData((int)$this->customer_number)->economic_customer->corporateIdentificationNumber . ')' : '')?> som kunde hos Truck Wash.
|
||||
Tak for din registrering af <?=$customer_label?> som kunde hos Truck Wash.
|
||||
</p>
|
||||
|
||||
<!-- You can now wash your trucks -->
|
||||
@@ -185,4 +187,19 @@ class email_template_new_customer
|
||||
# End of the html
|
||||
return ob_get_clean();
|
||||
}
|
||||
|
||||
private function getCustomerRegistrationLabel(): string
|
||||
{
|
||||
$customer = (new users_o())->getUserByCustomerNumber($this->customer_number);
|
||||
$customer_name = trim((string)($customer->getCustomerName($this->customer_number) ?? ''));
|
||||
$customer_label = $customer_name === '' ? 'virksomhed (CVR)' : $customer_name;
|
||||
|
||||
$customer->getCustomerEcocomicData($this->customer_number);
|
||||
$corporate_identification_number = trim((string)($customer->economic_customer->corporateIdentificationNumber ?? ''));
|
||||
if ($corporate_identification_number !== '') {
|
||||
$customer_label .= ' (' . $corporate_identification_number . ')';
|
||||
}
|
||||
|
||||
return $customer_label;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -527,6 +527,10 @@ class users_o extends db
|
||||
|
||||
public function getCustomerEcocomicData(?int $customer_number = null): users_o
|
||||
{
|
||||
if ($customer_number !== null && !isset($this->id)) {
|
||||
$this->getUserByCustomerNumber($customer_number);
|
||||
}
|
||||
|
||||
// Check if the customer number is set
|
||||
if (!isset($this->customer_number) && $customer_number === null) {
|
||||
return $this;
|
||||
@@ -538,7 +542,9 @@ class users_o extends db
|
||||
return $this;
|
||||
}
|
||||
|
||||
$cachedCustomer = $this->getCached('economic_customer');
|
||||
$cachedCustomer = isset($this->id) && $this->id > 0
|
||||
? $this->getCached('economic_customer')
|
||||
: null;
|
||||
if (is_object($cachedCustomer)) {
|
||||
$cachedCustomerNumber = (int)($cachedCustomer->customerNumber ?? $cachedCustomer->customer_number ?? 0);
|
||||
if ($cachedCustomerNumber === $customer_number) {
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
return [
|
||||
['path' => 'tests/auth/CreateTokenUserNotFoundTest.php', 'classification' => 'unit', 'type' => 'script'],
|
||||
['path' => 'tests/auth/NewCustomerEmailTemplateTest.php', 'classification' => 'unit', 'type' => 'script'],
|
||||
['path' => 'tests/auth/PasskeyChallengeTest.php', 'classification' => 'unit', 'type' => 'script'],
|
||||
['path' => 'tests/auth/PemToCoseConversionTest.php', 'classification' => 'unit', 'type' => 'script'],
|
||||
['path' => 'tests/auth/RegisterCvrTest.php', 'classification' => 'unit', 'type' => 'script'],
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
it('renders the new customer welcome template without unselected user access or leaked output', function (): void {
|
||||
$result = run_legacy_script('tests/auth/NewCustomerEmailTemplateTest.php');
|
||||
|
||||
expect($result['exitCode'])->toBe(0, $result['output']);
|
||||
});
|
||||
@@ -0,0 +1,99 @@
|
||||
<?php
|
||||
namespace {
|
||||
if (!defined('WD')) {
|
||||
define('WD', dirname(__DIR__, 2));
|
||||
}
|
||||
}
|
||||
|
||||
namespace objects {
|
||||
class users_o
|
||||
{
|
||||
public static array $calls = [];
|
||||
private bool $selected = false;
|
||||
public object $economic_customer;
|
||||
|
||||
public function getUserByCustomerNumber(int $customer_number): self
|
||||
{
|
||||
self::$calls[] = 'select:' . $customer_number;
|
||||
$this->selected = true;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getCustomerName(int $customer_number): ?string
|
||||
{
|
||||
if (!$this->selected) {
|
||||
throw new \RuntimeException('Customer name requested before local customer selection.');
|
||||
}
|
||||
|
||||
self::$calls[] = 'name:' . $customer_number;
|
||||
|
||||
return 'KING FOOD DANMARK A/S';
|
||||
}
|
||||
|
||||
public function getCustomerEcocomicData(?int $customer_number = null): self
|
||||
{
|
||||
if (!$this->selected) {
|
||||
throw new \RuntimeException('Economic customer requested before local customer selection.');
|
||||
}
|
||||
|
||||
self::$calls[] = 'economic:' . (int)$customer_number;
|
||||
$this->economic_customer = (object)[
|
||||
'corporateIdentificationNumber' => '12345678',
|
||||
];
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
require_once WD . '/modules/email/helpers/email_template.php';
|
||||
require_once WD . '/modules/email/templates/email_template_new_customer.php';
|
||||
|
||||
function assert_true(bool $condition, string $message): void
|
||||
{
|
||||
if (!$condition) {
|
||||
throw new \RuntimeException($message);
|
||||
}
|
||||
}
|
||||
|
||||
function cleanup_buffers_to(int $base_level): string
|
||||
{
|
||||
$output = '';
|
||||
while (ob_get_level() > $base_level) {
|
||||
$output .= (string)ob_get_clean();
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
$base_level = ob_get_level();
|
||||
ob_start();
|
||||
|
||||
try {
|
||||
$html = (new \email\templates\email_template_new_customer(
|
||||
12345678,
|
||||
'https://truckwash.io/auth/password-reset/mock-token',
|
||||
))->generate_html();
|
||||
$leaked_output = cleanup_buffers_to($base_level);
|
||||
|
||||
assert_true($leaked_output === '', 'Template generation must not leak buffered HTML output.');
|
||||
assert_true(
|
||||
str_contains($html, 'Tak for din registrering af KING FOOD DANMARK A/S (12345678) som kunde hos Truck Wash.'),
|
||||
'Template must render the selected customer name and CVR in the welcome intro.'
|
||||
);
|
||||
assert_true(
|
||||
\objects\users_o::$calls === ['select:12345678', 'name:12345678', 'economic:12345678'],
|
||||
'Template must select the local customer before reading customer details.'
|
||||
);
|
||||
} catch (\Throwable $exception) {
|
||||
$leaked_output = cleanup_buffers_to($base_level);
|
||||
fwrite(STDERR, $leaked_output);
|
||||
fwrite(STDERR, $exception->getMessage() . PHP_EOL);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
echo "\033[32m[PASS]\033[0m New customer email template renders without leaked output.\n";
|
||||
exit(0);
|
||||
}
|
||||
Reference in New Issue
Block a user