Skip to content

Commit

Permalink
NEXT-9291 - Add Data Protection Information checkbox, fixes shopwareB…
Browse files Browse the repository at this point in the history
  • Loading branch information
rune.laenen authored and shyim committed Feb 2, 2021
1 parent b94029a commit 4ad8845
Show file tree
Hide file tree
Showing 7 changed files with 158 additions and 9 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
title: Add Data Protection Information checkbox
issue: NEXT-9291
author: Rune Laenen
author_email: [email protected]
author_github: runelaenen
---
# Core
* Added `core.loginRegistration.requireDataProtectionCheckbox` configuration option, defaults to false.
* Added `acceptedDataProtection` parameter to `Shopware\Core\Checkout\Customer\SalesChannel\RegisterRoute`
* Added `acceptedDataProtection` validation rule if `core.loginRegistration.requireDataProtectionCheckbox` configuration is enabled
___
# Storefront
* Added blocks `component_privacy_dpi`, `component_privacy_dpi_checkbox` and `component_privacy_dpi_label` in `@Storefront/storefront/component/privacy-notice.html.twig`
5 changes: 5 additions & 0 deletions src/Core/Checkout/Customer/SalesChannel/RegisterRoute.php
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ public function getDecorated(): AbstractRegisterRoute
* @OA\Parameter(name="affiliateCode", description="Affilicate Code", in="query", @OA\Schema(type="string")),
* @OA\Parameter(name="campaignCode", description="Campaign Code", in="query", @OA\Schema(type="string")),
* @OA\Parameter(name="password", description="Password", in="query", @OA\Schema(type="string")),
* @OA\Parameter(name="acceptedDataProtection", description="Accepted Data Protection policy", in="query", @OA\Schema(type="boolean")),
* @OA\Parameter(name="billingAddress", description="Billingaddress", in="query", @OA\JsonContent(ref="#/components/schemas/customer_address_flat")),
* @OA\Parameter(name="shippingAddress", description="Shippingaddress", in="query", @OA\JsonContent(ref="#/components/schemas/customer_address_flat")),
* @OA\Response(
Expand Down Expand Up @@ -316,6 +317,10 @@ private function validateRegistrationData(DataBag $data, bool $isGuest, SalesCha
));
}

if ($this->systemConfigService->get('core.loginRegistration.requireDataProtectionCheckbox', $context->getSalesChannel()->getId())) {
$definition->add('acceptedDataProtection', new NotBlank());
}

$violations = $this->validator->getViolations($data->all(), $definition);
if (!$violations->count()) {
return;
Expand Down
57 changes: 57 additions & 0 deletions src/Core/Checkout/Test/Customer/AccountRegistrationServiceTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,63 @@ public function testFinishDoubleOptInRegistration(): void
static::assertMailRecipientStructEvent($this->getMailRecipientStruct(['email' => $email, 'firstName' => 'Max', 'lastName' => 'Mustermann']), $event);
}

public function testRegisterWithDataProtectionCheckbox(): void
{
$systemConfigService = $this->getContainer()->get(SystemConfigService::class);
$systemConfigService->set('core.loginRegistration.requireDataProtectionCheckbox', true);

$salesChannelContext = $this->createContextWithTestDomain();

$customerRegisterData = $this->getCustomerRegisterData();
$customerRegisterData['acceptedDataProtection'] = '1';

$dataBag = new DataBag();
$dataBag->add($customerRegisterData);

/** @var EventDispatcher $dispatcher */
$dispatcher = $this->getContainer()->get('event_dispatcher');
$phpunit = $this;

$customerEventDidRun = false;
$listenerCustomerEventClosure = function (CustomerRegisterEvent $event) use (&$customerEventDidRun, $phpunit, $customerRegisterData): void {
$customerEventDidRun = true;
$phpunit->assertSame($customerRegisterData['email'], $event->getCustomer()->getEmail());
};
$dispatcher->addListener(CustomerRegisterEvent::class, $listenerCustomerEventClosure);

$this->accountRegistrationService->register($dataBag, false, $salesChannelContext);

$dispatcher->removeListener(CustomerRegisterEvent::class, $listenerCustomerEventClosure);

static::assertTrue($customerEventDidRun, 'The "' . CustomerRegisterEvent::class . '" Event did not run');
}

