Passed
Push — master ( c22b6a...5f79f5 )
by Julito
11:21
created

Meeting::preFlush()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 4
c 0
b 0
f 0
nc 4
nop 0
dl 0
loc 7
rs 10
1
<?php
2
3
/* For licensing terms, see /license.txt */
4
5
namespace Chamilo\PluginBundle\Zoom;
6
7
use Chamilo\CoreBundle\Entity\Course;
8
use Chamilo\CoreBundle\Entity\CourseRelUser;
9
use Chamilo\CoreBundle\Entity\Session;
10
use Chamilo\CoreBundle\Entity\SessionRelCourseRelUser;
11
use Chamilo\CourseBundle\Entity\CGroupInfo;
12
use Chamilo\PluginBundle\Zoom\API\MeetingInfoGet;
13
use Chamilo\PluginBundle\Zoom\API\MeetingListItem;
14
use Chamilo\PluginBundle\Zoom\API\MeetingSettings;
15
use Chamilo\UserBundle\Entity\User;
16
use Database;
17
use DateInterval;
18
use DateTime;
19
use DateTimeZone;
20
use Doctrine\Common\Collections\ArrayCollection;
21
use Doctrine\ORM\Mapping as ORM;
22
use Exception;
23
24
/**
25
 * Class Meeting.
26
 *
27
 * @ORM\Entity(repositoryClass="Chamilo\PluginBundle\Zoom\MeetingRepository")
28
 * @ORM\Table(
29
 *     name="plugin_zoom_meeting",
30
 *     indexes={
31
 *         @ORM\Index(name="user_id_index", columns={"user_id"}),
32
 *         @ORM\Index(name="course_id_index", columns={"course_id"}),
33
 *         @ORM\Index(name="session_id_index", columns={"session_id"})
34
 *     }
35
 * )
36
 * @ORM\HasLifecycleCallbacks
37
 */
