Passed
Push — master ( 54b1a6...aec489 )
by Christian
10:37 queued 13s
created

ChangeCustomerProfileRoute::change()   B

Complexity

Conditions 7
Paths 24

Size

Total Lines 40
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 21
nc 24
nop 3
dl 0
loc 40
rs 8.6506
c 0
b 0
f 0
1
<?php declare(strict_types=1);
2
3
namespace Shopware\Core\Checkout\Customer\SalesChannel;
4
5
use OpenApi\Annotations as OA;
6
use Shopware\Core\Checkout\Customer\CustomerEntity;
7
use Shopware\Core\Checkout\Customer\CustomerEvents;
8
use Shopware\Core\Framework\Context;
9
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
10
use Shopware\Core\Framework\Event\DataMappingEvent;
11
use Shopware\Core\Framework\Feature;
12
use Shopware\Core\Framework\Plugin\Exception\DecorationPatternException;
13
use Shopware\Core\Framework\Routing\Annotation\ContextTokenRequired;
14
use Shopware\Core\Framework\Routing\Annotation\LoginRequired;
15
use Shopware\Core\Framework\Routing\Annotation\RouteScope;
16
use Shopware\Core\Framework\Routing\Annotation\Since;
17
use Shopware\Core\Framework\Validation\BuildValidationEvent;
18
use Shopware\Core\Framework\Validation\DataBag\DataBag;
19
use Shopware\Core\Framework\Validation\DataBag\RequestDataBag;
20
use Shopware\Core\Framework\Validation\DataValidationDefinition;
21
use Shopware\Core\Framework\Validation\DataValidationFactoryInterface;
22
use Shopware\Core\Framework\Validation\DataValidator;
23
use Shopware\Core\System\SalesChannel\SalesChannelContext;
24
use Shopware\Core\System\SalesChannel\SuccessResponse;
25
use Symfony\Component\Routing\Annotation\Route;
26
use Symfony\Component\Validator\Constraints\NotBlank;
27
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
28
29
/**
30
 * @RouteScope(scopes={"store-api"})
31
 * @ContextTokenRequired()
32
 */
