Passed
Push — master ( 4e288b...e6188e )
by
unknown
09:39 queued 18s
created

AbstractMigrationChamilo::addSettingCurrent()   A

Complexity

Conditions 5
Paths 2

Size

Total Lines 56
Code Lines 30

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 30
c 0
b 0
f 0
nc 2
nop 13
dl 0
loc 56
rs 9.1288

How to fix   Long Method    Many Parameters   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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
declare(strict_types=1);
4
5
/* For licensing terms, see /license.txt */
6
7
namespace Chamilo\CoreBundle\Migrations;
8
9
use Chamilo\CoreBundle\Entity\AbstractResource;
10
use Chamilo\CoreBundle\Entity\AccessUrl;
11
use Chamilo\CoreBundle\Entity\Admin;
12
use Chamilo\CoreBundle\Entity\Course;
13
use Chamilo\CoreBundle\Entity\ResourceInterface;
14
use Chamilo\CoreBundle\Entity\ResourceLink;
15
use Chamilo\CoreBundle\Entity\Session;
16
use Chamilo\CoreBundle\Entity\SettingsCurrent;
17
use Chamilo\CoreBundle\Entity\SettingsOptions;
18
use Chamilo\CoreBundle\Entity\User;
19
use Chamilo\CoreBundle\Repository\Node\UserRepository;
20
use Chamilo\CoreBundle\Repository\ResourceRepository;
21
use Chamilo\CoreBundle\Repository\SessionRepository;
22
use Chamilo\CourseBundle\Repository\CGroupRepository;
23
use DateTime;
24
use DateTimeZone;
25
use Doctrine\DBAL\Connection;
26
use Doctrine\Migrations\AbstractMigration;
27
use Doctrine\ORM\EntityManagerInterface;
28
use Psr\Log\LoggerInterface;
29
use Symfony\Component\DependencyInjection\ContainerInterface;
30
use Symfony\Component\Filesystem\Filesystem;
31
use Symfony\Component\HttpFoundation\File\UploadedFile;
32
33
abstract class AbstractMigrationChamilo extends AbstractMigration
34
{
35
    public const BATCH_SIZE = 20;
36
37
    protected ?EntityManagerInterface $entityManager = null;
38
    protected ?ContainerInterface $container = null;
39
40
    private LoggerInterface $logger;
41
42
    public function __construct(Connection $connection, LoggerInterface $logger)
43
    {
44
        parent::__construct($connection, $logger);
45
        $this->logger = $logger;
46
    }
47
48
    protected function getLogger(): LoggerInterface
49
    {
50
        return $this->logger;
51
    }
52
53
    public function setEntityManager(EntityManagerInterface $entityManager): void
54
    {
55
        $this->entityManager = $entityManager;
56
    }
57
58
    public function setContainer(?ContainerInterface $container = null): void
59
    {
60
        $this->container = $container;
61
    }
62
63
    public function adminExist(): bool
64
    {
65
        $sql = 'SELECT user_id FROM admin WHERE user_id IN (SELECT id FROM user) ORDER BY id LIMIT 1';
66
        $result = $this->connection->executeQuery($sql);
67
        $adminRow = $result->fetchAssociative();
68
69
        if (empty($adminRow)) {
70
            return false;
71
        }
72
73
        return true;
74
    }
75
76
    public function getAdmin(): User
77
    {
78
        $admin = $this->entityManager
79
            ->getRepository(Admin::class)
0 ignored issues
show
Bug introduced by
The method getRepository() does not exist on null. ( Ignorable by Annotation )

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

79
            ->/** @scrutinizer ignore-call */ getRepository(Admin::class)

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
80
            ->findOneBy([], ['id' => 'ASC'])
81
        ;
82
83
        return $admin->getUser();
84
    }
85
86
    /**
87
     * Speeds up SettingsCurrent creation.
88
     *
89
     * @param string $variable            The variable itself
90
     * @param string $subKey              The subkey
91
     * @param string $type                The type of setting (text, radio, select, etc)
92
     * @param string $category            The category (Platform, User, etc)
93
     * @param string $selectedValue       The default value
94
     * @param string $title               The setting title string name
95
     * @param string $comment             The setting comment string name
96
     * @param string $scope               The scope
97
     * @param string $subKeyText          Text if there is a subKey
98
     * @param int    $accessUrl           What URL it is for
99
     * @param bool   $accessUrlChangeable Whether it can be changed on each url
100
     * @param bool   $accessUrlLocked     Whether the setting for the current URL is
101
     *                                    locked to the current value
102
     * @param array  $options             Optional array in case of a radio-type field,
103
     *                                    to insert options
104
     */
105
    public function addSettingCurrent(
106
        $variable,
107
        $subKey,
108
        $type,
109
        $category,
110
        $selectedValue,
111
        $title,
112
        $comment,
113
        $scope = '',
114
        $subKeyText = '',
115
        $accessUrl = 1,
116
        $accessUrlChangeable = false,
117
        $accessUrlLocked = true,
118
        $options = []
119
    ): void {
120
        $accessUrl = $this->entityManager->find(AccessUrl::class, $accessUrl);
121
122
        $setting = new SettingsCurrent();
123
        $setting
124
            ->setVariable($variable)
125
            ->setSubkey($subKey)
126
            ->setType($type)
127
            ->setCategory($category)
128
            ->setSelectedValue($selectedValue)
129
            ->setTitle($title)
130
            ->setComment($comment)
131
            ->setScope($scope)
132
            ->setSubkeytext($subKeyText)
133
            ->setUrl($accessUrl)
134
            ->setAccessUrlChangeable((int) $accessUrlChangeable)
135
            ->setAccessUrlLocked((int) $accessUrlLocked)
136
        ;
137
138
        $this->entityManager->persist($setting);
139
140
        if (\count($options) > 0) {
141
            foreach ($options as $option) {
142
                if (empty($option['text'])) {
143
                    if ('true' === $option['value']) {
144
                        $option['text'] = 'Yes';
145
                    } else {
146
                        $option['text'] = 'No';
147
                    }
148
                }
149
150
                $settingOption = new SettingsOptions();
151
                $settingOption
152
                    ->setVariable($variable)
153
                    ->setValue($option['value'])
154
                    ->setDisplayText($option['text'])
155
                ;
156
157
                $this->entityManager->persist($settingOption);
158
            }
159
        }
160
        $this->entityManager->flush();
161
    }
162
163
    /**
164
     * @param string     $variable
165
     * @param null|mixed $configuration
166
     */
167
    public function getConfigurationValue($variable, $configuration = null)
168
    {
169
        global $_configuration;
170
171
        if (isset($configuration)) {
172
            $_configuration = $configuration;
173
        }
174
175
        if (isset($_configuration[$variable])) {
176
            return $_configuration[$variable];
177
        }
178
179
        return false;
180
    }
181
182
    public function getMailConfigurationValue(string $variable, array $configuration = []): mixed
183
    {
184
        global $platform_email;
185
186
        if ($configuration) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $configuration of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
187
            $platform_email = $configuration;
188
        }
189
190
        if (isset($platform_email[$variable])) {
191
            return $platform_email[$variable];
192
        }
193
194
        return false;
195
    }
