Passed
Push — 1.11.x ( b4ce57...e435f5 )
by Julito
09:28
created

Meeting::requiresDateAndDuration()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 2
c 0
b 0
f 0
nc 2
nop 0
dl 0
loc 4
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="id", 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
     *
121
     * @ORM\OneToMany(targetEntity="MeetingActivity", mappedBy="meeting", cascade={"persist", "remove"})
122
     *
123
     */
124
    protected $activities;
125
126
    /**
127
     * @var Registrant[]|ArrayCollection
128
     *
129
     * @ORM\OneToMany(targetEntity="Registrant", mappedBy="meeting", cascade={"persist", "remove"})
130
     *
131
     */
132
    protected $registrants;
133
134
    /**
135
     * @var Recording[]|ArrayCollection
136
     * @ORM\OneToMany(targetEntity="Recording", mappedBy="meeting", cascade={"persist"}, orphanRemoval=true)
137
     */
138
    protected $recordings;
139
140
    public function __construct()
141
    {
142
        $this->registrants = new ArrayCollection();
143
        $this->recordings = new ArrayCollection();
144
        $this->activities = new ArrayCollection();
145
    }
146
147
    /**
148
     * @return string
149
     */
150
    public function __toString()
151
    {
152
        return sprintf('Meeting %d', $this->id);
153
    }
154
155
    /**
156
     * @return int
157
     */
158
    public function getId()
159
    {
160
        return $this->id;
161
    }
162
163
    /**
164
     * @return int
165
     */
166
    public function getMeetingId()
167
    {
168
        return $this->meetingId;
169
    }
170
171
    /**
172
     * @param int $meetingId
173
     *
174
     * @return Meeting
175
     */
176
    public function setMeetingId($meetingId)
177
    {
178
        $this->meetingId = $meetingId;
179
180
        return $this;
181
    }
182
183
    /**
184
     * @return User
185
     */
186
    public function getUser()
187
    {
188
        return $this->user;
189
    }
190
191
    /**
192
     * @return Course
193
     */
194
    public function getCourse()
195
    {
196
        return $this->course;
197
    }
198
199
    /**
200
     * @return Session
201
     */
202
    public function getSession()
203
    {
204
        return $this->session;
205
    }
206
207
    /**
208
     * @return Registrant[]|ArrayCollection
209
     */
210
    public function getRegistrants()
211
    {
212
        return $this->registrants;
213
    }
214
215
    /**
216
     * @return Recording[]|ArrayCollection
217
     */
218
    public function getRecordings()
219
    {
220
        return $this->recordings;
221
    }
222
223
    /**
224
     * @return MeetingActivity[]|ArrayCollection
225
     */
226
    public function getActivities()
227
    {
228
        return $this->activities;
229
    }
230
231
    public function addActivity(MeetingActivity $activity)
232
    {
233
        $activity->setMeeting($this);
234
        $this->activities[] = $activity;
235
    }
236
237
    /**
238
     * @param MeetingActivity[]|ArrayCollection $activities
239
     *
240
     * @return Meeting
241
     */
242
    public function setActivities($activities)
243
    {
244
        $this->activities = $activities;
245
246
        return $this;
247
    }
248
249
    /**
250
     * @ORM\PostLoad
251
     *
252
     * @throws Exception
253
     */
254
    public function postLoad()
255
    {
256
        if (null !== $this->meetingListItemJson) {
257
            $this->meetingListItem = MeetingListItem::fromJson($this->meetingListItemJson);
258
        }
259
        if (null !== $this->meetingInfoGetJson) {
260
            $this->meetingInfoGet = MeetingInfoGet::fromJson($this->meetingInfoGetJson);
261
        }
262
        $this->initializeDisplayableProperties();
263
    }
264
265
    /**
266
     * @ORM\PostUpdate
267
     *
268
     * @throws Exception
269
     */
270
    public function postUpdate()
271
    {
272
        $this->initializeDisplayableProperties();
273
    }
274
275
    /**
276
     * @ORM\PreFlush
277
     */
278
    public function preFlush()
279
    {
280
        if (null !== $this->meetingListItem) {
281
            $this->meetingListItemJson = json_encode($this->meetingListItem);
282
        }
283
        if (null !== $this->meetingInfoGet) {
284
            $this->meetingInfoGetJson = json_encode($this->meetingInfoGet);
285
        }
286
    }
287
288
    /**
289
     * @return MeetingListItem
290
     */
291
    public function getMeetingListItem()
292
    {
293
        return $this->meetingListItem;
294
    }
295
296
    /**
297
     * @return MeetingInfoGet
298
     */
299
    public function getMeetingInfoGet()
300
    {
301
        return $this->meetingInfoGet;
302
    }