33
class ChangeCustomerProfileRoute extends AbstractChangeCustomerProfileRoute
34
{
35
    /**
36
     * @var EntityRepositoryInterface
37
     */
38
    private $customerRepository;
39
40
    /**
41
     * @var EventDispatcherInterface
42
     */
43
    private $eventDispatcher;
44
45
    /**
46
     * @var DataValidator
47
     */
48
    private $validator;
49
50
    /**
51
     * @var DataValidationFactoryInterface
52
     */
53
    private $customerProfileValidationFactory;
54
55
    public function __construct(
56
        EntityRepositoryInterface $customerRepository,
57
        EventDispatcherInterface $eventDispatcher,
58
        DataValidator $validator,
59
        DataValidationFactoryInterface $customerProfileValidationFactory
60
    ) {
61
        $this->customerRepository = $customerRepository;
62
        $this->eventDispatcher = $eventDispatcher;
63
        $this->validator = $validator;
64
        $this->customerProfileValidationFactory = $customerProfileValidationFactory;
65
    }
66
67
    public function getDecorated(): AbstractChangeCustomerProfileRoute
68
    {
69
        throw new DecorationPatternException(self::class);
70
    }
71
72
    /**
73
     * @Since("6.2.0.0")
74
     * @OA\Post(
75
     *      path="/account/change-profile",
76
     *      summary="Change profile information",
77
     *      operationId="changeProfile",
78
     *      tags={"Store API", "Account"},
79
     *      @OA\RequestBody(
80
     *          required=true,
81
     *          @OA\JsonContent(
82
     *              @OA\Property(property="salutationId", description="Salutation ID", type="string"),
83
     *              @OA\Property(property="firstName", description="Firstname", type="string"),
84
     *              @OA\Property(property="lastName", description="Firstname", type="string")
85
     *          )
86
     *      ),
87
     *      @OA\Response(
88
     *          response="200",
89
     *          description="Successfully saved",
90
     *          @OA\JsonContent(ref="#/components/schemas/SuccessResponse")
91
     *     )
92
     * )
93
     * @LoginRequired()
94
     * @Route(path="/store-api/v{version}/account/change-profile", name="store-api.account.change-profile", methods={"POST"})
95
     */
96
    public function change(RequestDataBag $data, SalesChannelContext $context, ?CustomerEntity $customer = null): SuccessResponse
97
    {
98
        /* @deprecated tag:v6.4.0 - Parameter $customer will be mandatory when using with @LoginRequired() */
99
        if (!$customer) {
100
            $customer = $context->getCustomer();
101
        }
102
103
        $validation = $this->customerProfileValidationFactory->update($context);
104
105
        if ($data->get('accountType') === CustomerEntity::ACCOUNT_TYPE_BUSINESS) {
106
            $validation->add('company', new NotBlank());
107
        } else {
108
            $data->set('company', '');
109
            $data->set('vatIds', null);
110
        }
111
112
        $this->dispatchValidationEvent($validation, $context->getContext());
113
114
        $this->validator->validate($data->all(), $validation);
115
116
        $customerData = $data->only('firstName', 'lastName', 'salutationId', 'title', 'company');
117
118
        if (Feature::isActive('FEATURE_NEXT_10559') && $vatIds = $data->get('vatIds')) {
119
            $customerData['vatIds'] = empty($vatIds->all()) ? null : $vatIds->all();
120
        }
121
122
        if ($birthday = $this->getBirthday($data)) {
123
            $customerData['birthday'] = $birthday;
124
        }
125
126
        $mappingEvent = new DataMappingEvent($data, $customerData, $context->getContext());
127
        $this->eventDispatcher->dispatch($mappingEvent, CustomerEvents::MAPPING_CUSTOMER_PROFILE_SAVE);
0 ignored issues
show
Unused Code introduced by
The call to Symfony\Contracts\EventD...erInterface::dispatch() has too many arguments starting with Shopware\Core\Checkout\C...G_CUSTOMER_PROFILE_SAVE. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

127
        $this->eventDispatcher->/** @scrutinizer ignore-call */ 
128
                                dispatch($mappingEvent, CustomerEvents::MAPPING_CUSTOMER_PROFILE_SAVE);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
128
129
        $customerData = $mappingEvent->getOutput();
130
131
        $customerData['id'] = $customer->getId();
132
133
        $this->customerRepository->update([$customerData], $context->getContext());
134
135
        return new SuccessResponse();
136
    }
137
138
    private function dispatchValidationEvent(DataValidationDefinition $definition, Context $context): void
139
    {
140
        $validationEvent = new BuildValidationEvent($definition, $context);
141
        $this->eventDispatcher->dispatch($validationEvent, $validationEvent->getName());
0 ignored issues
show
Unused Code introduced by
The call to Symfony\Contracts\EventD...erInterface::dispatch() has too many arguments starting with $validationEvent->getName(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

141
        $this->eventDispatcher->/** @scrutinizer ignore-call */ 
142
                                dispatch($validationEvent, $validationEvent->getName());

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
142
    }
143
144
    private function getBirthday(DataBag $data): ?\DateTimeInterface
145
    {
146
        $birthdayDay = $data->get('birthdayDay');
147
        $birthdayMonth = $data->get('birthdayMonth');
148
        $birthdayYear = $data->get('birthdayYear');
149
150
        if (!$birthdayDay || !$birthdayMonth || !$birthdayYear) {
151
            return null;
152
        }
153
154
        return new \DateTime(sprintf(
155
            '%s-%s-%s',
156
            $birthdayYear,
157
            $birthdayMonth,
158
            $birthdayDay
159
        ));
160
    }
161
}
162