38
class Meeting
39
{
40
    /** @var string meeting type name */
41
    public $typeName;
42
43
    /** @var DateTime meeting start time as a DateTime instance */
44
    public $startDateTime;
45
46
    /** @var string meeting formatted start time */
47
    public $formattedStartTime;
48
49
    /** @var DateInterval meeting duration as a DateInterval instance */
50
    public $durationInterval;
51
52
    /** @var string meeting formatted duration */
53
    public $formattedDuration;
54
55
    /** @var string */
56
    public $statusName;
57
58
    /**
59
     * @var int
60
     * @ORM\Column(type="integer")
61
     * @ORM\Id
62
     * @ORM\GeneratedValue()
63
     */
64
    protected $id;
65
66
    /**
67
     * @var int the remote zoom meeting identifier
68
     * @ORM\Column(name="meeting_id", type="string")
69
     */
70
    protected $meetingId;
71
72
    /**
73
     * @var User
74
     * @ORM\ManyToOne(targetEntity="Chamilo\UserBundle\Entity\User")
75
     * @ORM\JoinColumn(name="user_id", referencedColumnName="id", nullable=true)
76
     */
77
    protected $user;
78
79
    /**
80
     * @var Course
81
     * @ORM\ManyToOne(targetEntity="Chamilo\CoreBundle\Entity\Course")
82
     * @ORM\JoinColumn(name="course_id", referencedColumnName="id", nullable=true)
83
     */
84
    protected $course;
85
86
    /**
87
     * @var CGroupInfo
88
     * @ORM\ManyToOne(targetEntity="Chamilo\CourseBundle\Entity\CGroupInfo")
89
     * @ORM\JoinColumn(name="group_id", referencedColumnName="iid", nullable=true)
90
     */
91
    protected $group;
92
93
    /**
94
     * @var Session
95
     * @ORM\ManyToOne(targetEntity="Chamilo\CoreBundle\Entity\Session")
96
     * @ORM\JoinColumn(name="session_id", referencedColumnName="id", nullable=true)
97
     */
98
    protected $session;
99
100
    /**
101
     * @var string
102
     * @ORM\Column(type="text", name="meeting_list_item_json", nullable=true)
103
     */
104
    protected $meetingListItemJson;
105
106
    /**
107
     * @var string
108
     * @ORM\Column(type="text", name="meeting_info_get_json", nullable=true)
109
     */
110
    protected $meetingInfoGetJson;
111
112
    /** @var MeetingListItem */
113
    protected $meetingListItem;
114
115
    /** @var MeetingInfoGet */
116
    protected $meetingInfoGet;
117
118
    /**
119
     * @var MeetingActivity[]|ArrayCollection
120
     * @ORM\OrderBy({"createdAt" = "DESC"})
121
     * @ORM\OneToMany(targetEntity="MeetingActivity", mappedBy="meeting", cascade={"persist", "remove"})
122
     */
123
    protected $activities;
124
125
    /**
126
     * @var Registrant[]|ArrayCollection
127
     *
128
     * @ORM\OneToMany(targetEntity="Registrant", mappedBy="meeting", cascade={"persist", "remove"})
129
     */
130
    protected $registrants;
131
132
    /**
133
     * @var Recording[]|ArrayCollection
134
     *
135
     * @ORM\OneToMany(targetEntity="Recording", mappedBy="meeting", cascade={"persist"}, orphanRemoval=true)
136
     */
137
    protected $recordings;
138
139
    public function __construct()
140
    {
141
        $this->registrants = new ArrayCollection();
142
        $this->recordings = new ArrayCollection();
143
        $this->activities = new ArrayCollection();
144
    }
145
146
    /**
147
     * @return string
148
     */
149
    public function __toString()
150
    {
151
        return sprintf('Meeting %d', $this->id);
152
    }
153
154
    /**
155
     * @return int
156
     */
157
    public function getId()
158
    {
159
        return $this->id;
160
    }
161
162
    /**
163
     * @return int
164
     */
165
    public function getMeetingId()
166
    {
167
        return $this->meetingId;
168
    }
169
170
    /**
171
     * @param int $meetingId
172
     *
173
     * @return Meeting
174
     */
175
    public function setMeetingId($meetingId)
176
    {
177
        $this->meetingId = $meetingId;
178
179
        return $this;
180
    }
181
182
    /**
183
     * @return User
184
     */
185
    public function getUser()
186
    {
187
        return $this->user;
188
    }
189
190
    /**
191
     * @return Course
192
     */
193
    public function getCourse()
194
    {
195
        return $this->course;
196
    }
197
198
    /**
199
     * @return Session
200
     */
201
    public function getSession()
202
    {
203
        return $this->session;
204
    }
205
206
    /**
207
     * @return Registrant[]|ArrayCollection
208
     */
209
    public function getRegistrants()
210
    {
211
        return $this->registrants;
212
    }
213
214
    /**
215
     * @return Recording[]|ArrayCollection
216
     */
217
    public function getRecordings()
218
    {
219
        return $this->recordings;
220
    }
221
222
    /**
223
     * @return MeetingActivity[]|ArrayCollection
224
     */
225
    public function getActivities()
226
    {
227
        return $this->activities;
228
    }
229
230
    public function addActivity(MeetingActivity $activity)
231
    {
232
        $activity->setMeeting($this);
233
        $this->activities[] = $activity;
234
    }
235
236
    /**
237
     * @param MeetingActivity[]|ArrayCollection $activities
238
     *
239
     * @return Meeting
240
     */
241
    public function setActivities($activities)
242
    {
243
        $this->activities = $activities;
244
245
        return $this;
246
    }
247
248
    /**
249
     * @ORM\PostLoad
250
     *
251
     * @throws Exception
252
     */
253
    public function postLoad()
254
    {
255
        if (null !== $this->meetingListItemJson) {
256
            $this->meetingListItem = MeetingListItem::fromJson($this->meetingListItemJson);
257
        }
258
        if (null !== $this->meetingInfoGetJson) {
259
            $this->meetingInfoGet = MeetingInfoGet::fromJson($this->meetingInfoGetJson);
260
        }
261
        $this->initializeDisplayableProperties();
262
    }
263
264
    /**
265
     * @ORM\PostUpdate
266
     *
267
     * @throws Exception
268
     */
269
    public function postUpdate()
270
    {
271
        $this->initializeDisplayableProperties();
272
    }
273
274
    /**
275
     * @ORM\PreFlush
276
     */
277
    public function preFlush()
278
    {
279
        if (null !== $this->meetingListItem) {
280
            $this->meetingListItemJson = json_encode($this->meetingListItem);
281
        }
282
        if (null !== $this->meetingInfoGet) {
283
            $this->meetingInfoGetJson = json_encode($this->meetingInfoGet);
284
        }
285
    }
286
287
    /**
288
     * @return MeetingListItem
289
     */
290
    public function getMeetingListItem()
291
    {
292
        return $this->meetingListItem;
293
    }
294
295
    /**
296
     * @return MeetingInfoGet
297
     */
298
    public function getMeetingInfoGet()
299
    {
300
        return $this->meetingInfoGet;
301
    }
302
303
    /**
304
     * @param User $user
305
     *
306
     * @return $this
307
     */
308
    public function setUser($user)
309
    {
310
        $this->user = $user;
311
312
        return $this;
313
    }
314
315
    /**
316
     * @param Course $course
317
     *
318
     * @return $this
319
     */
320
    public function setCourse($course)
321
    {
322
        $this->course = $course;
323
324
        return $this;
325
    }
326
327
    /**
328
     * @param Session $session
329
     *
330
     * @return $this
331
     */
332
    public function setSession($session)
333
    {
334
        $this->session = $session;
335
336
        return $this;
337
    }
338
339
    /**
340
     * @return CGroupInfo
341
     */
342
    public function getGroup()
343
    {
344
        return $this->group;
345
    }
346
347
    /**
348
     * @param CGroupInfo $group
349
     *
350
     * @return Meeting
351
     */
352
    public function setGroup($group)
353
    {
354
        $this->group = $group;
355
356
        return $this;
357
    }
358
359
    /**
360
     * @param MeetingListItem $meetingListItem
361
     *
362
     * @throws Exception
363
     *
364
     * @return Meeting
365
     */
366
    public function setMeetingListItem($meetingListItem)
367
    {
368
        if (null === $this->meetingId) {
369
            $this->meetingId = $meetingListItem->id;
0 ignored issues
show
Documentation Bug introduced by
The property $meetingId was declared of type integer, but $meetingListItem->id is of type string. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
370
        } elseif ($this->meetingId != $meetingListItem->id) {
371
            throw new Exception('the Meeting identifier differs from the MeetingListItem identifier');
372
        }
373
        $this->meetingListItem = $meetingListItem;
374
375
        return $this;
376
    }
377
378
    /**
379
     * @param MeetingInfoGet $meetingInfoGet
380
     *
381
     * @throws Exception
382
     *
383
     * @return Meeting
384
     */
385
    public function setMeetingInfoGet($meetingInfoGet)
386
    {
387
        if (null === $this->meetingId) {
388
            $this->meetingId = $meetingInfoGet->id;
0 ignored issues
show
Documentation Bug introduced by
The property $meetingId was declared of type integer, but $meetingInfoGet->id is of type string. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
389
        } elseif ($this->meetingId != $meetingInfoGet->id) {
390
            throw new Exception('the Meeting identifier differs from the MeetingInfoGet identifier');
391
        }
392
        $this->meetingInfoGet = $meetingInfoGet;
393
        $this->initializeDisplayableProperties();
394
395
        return $this;
396
    }
397
398
    /**
399
     * @return bool
400
     */
401
    public function isCourseMeeting()
402
    {
403
        return null !== $this->course;
404
    }
405
406
    /**
407
     * @return bool
408
     */
409
    public function isCourseGroupMeeting()
410
    {
411
        return null !== $this->course && null !== $this->group;
412
    }
413
414
    /**
415
     * @return bool
416
     */
417
    public function isUserMeeting()
418
    {
419
        return null !== $this->user && null === $this->course;
420
    }
421
422
    /**
423
     * @return bool
424
     */
425
    public function isGlobalMeeting()
426
    {
427
        return null === $this->user && null === $this->course;
428
    }
429
430
    public function setStatus($status)
431
    {
432
        $this->meetingInfoGet->status = $status;
433
    }
434
435
    /**
436
     * Builds the list of users that can register into this meeting.
437
     * Zoom requires an email address, therefore users without an email address are excluded from the list.
438
     *
439
     * @return User[] the list of users
440
     */
441
    public function getRegistrableUsers()
442
    {
443
        $users = [];
444
        if (!$this->isCourseMeeting()) {
445
            $criteria = ['active' => true];
446
            $users = Database::getManager()->getRepository('ChamiloUserBundle:User')->findBy($criteria);
447
        } elseif (null === $this->session) {
448
            if (null !== $this->course) {
449
                /** @var CourseRelUser $courseRelUser */
450
                foreach ($this->course->getUsers() as $courseRelUser) {
451
                    $users[] = $courseRelUser->getUser();
452
                }
453
            }
454
        } else {
455
            if (null !== $this->course) {
456
                $subscriptions = $this->session->getUserCourseSubscriptionsByStatus($this->course, Session::STUDENT);
457
                if ($subscriptions) {
458
                    /** @var SessionRelCourseRelUser $sessionCourseUser */
459
                    foreach ($subscriptions as $sessionCourseUser) {
460
                        $users[] = $sessionCourseUser->getUser();
461
                    }
462
                }
463
            }
464
        }
465
466
        $activeUsersWithEmail = [];
467
        foreach ($users as $user) {
468
            if ($user->isActive() && !empty($user->getEmail())) {
469
                $activeUsersWithEmail[] = $user;
470
            }
471
        }
472
473
        return $activeUsersWithEmail;
474
    }
475
476
    /**
477
     * @return bool
478
     */
479
    public function requiresDateAndDuration()
480
    {
481
        return MeetingInfoGet::TYPE_SCHEDULED === $this->meetingInfoGet->type
482
            || MeetingInfoGet::TYPE_RECURRING_WITH_FIXED_TIME === $this->meetingInfoGet->type;
483
    }
484
485
    /**
486
     * @return bool
487
     */
488
    public function requiresRegistration()
489
    {
490
        return
491
            MeetingSettings::APPROVAL_TYPE_AUTOMATICALLY_APPROVE === $this->meetingInfoGet->settings->approval_type;
492
        /*return
493
            MeetingSettings::APPROVAL_TYPE_NO_REGISTRATION_REQUIRED != $this->meetingInfoGet->settings->approval_type;*/
494
    }
495
496
    /**
497
     * @return bool
498
     */
499
    public function hasCloudAutoRecordingEnabled()
500
    {
501
        return \ZoomPlugin::RECORDING_TYPE_NONE !== $this->meetingInfoGet->settings->auto_recording;
502
    }
503
504
    /**
505
     * @param User $user
506
     *
507
     * @return bool
508
     */
509
    public function hasRegisteredUser($user)
510
    {
511
        return $this->getRegistrants()->exists(
512
            function (Registrant $registrantEntity) use (&$user) {
513
                return $registrantEntity->getUser() === $user;
514
            }
515
        );
516
    }
517
518
    /**
519
     * @param User $user
520
     *
521
     * @return Registrant|null
522
     */
523
    public function getRegistrant($user)
524
    {
525
        foreach ($this->getRegistrants() as $registrant) {
526
            if ($registrant->getUser() === $user) {
527
                return $registrant;
528
            }
529
        }
530
531
        return null;
532
    }
533
534
    /**
535
     * Generates a short presentation of the meeting for the future participant.
536
     * To be displayed above the "Enter meeting" link.
537
     *
538
     * @return string
539
     */
540
    public function getIntroduction()
541
    {
542
        $introduction = sprintf('<h1>%s</h1>', $this->meetingInfoGet->topic);
543
        if (!$this->isGlobalMeeting()) {
544
            if (!empty($this->formattedStartTime)) {
545
                $introduction .= $this->formattedStartTime;
546
                if (!empty($this->formattedDuration)) {
547
                    $introduction .= ' ('.$this->formattedDuration.')';
548
                }
549
            }
550
        }
551
        if ($this->user) {
552
            $introduction .= sprintf('<p>%s</p>', $this->user->getFullname());
553
        } elseif ($this->isCourseMeeting()) {
554
            if (null === $this->session) {
555
                $introduction .= sprintf('<p class="main">%s</p>', $this->course);
556
            } else {
557
                $introduction .= sprintf('<p class="main">%s (%s)</p>', $this->course, $this->session);
558
            }
559
        }
560
        if (!empty($this->meetingInfoGet->agenda)) {
561
            $introduction .= sprintf('<p>%s</p>', $this->meetingInfoGet->agenda);
562
        }
563
564
        return $introduction;
565
    }
566
567
    /**
568
     * @throws Exception on unexpected start_time or duration
569
     */
570
    private function initializeDisplayableProperties()
571
    {
572
        $zoomPlugin = new \ZoomPlugin();
573
574
        $typeList = [
575
            API\Meeting::TYPE_INSTANT => $zoomPlugin->get_lang('InstantMeeting'),
576
            API\Meeting::TYPE_SCHEDULED => $zoomPlugin->get_lang('ScheduledMeeting'),
577
            API\Meeting::TYPE_RECURRING_WITH_NO_FIXED_TIME => $zoomPlugin->get_lang('RecurringWithNoFixedTime'),
578
            API\Meeting::TYPE_RECURRING_WITH_FIXED_TIME => $zoomPlugin->get_lang('RecurringWithFixedTime'),
579
        ];
580
        $this->typeName = $typeList[$this->meetingInfoGet->type];
581
582
        if (property_exists($this, 'status')) {
583
            $statusList = [
584
                'waiting' => $zoomPlugin->get_lang('Waiting'),
585
                'started' => $zoomPlugin->get_lang('Started'),
586
                'finished' => $zoomPlugin->get_lang('Finished'),
587
            ];
588
            $this->statusName = $statusList[$this->meetingInfoGet->status];
589
        }
590
        $this->startDateTime = null;
591
        $this->formattedStartTime = '';
592
        $this->durationInterval = null;
593
        $this->formattedDuration = '';
594
        if (!empty($this->meetingInfoGet->start_time)) {
595
            $this->startDateTime = new DateTime($this->meetingInfoGet->start_time);
596
            $this->startDateTime->setTimezone(new DateTimeZone(date_default_timezone_get()));
597
            $this->formattedStartTime = $this->startDateTime->format('Y-m-d H:i');
598
        }
599
600
        if (!empty($this->meetingInfoGet->duration)) {
601
            $now = new DateTime();
602
            $later = new DateTime();
603
            $later->add(new DateInterval('PT'.$this->meetingInfoGet->duration.'M'));
604
            $this->durationInterval = $later->diff($now);
0 ignored issues
show
Documentation Bug introduced by
It seems like $later->diff($now) can also be of type false. However, the property $durationInterval is declared as type DateInterval. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
605
            $this->formattedDuration = $this->durationInterval->format($zoomPlugin->get_lang('DurationFormat'));
606
        }
607
    }
608
}
609