196
197
    /**
198
     * Remove a setting completely.
199
     *
200
     * @param string $variable The setting variable name
201
     */
202
    public function removeSettingCurrent($variable): void
203
    {
204
        // to be implemented
205
    }
206
207
    public function addLegacyFileToResource(
208
        string $filePath,
209
        ResourceRepository $repo,
210
        AbstractResource $resource,
211
        $id,
212
        $fileName = '',
213
        $description = ''
214
    ): bool {
215
        $class = $resource::class;
216
        $documentPath = basename($filePath);
217
218
        if (is_dir($filePath) || (!is_dir($filePath) && !file_exists($filePath))) {
219
            $this->warnIf(true, "Cannot migrate {$class} #'.{$id}.' file not found: {$documentPath}");
220
221
            return false;
222
        }
223
224
        $mimeType = mime_content_type($filePath);
225
        if (empty($fileName)) {
226
            $fileName = basename($documentPath);
227
        }
228
        $file = new UploadedFile($filePath, $fileName, $mimeType, null, true);
229
        $repo->addFile($resource, $file);
230
231
        return true;
232
    }
233
234
    public function fixItemProperty(
235
        $tool,
236
        ResourceRepository $repo,
237
        $course,
238
        $admin,
239
        ResourceInterface $resource,
240
        $parentResource,
241
        array $items = []
242
    ) {
243
        $courseId = $course->getId();
244
        $id = $resource->getResourceIdentifier();
245
246
        if (empty($items)) {
247
            $sql = "SELECT * FROM c_item_property
248
                    WHERE tool = '{$tool}' AND c_id = {$courseId} AND ref = {$id}";
249
            $result = $this->connection->executeQuery($sql);
250
            $items = $result->fetchAllAssociative();
251
        }
252
253
        // For some reason the resource doesn't have a c_item_property value.
254
        if (empty($items)) {
255
            return false;
256
        }
257
258
        $sessionRepo = $this->container->get(SessionRepository::class);
0 ignored issues
show
Bug introduced by
The method get() does not exist on null. ( Ignorable by Annotation )

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

258
        /** @scrutinizer ignore-call */ 
259
        $sessionRepo = $this->container->get(SessionRepository::class);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
259
        $groupRepo = $this->container->get(CGroupRepository::class);
260
        $userRepo = $this->container->get(UserRepository::class);
261
262
        $resource->setParent($parentResource);
0 ignored issues
show
Bug introduced by
The method setParent() does not exist on Chamilo\CoreBundle\Entity\ResourceInterface. Since it exists in all sub-types, consider adding an abstract or default implementation to Chamilo\CoreBundle\Entity\ResourceInterface. ( Ignorable by Annotation )

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

262
        $resource->/** @scrutinizer ignore-call */ 
263
                   setParent($parentResource);
Loading history...
263
        $resourceNode = null;
264
        $userList = [];
265
        $groupList = [];
266
        $sessionList = [];
267
        foreach ($items as $item) {
268
            $visibility = (int) $item['visibility'];
269
            $userId = (int) $item['insert_user_id'];
270
            $sessionId = $item['session_id'] ?? 0;
271
            $groupId = $item['to_group_id'] ?? 0;
272
            if (empty($item['lastedit_date'])) {
273
                $lastUpdatedAt = new DateTime('now', new DateTimeZone('UTC'));
274
            } else {
275
                $lastUpdatedAt = new DateTime($item['lastedit_date'], new DateTimeZone('UTC'));
276
            }
277
            $newVisibility = ResourceLink::VISIBILITY_DRAFT;
278
279
            // Old 1.11.x visibility (item property) is based in this switch:
280
            switch ($visibility) {
281
                case 0:
282
                    $newVisibility = ResourceLink::VISIBILITY_DRAFT;
283
284
                    break;
285
286
                case 1:
287
                    $newVisibility = ResourceLink::VISIBILITY_PUBLISHED;
288
289
                    break;
290
            }
291
292
            // If c_item_property.insert_user_id doesn't exist we use the first admin id.
293
            $user = null;
294
            if (isset($userList[$userId])) {
295
                $user = $userList[$userId];
296
            } else {
297
                if (!empty($userId)) {
298
                    $userFound = $userRepo->find($userId);
299
                    if ($userFound) {
300
                        $user = $userList[$userId] = $userRepo->find($userId);
301
                    }
302
                }
303
            }
304
305
            if (null === $user) {
306
                $user = $admin;
307
            }
308
309
            $session = null;
310
            if (!empty($sessionId)) {
311
                if (isset($sessionList[$sessionId])) {
312
                    $session = $sessionList[$sessionId];
313
                } else {
314
                    $session = $sessionList[$sessionId] = $sessionRepo->find($sessionId);
315
                }
316
            }
317
318
            $group = null;
319
            if (!empty($groupId)) {
320
                if (isset($groupList[$groupId])) {
321
                    $group = $groupList[$groupId];
322
                } else {
323
                    $group = $groupList[$groupId] = $groupRepo->find($groupId);
324
                }
325
            }
326
327
            if (null === $resourceNode) {
328
                $resourceNode = $repo->addResourceNode($resource, $user, $parentResource);
329
                $this->entityManager->persist($resourceNode);
330
            }
331
            $resource->addCourseLink($course, $session, $group, $newVisibility);
0 ignored issues
show
Bug introduced by
The method addCourseLink() does not exist on Chamilo\CoreBundle\Entity\ResourceInterface. It seems like you code against a sub-type of said class. However, the method does not exist in Chamilo\CoreBundle\Entity\User. Are you sure you never get one of those? ( Ignorable by Annotation )

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

331
            $resource->/** @scrutinizer ignore-call */ 
332
                       addCourseLink($course, $session, $group, $newVisibility);
Loading history...
332
333
            if (2 === $visibility) {
334
                $link = $resource->getResourceNode()->getResourceLinkByContext($course, $session, $group);
335
                $link->setDeletedAt($lastUpdatedAt);
336
            }
337
338
            $this->entityManager->persist($resource);
339
        }
340
341
        return true;
342
    }
