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

getMailConfigurationValue()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 13
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 6
c 0
b 0
f 0
nc 4
nop 2
dl 0
loc 13
rs 10
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