303
304
    /**
305
     * @param User $user
306
     *
307
     * @return $this
308
     */
309
    public function setUser($user)
310
    {
311
        $this->user = $user;
312
313
        return $this;
314
    }
315
316
    /**
317
     * @param Course $course
318
     *
319
     * @return $this
320
     */
321
    public function setCourse($course)
322
    {
323
        $this->course = $course;
324
325
        return $this;
326
    }
327
328
    /**
329
     * @param Session $session
330
     *
331
     * @return $this
332
     */
333
    public function setSession($session)
334
    {
335
        $this->session = $session;
336
337
        return $this;
338
    }
339
340
    /**
341
     * @return CGroupInfo
342
     */
343
    public function getGroup()
344
    {
345
        return $this->group;
346
    }
347
348
    /**
349
     * @param CGroupInfo $group
350
     *
351
     * @return Meeting
352
     */
353
    public function setGroup($group)
354
    {
355
        $this->group = $group;
356
357
        return $this;
358
    }
359
360
    /**
361
     * @param MeetingListItem $meetingListItem
362
     *
363
     * @throws Exception
364
     *
365
     * @return Meeting
366
     */
367
    public function setMeetingListItem($meetingListItem)
368
    {
369
        if (null === $this->meetingId) {
370
            $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...
371
        } elseif ($this->meetingId != $meetingListItem->id) {
372
            throw new Exception('the Meeting identifier differs from the MeetingListItem identifier');
373
        }
374
        $this->meetingListItem = $meetingListItem;
375
376
        return $this;
377
    }
378
379
    /**
380
     * @param MeetingInfoGet $meetingInfoGet
381
     *
382
     * @throws Exception
383
     *
384
     * @return Meeting
385
     */
386
    public function setMeetingInfoGet($meetingInfoGet)
387
    {
388
        if (null === $this->meetingId) {
389
            $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...
390
        } elseif ($this->meetingId != $meetingInfoGet->id) {
391
            throw new Exception('the Meeting identifier differs from the MeetingInfoGet identifier');
392
        }
393
        $this->meetingInfoGet = $meetingInfoGet;
394
        $this->initializeDisplayableProperties();
395
396
        return $this;
397
    }
398
399
    /**
400
     * @return bool
401
     */
402
    public function isCourseMeeting()
403
    {
404
        return null !== $this->course;
405
    }
406
407
    /**
408
     * @return bool
409
     */
410
    public function isUserMeeting()
411
    {
412
        return null !== $this->user && null === $this->course;
413
    }
414
415
    /**
416
     * @return bool
417
     */
418
    public function isGlobalMeeting()
419
    {
420
        return null === $this->user && null === $this->course;
421
    }
422
423
    public function setStatus($status)
424
    {
425
        $this->meetingInfoGet->status = $status;
426
    }
427
428
    /**
429
     * Builds the list of users that can register into this meeting.
430
     * Zoom requires an email address, therefore users without an email address are excluded from the list.
431
     *
432
     * @return User[] the list of users
433
     */
434
    public function getRegistrableUsers()
435
    {
436
        $users = [];
437
        if (!$this->isCourseMeeting()) {
438
            $criteria = ['active' => true];
439
            $users = Database::getManager()->getRepository('ChamiloUserBundle:User')->findBy($criteria);
440
        } elseif (null === $this->session) {
441
            if (null !== $this->course) {
442
                /** @var CourseRelUser $courseRelUser */
443
                foreach ($this->course->getUsers() as $courseRelUser) {
444
                    $users[] = $courseRelUser->getUser();
445
                }
446
            }
447
        } else {
448
            if (null !== $this->course) {
449
                $subscriptions = $this->session->getUserCourseSubscriptionsByStatus($this->course, Session::STUDENT);
450
                if ($subscriptions) {
451
                    /** @var SessionRelCourseRelUser $sessionCourseUser */
452
                    foreach ($subscriptions as $sessionCourseUser) {
453
                        $users[] = $sessionCourseUser->getUser();
454
                    }
455
                }
456
            }
457
        }
458
459
        $activeUsersWithEmail = [];
460
        foreach ($users as $user) {
461
            if ($user->isActive() && !empty($user->getEmail())) {
462
                $activeUsersWithEmail[] = $user;
463
            }
464
        }
465
466
        return $activeUsersWithEmail;
467
    }
468
469
    /**
470
     * @return bool
471
     */
472
    public function requiresDateAndDuration()
473
    {
474
        return MeetingInfoGet::TYPE_SCHEDULED === $this->meetingInfoGet->type
475
            || MeetingInfoGet::TYPE_RECURRING_WITH_FIXED_TIME === $this->meetingInfoGet->type;
476
    }
477
478
    /**
479
     * @return bool
480
     */