343
344
    public function fileExists($filePath): bool
345
    {
346
        return file_exists($filePath) && !is_dir($filePath) && is_readable($filePath);
347
    }
348
349
    public function findCourse(int $id): ?Course
350
    {
351
        if (0 === $id) {
352
            return null;
353
        }
354
355
        return $this->entityManager->find(Course::class, $id);
356
    }
357
358
    public function findSession(int $id): ?Session
359
    {
360
        if (0 === $id) {
361
            return null;
362
        }
363
364
        return $this->entityManager->find(Session::class, $id);
365
    }
366
367
    public function getMailConfigurationValueFromFile(string $variable): ?string
368
    {
369
        global $platform_email;
370
371
        $rootPath = $this->container->get('kernel')->getProjectDir();
372
        $oldConfigPath = $this->getUpdateRootPath().'/app/config/mail.conf.php';
373
374
        $configFileLoaded = \in_array($oldConfigPath, get_included_files(), true);
375
376
        if (!$configFileLoaded) {
377
            include_once $oldConfigPath;
378
        }
379
380
        $settingValue = $this->getConfigurationValue($variable, $platform_email);
381
382
        if (\is_bool($settingValue)) {
383
            $selectedValue = var_export($settingValue, true);
384
        } else {
385
            $selectedValue = (string) $settingValue;
386
        }
387
388
        return $selectedValue;
389
    }
