Passed
Pull Request — master (#5310)
by Angel Fernando Quiroz
07:05
created

AbstractMigrationChamilo::generateFilePath()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
c 0
b 0
f 0
nc 1
nop 1
dl 0
loc 5
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\Migrations\AbstractMigration;
26
use Doctrine\ORM\EntityManager;
27
use ReflectionClass;
28
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
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 implements ContainerAwareInterface
34
{
35
    public const BATCH_SIZE = 20;
36
37
    private ?EntityManager $manager = null;
38
    private ?ContainerInterface $container = null;
39
40
    public function setEntityManager(EntityManager $manager): void
41
    {
42
        $this->manager = $manager;
43
    }
44
45
    public function setContainer(?ContainerInterface $container = null): void
46
    {
47
        $this->container = $container;
48
    }
49
50
    /**
51
     * @return ContainerInterface
52
     */
53
    public function getContainer()
54
    {
55
        return $this->container;
56
    }
57
58
    public function adminExist(): bool
59
    {
60
        $em = $this->getEntityManager();
61
        $connection = $em->getConnection();
62
63
        $sql = 'SELECT user_id FROM admin WHERE user_id IN (SELECT id FROM user) ORDER BY id LIMIT 1';
64
        $result = $connection->executeQuery($sql);
65
        $adminRow = $result->fetchAssociative();
66
67
        if (empty($adminRow)) {
68
            return false;
69
        }
70
71
        return true;
72
    }
73
74
    public function getAdmin(): User
75
    {
76
        $admin = $this->getEntityManager()
77
            ->getRepository(Admin::class)
78
            ->findOneBy([], ['id' => 'ASC'])
79
        ;
80
81
        return $admin->getUser();
82
    }
83
84
    /**
85
     * @return EntityManager
86
     */
87
    public function getEntityManager()
88
    {
89
        return $this->getContainer()->get('doctrine')->getManager();
90
    }
91
92
    /**
93
     * Speeds up SettingsCurrent creation.
94
     *
95
     * @param string $variable            The variable itself
96
     * @param string $subKey              The subkey
97
     * @param string $type                The type of setting (text, radio, select, etc)
98
     * @param string $category            The category (Platform, User, etc)
99
     * @param string $selectedValue       The default value
100
     * @param string $title               The setting title string name
101
     * @param string $comment             The setting comment string name
102
     * @param string $scope               The scope
103
     * @param string $subKeyText          Text if there is a subKey
104
     * @param int    $accessUrl           What URL it is for
105
     * @param bool   $accessUrlChangeable Whether it can be changed on each url
106
     * @param bool   $accessUrlLocked     Whether the setting for the current URL is
107
     *                                    locked to the current value
108
     * @param array  $options             Optional array in case of a radio-type field,
109
     *                                    to insert options
110
     */
111
    public function addSettingCurrent(
112
        $variable,
113
        $subKey,
114
        $type,
115
        $category,
116
        $selectedValue,
117
        $title,
118
        $comment,
119
        $scope = '',
120
        $subKeyText = '',
121
        $accessUrl = 1,
122
        $accessUrlChangeable = false,
123
        $accessUrlLocked = true,
124
        $options = []
125
    ): void {
126
        $em = $this->getEntityManager();
127
128
        $accessUrl = $em->find(AccessUrl::class, $accessUrl);
129
130
        $setting = new SettingsCurrent();
131
        $setting
132
            ->setVariable($variable)
133
            ->setSubkey($subKey)
134
            ->setType($type)
135
            ->setCategory($category)
136
            ->setSelectedValue($selectedValue)
137
            ->setTitle($title)
138
            ->setComment($comment)
139
            ->setScope($scope)
140
            ->setSubkeytext($subKeyText)
141
            ->setUrl($accessUrl)
142
            ->setAccessUrlChangeable((int) $accessUrlChangeable)
143
            ->setAccessUrlLocked((int) $accessUrlLocked)
144
        ;
145
146
        $em->persist($setting);
147
148
        if (\count($options) > 0) {
149
            foreach ($options as $option) {
150
                if (empty($option['text'])) {
151
                    if ('true' === $option['value']) {
152
                        $option['text'] = 'Yes';
153
                    } else {
154
                        $option['text'] = 'No';
155
                    }
156
                }
157
158
                $settingOption = new SettingsOptions();
159
                $settingOption
160
                    ->setVariable($variable)
161
                    ->setValue($option['value'])
162
                    ->setDisplayText($option['text'])
163
                ;
164
165
                $em->persist($settingOption);
166
            }
167
        }
168
        $em->flush();
169
    }
170
171
    /**
172
     * @param string     $variable
173
     * @param null|mixed $configuration
174
     */
175
    public function getConfigurationValue($variable, $configuration = null)
176
    {
177
        global $_configuration;
178
179
        if (isset($configuration)) {
180
            $_configuration = $configuration;
181
        }
182
183
        if (isset($_configuration[$variable])) {
184
            return $_configuration[$variable];
185
        }
186
187
        return false;
188
    }
189
190
    /**
191
     * Remove a setting completely.
192
     *
193
     * @param string $variable The setting variable name
194
     */
195
    public function removeSettingCurrent($variable): void
196
    {
197
        // to be implemented
198
    }
199
200
    public function addLegacyFileToResource(
201
        string $filePath,
202
        ResourceRepository $repo,
203
        AbstractResource $resource,
204
        $id,
205
        $fileName = '',
206
        $description = ''
207
    ): bool {
208
        $class = $resource::class;
209
        $documentPath = basename($filePath);
210
211
        if (is_dir($filePath) || (!is_dir($filePath) && !file_exists($filePath))) {
212
            $this->warnIf(true, "Cannot migrate {$class} #'.{$id}.' file not found: {$documentPath}");
213
214
            return false;
215
        }
216
217
        $mimeType = mime_content_type($filePath);
218
        if (empty($fileName)) {
219
            $fileName = basename($documentPath);
220
        }
221
        $file = new UploadedFile($filePath, $fileName, $mimeType, null, true);
222
        $repo->addFile($resource, $file);
223
224
        return true;
225
    }
226
227
    public function fixItemProperty(
228
        $tool,
229
        ResourceRepository $repo,
230
        $course,
231
        $admin,
232
        ResourceInterface $resource,
233
        $parentResource,
234
        array $items = []
235
    ) {
236
        $container = $this->getContainer();
237
        $em = $this->getEntityManager();
238
        $connection = $em->getConnection();
239
240
        $courseId = $course->getId();
241
        $id = $resource->getResourceIdentifier();
242
243
        if (empty($items)) {
244
            $sql = "SELECT * FROM c_item_property
245
                    WHERE tool = '{$tool}' AND c_id = {$courseId} AND ref = {$id}";
246
            $result = $connection->executeQuery($sql);
247
            $items = $result->fetchAllAssociative();
248
        }
249
250
        // For some reason the resource doesn't have a c_item_property value.
251
        if (empty($items)) {
252
            return false;
253
        }
254
255
        $sessionRepo = $container->get(SessionRepository::class);
256
        $groupRepo = $container->get(CGroupRepository::class);
257
        $userRepo = $container->get(UserRepository::class);
258
259
        $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

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

328
            $resource->/** @scrutinizer ignore-call */ 
329
                       addCourseLink($course, $session, $group, $newVisibility);
Loading history...
329
330
            if (2 === $visibility) {
331
                $link = $resource->getResourceNode()->getResourceLinkByContext($course, $session, $group);
332
                $link->setDeletedAt($lastUpdatedAt);
333
            }
334
335
            $em->persist($resource);
336
        }
337
338
        return true;
339
    }
340
341
    public function fileExists($filePath): bool
342
    {
343
        return file_exists($filePath) && !is_dir($filePath) && is_readable($filePath);
344
    }
345
346
    public function findCourse(int $id): ?Course
347
    {
348
        if (0 === $id) {
349
            return null;
350
        }
351
352
        return $this->getEntityManager()->find(Course::class, $id);
353
    }
354
355
    public function findSession(int $id): ?Session
356
    {
357
        if (0 === $id) {
358
            return null;
359
        }
360
361
        return $this->getEntityManager()->find(Session::class, $id);
362
    }
363
364
    private function getVersionName(): string
0 ignored issues
show
Unused Code introduced by
The method getVersionName() is not used, and could be removed.

This check looks for private methods that have been defined, but are not used inside the class.

Loading history...
365
    {
366
        return (new ReflectionClass($this))->getShortName();
367
    }
368
369
    private function generateFilePath(string $filename): string
370
    {
371
        $cacheDir = $this->getContainer()->get('kernel')->getCacheDir();
372
373
        return $cacheDir.'/migration_'.$filename;
374
    }
375
376
    protected function writeFile(string $filename, string $content): void
377
    {
378
        $fullFilename = $this->generateFilePath($filename);
379
380
        $fs = new Filesystem();
381
        $fs->dumpFile($fullFilename, $content);
382
    }
383
384
    protected function readFile(string $filename): string
385
    {
386
        $fullFilename = $this->generateFilePath($filename);
387
388
        return file_get_contents($fullFilename);
389
    }
390
}
391