481
    public function requiresRegistration()
482
    {
483
        return
484
            MeetingSettings::APPROVAL_TYPE_AUTOMATICALLY_APPROVE === $this->meetingInfoGet->settings->approval_type;
485
        /*return
486
            MeetingSettings::APPROVAL_TYPE_NO_REGISTRATION_REQUIRED != $this->meetingInfoGet->settings->approval_type;*/
487
    }
488
489
    /**
490
     * @return bool
491
     */
492
    public function hasCloudAutoRecordingEnabled()
493
    {
494
        return 'cloud' === $this->meetingInfoGet->settings->auto_recording;
495
    }
496
497
    /**
498
     * @param User $user
499
     *
500
     * @return bool
501
     */
502
    public function hasRegisteredUser($user)
503
    {
504
        return $this->getRegistrants()->exists(
505
            function (Registrant $registrantEntity) use (&$user) {
506
                return $registrantEntity->getUser() === $user;
507
            }
508
        );
509
    }
510
511
    /**
512
     * @param User $user
513
     *
514
     * @return Registrant|null
515
     */
516
    public function getRegistrant($user)
517
    {
518
        foreach ($this->getRegistrants() as $registrant) {
519
            if ($registrant->getUser() === $user) {
520
                return $registrant;
521
            }
522
        }
523
524
        return null;
525
    }
526
527
    /**
528
     * Generates a short presentation of the meeting for the future participant.
529
     * To be displayed above the "Enter meeting" link.
530
     *
531
     * @return string
532
     */
533
    public function getIntroduction()
534
    {
535
        $introduction = sprintf('<h1>%s</h1>', $this->meetingInfoGet->topic);
536
        if (!$this->isGlobalMeeting()) {
537
            $introduction .= sprintf('<p>%s (%s)</p>', $this->formattedStartTime, $this->formattedDuration);
538
        }
539
        if ($this->user) {
540
            $introduction .= sprintf('<p>%s</p>', $this->user->getFullname());
541
        } elseif ($this->isCourseMeeting()) {
542
            if (null === $this->session) {
543
                $introduction .= sprintf('<p class="main">%s</p>', $this->course);
544
            } else {
545
                $introduction .= sprintf('<p class="main">%s (%s)</p>', $this->course, $this->session);
546
            }
547
        }
548
        if (!empty($this->meetingInfoGet->agenda)) {
549
            $introduction .= sprintf('<p>%s</p>', $this->meetingInfoGet->agenda);
550
        }
551
552
        return $introduction;
553
    }
554
555
    /**
556
     * @throws Exception on unexpected start_time or duration
557
     */
558
    private function initializeDisplayableProperties()
559
    {
560
        $zoomPlugin = new \ZoomPlugin();
561
562
        $typeList = [
563
            API\Meeting::TYPE_INSTANT => $zoomPlugin->get_lang('InstantMeeting'),
564
            API\Meeting::TYPE_SCHEDULED => $zoomPlugin->get_lang('ScheduledMeeting'),
565
            API\Meeting::TYPE_RECURRING_WITH_NO_FIXED_TIME => $zoomPlugin->get_lang('RecurringWithNoFixedTime'),
566
            API\Meeting::TYPE_RECURRING_WITH_FIXED_TIME => $zoomPlugin->get_lang('RecurringWithFixedTime'),
567
        ];
568
        $this->typeName = $typeList[$this->meetingInfoGet->type];
569
570
        if (property_exists($this, 'status')) {
571
            $statusList = [
572
                'waiting' => $zoomPlugin->get_lang('Waiting'),
573
                'started' => $zoomPlugin->get_lang('Started'),
574
                'finished' => $zoomPlugin->get_lang('Finished'),
575
            ];
576
            $this->statusName = $statusList[$this->meetingInfoGet->status];
577
        }
578
        $this->startDateTime = null;
579
        $this->formattedStartTime = '';
580
        $this->durationInterval = null;
581
        $this->formattedDuration = '';
582
        if (!empty($this->meetingInfoGet->start_time)) {
583
            $this->startDateTime = new DateTime($this->meetingInfoGet->start_time);
584
            $this->startDateTime->setTimezone(new DateTimeZone(date_default_timezone_get()));
585
            $this->formattedStartTime = $this->startDateTime->format('Y-m-d H:i');
586
        }
587
588
        if (!empty($this->meetingInfoGet->duration)) {
589
            $now = new DateTime();
590
            $later = new DateTime();
591
            $later->add(new DateInterval('PT'.$this->meetingInfoGet->duration.'M'));
592
            $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...
593
            $this->formattedDuration = $this->durationInterval->format($zoomPlugin->get_lang('DurationFormat'));
594
        }
595
    }
596
}
597