Passed
Pull Request — master (#5640)
by
unknown
07:05
created

AbstractMigrationChamilo::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 2
dl 0
loc 4
rs 10
c 0
b 0
f 0
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\Migrations\AbstractMigration;
26
use Doctrine\ORM\EntityManagerInterface;
27
use Psr\Log\LoggerInterface;
28
use Symfony\Component\DependencyInjection\ContainerInterface;
29
use Symfony\Component\Filesystem\Filesystem;
30
use Symfony\Component\HttpFoundation\File\UploadedFile;
31
32
abstract class AbstractMigrationChamilo extends AbstractMigration
33
{
34
    public const BATCH_SIZE = 20;
35
36
    protected ?EntityManagerInterface $entityManager = null;
37
    protected ?ContainerInterface $container = null;
38
39
    private LoggerInterface $logger;
40
41
    public function __construct($connection, LoggerInterface $logger)
42
    {
43
        parent::__construct($connection, $logger);
44
        $this->logger = $logger;
45
    }
46
47
    protected function getLogger(): LoggerInterface
48
    {
49
        return $this->logger;
50
    }
51
52
    public function setEntityManager(EntityManagerInterface $entityManager): void
53
    {
54
        $this->entityManager = $entityManager;
55
    }
56
57
    public function setContainer(?ContainerInterface $container = null): void
58
    {
59
        $this->container = $container;
60
    }
61
62
    public function adminExist(): bool
63
    {
64
        $sql = 'SELECT user_id FROM admin WHERE user_id IN (SELECT id FROM user) ORDER BY id LIMIT 1';
65
        $result = $this->connection->executeQuery($sql);
66
        $adminRow = $result->fetchAssociative();
67
68
        if (empty($adminRow)) {
69
            return false;
70
        }
71
72
        return true;
73
    }
74
75
    public function getAdmin(): User
76
    {
77
        $admin = $this->entityManager
78
            ->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

78
            ->/** @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...
79
            ->findOneBy([], ['id' => 'ASC'])
80
        ;
81
82
        return $admin->getUser();
83
    }
84
85
    /**
86
     * Speeds up SettingsCurrent creation.
87
     *
88
     * @param string $variable            The variable itself
89
     * @param string $subKey              The subkey
90
     * @param string $type                The type of setting (text, radio, select, etc)
91
     * @param string $category            The category (Platform, User, etc)
92
     * @param string $selectedValue       The default value
93
     * @param string $title               The setting title string name
94
     * @param string $comment             The setting comment string name
95
     * @param string $scope               The scope
96
     * @param string $subKeyText          Text if there is a subKey
97
     * @param int    $accessUrl           What URL it is for
98
     * @param bool   $accessUrlChangeable Whether it can be changed on each url
99
     * @param bool   $accessUrlLocked     Whether the setting for the current URL is
100
     *                                    locked to the current value
101
     * @param array  $options             Optional array in case of a radio-type field,
102
     *                                    to insert options
103
     */
104
    public function addSettingCurrent(
105
        $variable,
106
        $subKey,
107
        $type,
108
        $category,
109
        $selectedValue,
110
        $title,
111
        $comment,
112
        $scope = '',
113
        $subKeyText = '',
114
        $accessUrl = 1,
115
        $accessUrlChangeable = false,
116
        $accessUrlLocked = true,
117
        $options = []
118
    ): void {
119
        $accessUrl = $this->entityManager->find(AccessUrl::class, $accessUrl);
120
121
        $setting = new SettingsCurrent();
122
        $setting
123
            ->setVariable($variable)
124
            ->setSubkey($subKey)
125
            ->setType($type)
126
            ->setCategory($category)
127
            ->setSelectedValue($selectedValue)
128
            ->setTitle($title)
129
            ->setComment($comment)
130
            ->setScope($scope)
131
            ->setSubkeytext($subKeyText)
132
            ->setUrl($accessUrl)
133
            ->setAccessUrlChangeable((int) $accessUrlChangeable)
134
            ->setAccessUrlLocked((int) $accessUrlLocked)
135
        ;
136
137
        $this->entityManager->persist($setting);
138
139
        if (\count($options) > 0) {
140
            foreach ($options as $option) {
141
                if (empty($option['text'])) {
142
                    if ('true' === $option['value']) {
143
                        $option['text'] = 'Yes';
144
                    } else {
145
                        $option['text'] = 'No';
146
                    }
147
                }
148
149
                $settingOption = new SettingsOptions();
150
                $settingOption
151
                    ->setVariable($variable)
152
                    ->setValue($option['value'])
153
                    ->setDisplayText($option['text'])
154
                ;
155
156
                $this->entityManager->persist($settingOption);
157
            }
158
        }
159
        $this->entityManager->flush();
160
    }
161
162
    /**
163
     * @param string     $variable
164
     * @param null|mixed $configuration
165
     */
166
    public function getConfigurationValue($variable, $configuration = null)
167
    {
168
        global $_configuration;
169
170
        if (isset($configuration)) {
171
            $_configuration = $configuration;
172
        }
173
174
        if (isset($_configuration[$variable])) {
175
            return $_configuration[$variable];
176
        }
177
178
        return false;
179
    }
180
181
    public function getMailConfigurationValue(string $variable, array $configuration = []): mixed
182
    {
183
        global $platform_email;
184
185
        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...
186
            $platform_email = $configuration;
187
        }
188
189
        if (isset($platform_email[$variable])) {
190
            return $platform_email[$variable];
191
        }
192
193
        return false;
194
    }
195
196
    /**
197
     * Remove a setting completely.
198
     *
199
     * @param string $variable The setting variable name
200
     */
201
    public function removeSettingCurrent($variable): void
202
    {
203
        // to be implemented
204
    }
205
206
    public function addLegacyFileToResource(
207
        string $filePath,
208
        ResourceRepository $repo,
209
        AbstractResource $resource,
210
        $id,
211
        $fileName = '',
212
        $description = ''
213
    ): bool {
214
        $class = $resource::class;
215
        $documentPath = basename($filePath);
216
217
        if (is_dir($filePath) || (!is_dir($filePath) && !file_exists($filePath))) {
218
            $this->warnIf(true, "Cannot migrate {$class} #'.{$id}.' file not found: {$documentPath}");
219
220
            return false;
221
        }
222
223
        $mimeType = mime_content_type($filePath);
224
        if (empty($fileName)) {
225
            $fileName = basename($documentPath);
226
        }
227
        $file = new UploadedFile($filePath, $fileName, $mimeType, null, true);
228
        $repo->addFile($resource, $file);
229
230
        return true;
231
    }
232
233
    public function fixItemProperty(
234
        $tool,
235
        ResourceRepository $repo,
236
        $course,
237
        $admin,
238
        ResourceInterface $resource,
239
        $parentResource,
240
        array $items = []
241
    ) {
242
        $courseId = $course->getId();
243
        $id = $resource->getResourceIdentifier();
244
245
        if (empty($items)) {
246
            $sql = "SELECT * FROM c_item_property
247
                    WHERE tool = '{$tool}' AND c_id = {$courseId} AND ref = {$id}";
248
            $result = $this->connection->executeQuery($sql);
249
            $items = $result->fetchAllAssociative();
250
        }
251
252
        // For some reason the resource doesn't have a c_item_property value.
253
        if (empty($items)) {
254
            return false;
255
        }
256
257
        $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

257
        /** @scrutinizer ignore-call */ 
258
        $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...
258
        $groupRepo = $this->container->get(CGroupRepository::class);
259
        $userRepo = $this->container->get(UserRepository::class);
260
261
        $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

261
        $resource->/** @scrutinizer ignore-call */ 
262
                   setParent($parentResource);
Loading history...
262
        $resourceNode = null;
263
        $userList = [];
264
        $groupList = [];
265
        $sessionList = [];
266
        foreach ($items as $item) {
267
            $visibility = (int) $item['visibility'];
268
            $userId = (int) $item['insert_user_id'];
269
            $sessionId = $item['session_id'] ?? 0;
270
            $groupId = $item['to_group_id'] ?? 0;
271
            if (empty($item['lastedit_date'])) {
272
                $lastUpdatedAt = new DateTime('now', new DateTimeZone('UTC'));
273
            } else {
274
                $lastUpdatedAt = new DateTime($item['lastedit_date'], new DateTimeZone('UTC'));
275
            }
276
            $newVisibility = ResourceLink::VISIBILITY_DRAFT;
277
278
            // Old 1.11.x visibility (item property) is based in this switch:
279
            switch ($visibility) {
280
                case 0:
281
                    $newVisibility = ResourceLink::VISIBILITY_DRAFT;
282
283
                    break;
284
285
                case 1:
286
                    $newVisibility = ResourceLink::VISIBILITY_PUBLISHED;
287
288
                    break;
289
            }
290
291
            // If c_item_property.insert_user_id doesn't exist we use the first admin id.
292
            $user = null;
293
            if (isset($userList[$userId])) {
294
                $user = $userList[$userId];
295
            } else {
296
                if (!empty($userId)) {
297
                    $userFound = $userRepo->find($userId);
298
                    if ($userFound) {
299
                        $user = $userList[$userId] = $userRepo->find($userId);
300
                    }
301
                }
302
            }
303
304
            if (null === $user) {
305
                $user = $admin;
306
            }
307
308
            $session = null;
309
            if (!empty($sessionId)) {
310
                if (isset($sessionList[$sessionId])) {
311
                    $session = $sessionList[$sessionId];
312
                } else {
313
                    $session = $sessionList[$sessionId] = $sessionRepo->find($sessionId);
314
                }
315
            }
316
317
            $group = null;
318
            if (!empty($groupId)) {
319
                if (isset($groupList[$groupId])) {
320
                    $group = $groupList[$groupId];
321
                } else {
322
                    $group = $groupList[$groupId] = $groupRepo->find($groupId);
323
                }
324
            }
325
326
            if (null === $resourceNode) {
327
                $resourceNode = $repo->addResourceNode($resource, $user, $parentResource);
328
                $this->entityManager->persist($resourceNode);
329
            }
330
            $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

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