390
391
    private function generateFilePath(string $filename): string
392
    {
393
        $cacheDir = $this->container->get('kernel')->getCacheDir();
394
395
        return $cacheDir.'/migration_'.$filename;
396
    }
397
398
    protected function writeFile(string $filename, string $content): void
399
    {
400
        $fullFilename = $this->generateFilePath($filename);
401
402
        $fs = new Filesystem();
403
        $fs->dumpFile($fullFilename, $content);
404
    }
405
406
    protected function readFile(string $filename): string
407
    {
408
        $fullFilename = $this->generateFilePath($filename);
409
410
        return file_get_contents($fullFilename);
411
    }
412
413
    protected function removeFile(string $filename): void
414
    {
415
        $fullFilename = $this->generateFilePath($filename);
416
417
        $fs = new Filesystem();
418
        $fs->remove($fullFilename);
419
    }
420
421
    protected function getUpdateRootPath(): string
422
    {
423
        $updateRootPath = getenv('UPDATE_PATH');
424
425
        if (!empty($updateRootPath)) {
426
427
            error_log('getUpdateRootPath ::: '.$updateRootPath);
428
429
            return rtrim($updateRootPath, '/');
430
        }
431
432
        return $this->container->getParameter('kernel.project_dir');
433
    }
434
}
435