Passed
Push — master ( 13c68b...d6cf3f )
by Angel Fernando Quiroz
09:49 queued 19s
created

AzureSyncAbstractCommand::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 20
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 5
c 1
b 0
f 0
nc 1
nop 10
dl 0
loc 20
rs 10

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
/* For licensing terms, see /license.txt */
4
5
declare(strict_types=1);
6
7
namespace Chamilo\CoreBundle\Command;
8
9
use Chamilo\CoreBundle\Entity\AzureSyncState;
10
use Chamilo\CoreBundle\Helpers\AccessUrlHelper;
11
use Chamilo\CoreBundle\Helpers\AuthenticationConfigHelper;
12
use Chamilo\CoreBundle\Helpers\AzureAuthenticatorHelper;
13
use Chamilo\CoreBundle\Helpers\UserHelper;
14
use Chamilo\CoreBundle\Repository\AzureSyncStateRepository;
15
use Chamilo\CoreBundle\Repository\Node\UsergroupRepository;
16
use Chamilo\CoreBundle\Repository\Node\UserRepository;
17
use Chamilo\CoreBundle\Settings\SettingsManager;
18
use Doctrine\ORM\EntityManagerInterface;
19
use Exception;
20
use Generator;
21
use GuzzleHttp\Exception\GuzzleException;
22
use KnpU\OAuth2ClientBundle\Client\ClientRegistry;
23
use KnpU\OAuth2ClientBundle\Client\Provider\AzureClient;
24
use League\OAuth2\Client\Provider\Exception\IdentityProviderException;
25
use League\OAuth2\Client\Token\AccessTokenInterface;
26
use Symfony\Component\Console\Command\Command;
27
use TheNetworg\OAuth2\Client\Provider\Azure;
28
29
use const PHP_URL_QUERY;
30
31
abstract class AzureSyncAbstractCommand extends Command
32
{
33
    protected AzureClient $client;
34
35
    protected Azure $provider;
36
37
    protected array $providerParams = [];
38
39
    public function __construct(
40
        protected readonly ClientRegistry $clientRegistry,
41
        readonly AuthenticationConfigHelper $configHelper,
42
        readonly protected AzureAuthenticatorHelper $azureHelper,
43
        readonly protected AzureSyncStateRepository $syncStateRepo,
44
        protected readonly EntityManagerInterface $entityManager,
45
        protected readonly UserRepository $userRepository,
46
        protected readonly UsergroupRepository $usergroupRepository,
47
        protected readonly AccessUrlHelper $accessUrlHelper,
48
        protected readonly SettingsManager $settingsManager,
49
        protected readonly UserHelper $userHelper,
50
    ) {
51
        parent::__construct();
52
53
        $this->providerParams = $configHelper->getProviderConfig('azure');
54
55
        $this->client = $this->clientRegistry->getClient('azure');
56
57
        $this->provider = $this->client->getOAuth2Provider();
58
        $this->provider->tenant = $this->providerParams['tenant'] ?? null;
59
    }
60
61
    /**
62
     * @throws GuzzleException
63
     * @throws IdentityProviderException
64
     */
65
    protected function generateOrRefreshToken(?AccessTokenInterface &$token): void
66
    {
67
        if (!$token || ($token->getExpires() && !$token->getRefreshToken())) {
68
            $token = $this->provider->getAccessToken(
69
                'client_credentials',
70
                ['resource' => $this->provider->resource]
71
            );
72
        }
73
    }
74
75
    /**
76
     * @throws Exception
77
     */
78
    protected function getAzureUsers(): Generator
79
    {
80
        if ($this->providerParams['script_users_delta']) {
81
            $usersDeltaLink = $this->syncStateRepo->findOneBy(['title' => AzureSyncState::USERS_DATALINK]);
82
83
            $query = $usersDeltaLink
84
                ? $usersDeltaLink->getValue()
85
                : \sprintf('$select=%s', implode(',', AzureAuthenticatorHelper::QUERY_USER_FIELDS));
86
        } else {
87
            $query = \sprintf(
88
                '$top=%d&$select=%s',
89
                AzureSyncState::API_PAGE_SIZE,
90
                implode(',', AzureAuthenticatorHelper::QUERY_USER_FIELDS)
91
            );
92
        }
93
94
        $token = null;
95
96
        do {
97
            try {
98
                $this->generateOrRefreshToken($token);
99
100
                $azureUsersRequest = $this->provider->get(
101
                    $this->providerParams['script_users_delta'] ? "/v1.0/users/delta?$query" : "/v1.0/users?$query",
102
                    $token
103
                );
104
            } catch (GuzzleException|Exception $e) {
105
                throw new Exception('Exception when requesting users from Azure: '.$e->getMessage());
106
            }
107
108
            $azureUsersInfo = $azureUsersRequest ?? [];
109
110
            foreach ($azureUsersInfo as $azureUserInfo) {
111
                $azureUserInfo['mail'] = $azureUserInfo['mail'] ?? null;
112
                $azureUserInfo['surname'] = $azureUserInfo['surname'] ?? null;
113
                $azureUserInfo['givenName'] = $azureUserInfo['givenName'] ?? null;
114
115
                yield $azureUserInfo;
116
            }
117
118
            $hasNextLink = false;
119
120
            if (!empty($azureUsersRequest['@odata.nextLink'])) {
121
                $hasNextLink = true;
122
                $query = parse_url($azureUsersRequest['@odata.nextLink'], PHP_URL_QUERY);
123
            }
124
125
            if ($this->providerParams['script_users_delta'] && !empty($azureUsersRequest['@odata.deltaLink'])) {
126
                $this->syncStateRepo->save(
127
                    AzureSyncState::USERS_DATALINK,
128
                    parse_url($azureUsersRequest['@odata.deltaLink'], PHP_URL_QUERY),
129
                );
130
            }
131
        } while ($hasNextLink);
132
    }
133
134
    /**
135
     * @throws Exception
136
     */
137
    protected function getAzureGroupMembers(string $groupUid): Generator
138
    {
139
        $query = \sprintf(
140
            '$top=%d&$select=%s',
141
            AzureSyncState::API_PAGE_SIZE,
142
            implode(',', AzureAuthenticatorHelper::QUERY_GROUP_MEMBERS_FIELDS)
143
        );
144
145
        $token = null;
146
147
        do {
148
            try {
149
                $this->generateOrRefreshToken($token);
150
151
                $azureGroupMembersRequest = $this->provider->get(
152
                    "/v1.0/groups/$groupUid/members?$query",
153
                    $token
154
                );
155
            } catch (GuzzleException|Exception $e) {
156
                throw new Exception('Exception when requesting group members from Azure: '.$e->getMessage());
157
            }
158
159
            $azureGroupMembers = $azureGroupMembersRequest ?? [];
160
161
            foreach ($azureGroupMembers as $azureGroupMember) {
162
                yield $azureGroupMember;
163
            }
164
165
            $hasNextLink = false;
166
167
            if (!empty($azureGroupMembersRequest['@odata.nextLink'])) {
168
                $hasNextLink = true;
169
                $query = parse_url($azureGroupMembersRequest['@odata.nextLink'], PHP_URL_QUERY);
170
            }
171
        } while ($hasNextLink);
172
    }
173
174
    /**
175
     * @throws Exception
176
     */
177
    protected function getAzureGroups(): Generator
178
    {
179
        $getUsergroupsDelta = 'true' === $this->providerParams['script_usergroups_delta'];
180
181
        if ($getUsergroupsDelta) {
182
            $usergroupsDeltaLink = $this->syncStateRepo->findOneBy(['title' => AzureSyncState::USERGROUPS_DATALINK]);
183
184
            $query = $usergroupsDeltaLink
185
                ? $usergroupsDeltaLink->getValue()
186
                : sprintf('$select=%s', implode(',', AzureAuthenticatorHelper::QUERY_GROUP_FIELDS));
187
        } else {
188
            $query = sprintf(
189
                '$top=%d&$select=%s',
190
                AzureSyncState::API_PAGE_SIZE,
191
                implode(',', AzureAuthenticatorHelper::QUERY_GROUP_FIELDS)
192
            );
193
        }
194
195
        $token = null;
196
197
        do {
198
            try {
199
                $this->generateOrRefreshToken($token);
200
201
                $azureGroupsRequest = $this->provider->get(
202
                    $getUsergroupsDelta ? "/v1.0/groups/delta?$query" : "/v1.0/groups?$query",
203
                    $token
204
                );
205
            } catch (Exception|GuzzleException $e) {
206
                throw new Exception('Exception when requesting groups from Azure: '.$e->getMessage());
207
            }
208
209
            $azureGroupsInfo = $azureGroupsRequest ?? [];
210
211
            foreach ($azureGroupsInfo as $azureGroupInfo) {
212
                if (!empty($this->providerParams['group_filter_regex']) &&
213
                    !preg_match("/{$this->providerParams['group_filter_regex']}/", $azureGroupInfo['displayName'])
214
                ) {
215
                    continue;
216
                }
217
218
                yield $azureGroupInfo;
219
            }
220
221
            $hasNextLink = false;
222
223
            if (!empty($azureGroupsRequest['@odata.nextLink'])) {
224
                $hasNextLink = true;
225
                $query = parse_url($azureGroupsRequest['@odata.nextLink'], PHP_URL_QUERY);
226
            }
227
228
            if ($getUsergroupsDelta && !empty($azureGroupsRequest['@odata.deltaLink'])) {
229
                $this->syncStateRepo->save(
230
                    AzureSyncState::USERGROUPS_DATALINK,
231
                    parse_url($azureGroupsRequest['@odata.deltaLink'], PHP_URL_QUERY),
232
                );
233
            }
234
        } while ($hasNextLink);
235
    }
236
}
237