public function testRegisterWithInvalidDataProtectionCheckbox(): void
{
$systemConfigService = $this->getContainer()->get(SystemConfigService::class);
$systemConfigService->set('core.loginRegistration.requireDataProtectionCheckbox', true);

$salesChannelContext = $this->createContextWithTestDomain();

$customerRegisterData = $this->getCustomerRegisterData();

$dataBag = new DataBag();
$dataBag->add($customerRegisterData);

$exceptionWasThrown = false;

try {
$this->accountRegistrationService->register($dataBag, false, $salesChannelContext);
} catch (ConstraintViolationException $e) {
$exceptionWasThrown = true;

static::assertEquals(1, $e->getViolations()->count());
static::assertEquals(1, $e->getViolations('/acceptedDataProtection')->count());
}

static::assertTrue($exceptionWasThrown);
}

private function getMailRecipientStruct(array $customerData): MailRecipientStruct
{
return new MailRecipientStruct([
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php declare(strict_types=1);

namespace Shopware\Core\Migration;

use Doctrine\DBAL\Connection;
use Shopware\Core\Defaults;
use Shopware\Core\Framework\Migration\MigrationStep;
use Shopware\Core\Framework\Uuid\Uuid;

class Migration1610625925RequireDataProtectionCheckbox extends MigrationStep
{
public function getCreationTimestamp(): int
{
return 1610625925;
}

public function update(Connection $connection): void
{
$connection->insert('system_config', [
'id' => Uuid::randomBytes(),
'configuration_key' => 'core.loginRegistration.requireDataProtectionCheckbox',
'configuration_value' => json_encode(['_value' => false]),
'created_at' => (new \DateTime())->format(Defaults::STORAGE_DATE_TIME_FORMAT),
]);
}

public function updateDestructive(Connection $connection): void
{
// implement update destructive
}
}
6 changes: 6 additions & 0 deletions src/Core/System/Resources/config/loginRegistration.xml
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,12 @@
<label lang="de-DE">Löschen des Kunden zulassen</label>
</input-field>

<input-field type="bool">
<name>requireDataProtectionCheckbox</name>
<label>Data protection information must be accepted via a checkbox</label>
<label lang="de-DE">Datenschutzbestimmungen müssen über eine Checkbox akzeptiert werden</label>
</input-field>

<input-field type="bool">
<name>vatIdFieldRequired</name>
<label>VAT Reg.No. required</label>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,7 @@
.register-shipping {
padding-top: $spacer-lg;
}

.register-form .privacy-notice {
margin-bottom: $spacer;
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,44 @@
{% block component_privacy_notice %}
<p class="form-text privacy-notice">
{% block component_privacy_label %}
<label>
<strong>{{ "general.privacyTitle"|trans|sw_sanitize }}</strong><br />
{{ "general.privacyNotice"|trans({
'%url%': path('frontend.cms.page',{ id: shopware.config.core.basicInformation.privacyPage })
})|raw }}
</label>
<div class="form-text privacy-notice">
{% block component_privacy_title %}
<strong>{{ "general.privacyTitle"|trans|sw_sanitize }}</strong><br/>
{% endblock %}
</p>

{% block component_privacy_dpi %}
{% if shopware.config.core.loginRegistration.requireDataProtectionCheckbox == 1 %}
<div class="custom-control custom-checkbox data-protection-information">
{% block component_privacy_dpi_checkbox %}
<input type="checkbox"
class="custom-control-input {% if formViolations.getViolations('/acceptedDataProtection') is not empty %} is-invalid{% endif %}"
name="acceptedDataProtection"
required="required"
value="1"
id="acceptedDataProtection"
{% if data.get('acceptedDataProtection') %}checked="checked"{% endif %}>
{% endblock %}

{% block component_privacy_dpi_label %}
<label class="custom-control-label no-validation"
for="acceptedDataProtection">
{{ "general.privacyNotice"|trans({
'%url%': path('frontend.cms.page',{ id: shopware.config.core.basicInformation.privacyPage })
})|raw }}

{{ "general.required"|trans|sw_sanitize }}
</label>
{% endblock %}
</div>
{% else %}
<div class="data-protection-information">
{% block component_privacy_label %}
<label>
{{ "general.privacyNotice"|trans({
'%url%': path('frontend.cms.page',{ id: shopware.config.core.basicInformation.privacyPage })
})|raw }}
</label>
{% endblock %}
</div>
{% endif %}
{% endblock %}
</div>
{% endblock %}

0 comments on commit 4ad8845

Please sign in to comment.