Passed
Push — main ( b15a24...935ae5 )
by Axel
04:15
created

UsersUiSubscriber::amendForm()   A

Complexity

Conditions 6
Paths 6

Size

Total Lines 20
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 13
nc 6
nop 1
dl 0
loc 20
rs 9.2222
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the Zikula package.
7
 *
8
 * Copyright Zikula - https://ziku.la/
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace Zikula\ProfileBundle\EventSubscriber;
15
16
use Symfony\Component\DependencyInjection\Attribute\Autowire;
17
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
18
use Symfony\Component\HttpFoundation\File\UploadedFile;
19
use Symfony\Contracts\Translation\TranslatorInterface;
20
use Twig\Environment;
21
use Zikula\Bundle\FormExtensionBundle\Event\FormTypeChoiceEvent;
22
use Zikula\ProfileBundle\Form\ProfileTypeFactory;
23
use Zikula\ProfileBundle\Form\Type\AvatarType;
24
use Zikula\ProfileBundle\Helper\UploadHelper;
25
use Zikula\ProfileBundle\ProfileConstant;
26
use Zikula\ProfileBundle\Repository\PropertyRepositoryInterface;
27
use Zikula\UsersBundle\Event\EditUserFormPostCreatedEvent;
0 ignored issues
show
Bug introduced by
The type Zikula\UsersBundle\Event...serFormPostCreatedEvent was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
28
use Zikula\UsersBundle\Event\EditUserFormPostValidatedEvent;
0 ignored issues
show
Bug introduced by
The type Zikula\UsersBundle\Event...rFormPostValidatedEvent was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
29
use Zikula\UsersBundle\Event\UserAccountDisplayEvent;
30
use Zikula\UsersBundle\Repository\UserRepositoryInterface;
31
use Zikula\UsersBundle\UsersConstant;
32
33
/**
34
 * Hook-like event handlers for basic profile data.
35
 */
36
class UsersUiSubscriber implements EventSubscriberInterface
37
{
38
    /**
39
     * The area name that this handler processes.
40
     */
41
    public const EVENT_KEY = 'module.profile.users_ui_handler';
42
43
    public function __construct(
44
        private readonly TranslatorInterface $translator,
45
        private readonly UserRepositoryInterface $userRepository,
46
        private readonly PropertyRepositoryInterface $propertyRepository,
47
        private readonly ProfileTypeFactory $factory,
48
        private readonly Environment $twig,
49
        private readonly UploadHelper $uploadHelper,
50
        #[Autowire('%zikula_profile_module.property_prefix%')]
51
        private readonly string $prefix,
52
        private readonly bool $displayRegistrationDate,
53
        private readonly string $avatarImagePath
54
    ) {
55
    }
56
57
    public static function getSubscribedEvents(): array
58
    {
59
        return [
60
            UserAccountDisplayEvent::class => ['uiView'],
61
            EditUserFormPostCreatedEvent::class => ['amendForm'],
62
            EditUserFormPostValidatedEvent::class => ['editFormHandler'],
63
            FormTypeChoiceEvent::class => ['formTypeChoices'],
64
        ];
65
    }
66
67
    /**
68
     * Render and return profile information for display as part of a hook-like UI event issued from the Users bundle.
69
     */
70
    public function uiView(UserAccountDisplayEvent $event): void
71
    {
72
        $event->addContent(self::EVENT_KEY, $this->twig->render('@ZikulaProfile/Hook/display.html.twig', [
73
            'prefix' => $this->prefix,
74
            'user' => $event->getUser(),
75
            'activeProperties' => $this->propertyRepository->getDynamicFieldsSpecification(),
76
            'displayRegistrationDate' => $this->displayRegistrationDate,
77
        ]));
78
    }
79
80
    public function amendForm(EditUserFormPostCreatedEvent $event): void
81
    {
82
        $user = $event->getFormData();
83
        $uid = !empty($user['uid']) ? $user['uid'] : UsersConstant::USER_ID_ANONYMOUS;
84
        $userEntity = $this->userRepository->find($uid);
85
        $attributes = $userEntity->getAttributes() ?? [];
86
87
        // unpack json values (e.g. array for multi-valued options)
88
        foreach ($attributes as $key => $attribute) {
89
            $value = $attribute->getValue();
90
            if (is_string($value) && is_array(json_decode($value, true)) && JSON_ERROR_NONE === json_last_error()) {
91
                $attribute->setValue(json_decode($value, true));
92
            }
93
        }
94
95
        $profileForm = $this->formFactory->createForm($attributes, false);
0 ignored issues
show
Bug Best Practice introduced by
The property formFactory does not exist on Zikula\ProfileBundle\Eve...riber\UsersUiSubscriber. Did you maybe forget to declare it?
Loading history...
96
        $event
97
            ->formAdd($profileForm)
98
            ->addTemplate('@ZikulaProfile/Hook/edit.html.twig', [
99
                'imagePath' => $this->avatarImagePath,
100
            ])
101
        ;
102
    }
103
104
    public function editFormHandler(EditUserFormPostValidatedEvent $event): void
105
    {
106
        $userEntity = $event->getUser();
107
        $formData = $event->getFormData(ProfileConstant::FORM_BLOCK_PREFIX);
108
        foreach ($formData as $key => $value) {
109
            if (!empty($value)) {
110
                if ($value instanceof UploadedFile) {
111
                    $value = $this->uploadHelper->handleUpload($value, $userEntity->getUid());
112
                } elseif (is_array($value)) {
113
                    // pack multi-valued options into json
114
                    $value = json_encode($value);
115
                }
116
                $userEntity->setAttribute($key, $value);
117
            } elseif (false === mb_strpos($key, 'avatar')) {
118
                $userEntity->delAttribute($key);
119
            }
120
        }
121
122
        // we do not call flush here on purpose because maybe
123
        // other modules need to care for certain things before
124
        // the Users module calls flush after all listeners finished
125
    }
126
127
    public function formTypeChoices(FormTypeChoiceEvent $event): void
128
    {
129
        $choices = $event->getChoices();
130
131
        $groupName = $this->translator->trans('Other Fields', [], 'zikula');
132
        if (!isset($choices[$groupName])) {
133
            $choices[$groupName] = [];
134
        }
135
136
        $groupChoices = $choices[$groupName];
137
        $groupChoices[$this->translator->trans('Avatar')] = AvatarType::class;
138
        $choices[$groupName] = $groupChoices;
139
140
        $event->setChoices($choices);
141
    }
142
}
143