Passed
Push — 1.11.x ( 371b4c...d55312 )
by Julito
10:07
created

MeetingEntity::isUserMeeting()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 1
c 1
b 0
f 0
nc 2
nop 0
dl 0
loc 3
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\PluginBundle\Zoom\API\MeetingInfoGet;
12
use Chamilo\PluginBundle\Zoom\API\MeetingListItem;
13
use Chamilo\PluginBundle\Zoom\API\MeetingSettings;
14
use Chamilo\UserBundle\Entity\User;
15
use Database;
16
use DateInterval;
17
use DateTime;
18
use DateTimeZone;
19
use Doctrine\Common\Collections\ArrayCollection;
20
use Doctrine\ORM\Mapping as ORM;
21
use Exception;
22
23
/**
24
 * Class MeetingEntity.
25
 *
26
 * @ORM\Entity(repositoryClass="Chamilo\PluginBundle\Zoom\MeetingEntityRepository")
27
 * @ORM\Table(
28
 *     name="plugin_zoom_meeting",
29
 *     indexes={
30
 *         @ORM\Index(name="user_id_index", columns={"user_id"}),
31
 *         @ORM\Index(name="course_id_index", columns={"course_id"}),
32
 *         @ORM\Index(name="session_id_index", columns={"session_id"})
33
 *     }
34
 * )
35
 * @ORM\HasLifecycleCallbacks
36
 */
37
class MeetingEntity
38
{
39
    /** @var string meeting type name */
40
    public $typeName;
41
42
    /** @var DateTime meeting start time as a DateTime instance */
43
    public $startDateTime;
44
45
    /** @var string meeting formatted start time */
46
    public $formattedStartTime;
47
48
    /** @var DateInterval meeting duration as a DateInterval instance */
49
    public $durationInterval;
50
51
    /** @var string meeting formatted duration */
52
    public $formattedDuration;
53
54
    /** @var string */
55
    public $statusName;
56
57
    /**
58
     * @var int the remote zoom meeting identifier
59
     * @ORM\Column(type="integer")
60
     * @ORM\Id
61
     * @ORM\GeneratedValue()
62
     */
63
    protected $id;
64
65
    /**
66
     * @var int the remote zoom meeting identifier
67
     * @ORM\Column(type="string")
68
     */
69
    protected $meetingId;
70
71
    /**
72
     * @var User
73
     * @ORM\ManyToOne(
74
     *     targetEntity="Chamilo\UserBundle\Entity\User",
75
     * )
76
     * @ORM\JoinColumn(name="user_id", nullable=true)
77
     */
78
    protected $user;
79
80
    /**
81
     * @var Course
82
     * @ORM\ManyToOne(
83
     *     targetEntity="Chamilo\CoreBundle\Entity\Course",
84
     * )
85
     * @ORM\JoinColumn(name="course_id", nullable=true)
86
     */
87
    protected $course;
88
89
    /**
90
     * @var Session
91
     * @ORM\ManyToOne(
92
     *     targetEntity="Chamilo\CoreBundle\Entity\Session",
93
     * )
94
     * @ORM\JoinColumn(name="session_id", nullable=true)
95
     */
96
    protected $session;
97
98
    /**
99
     * @var string
100
     * @ORM\Column(type="text", name="meeting_list_item_json", nullable=true)
101
     */
102
    protected $meetingListItemJson;
103
104
    /**
105
     * @var string
106
     * @ORM\Column(type="text", name="meeting_info_get_json", nullable=true)
107
     */
108
    protected $meetingInfoGetJson;
109
110
    /** @var MeetingListItem */
111
    protected $meetingListItem;
112
113
    /** @var MeetingInfoGet */
114
    protected $meetingInfoGet;
115
116
    /**
117
     * @var RegistrantEntity[]|ArrayCollection
118
     *
119
     * @ORM\OneToMany(
120
     *     targetEntity="RegistrantEntity",
121
     *     mappedBy="meeting",
122
     *     cascade={"persist", "remove"}
123
     * )
124
     */
125
    protected $registrants;
126
127
    /**
128
     * @var RecordingEntity[]|ArrayCollection
129
     * @ORM\OneToMany(
130
     *     targetEntity="RecordingEntity",
131
     *     mappedBy="meeting",
132
     * )
133
     */
134
    protected $recordings;
135
136
    public function __construct()
137
    {
138
        $this->registrants = new ArrayCollection();
139
        $this->recordings = new ArrayCollection();
140
    }
141
142
    /**
143
     * @return string
144
     */
145
    public function __toString()
146
    {
147
        return sprintf('Meeting %d', $this->id);
148
    }
149
150
    /**
151
     * @return int
152
     */
153
    public function getId()
154
    {
155
        return $this->id;
156
    }
157
158
    /**
159
     * @return int
160
     */
161
    public function getMeetingId()
162
    {
163
        return $this->meetingId;
164
    }
165
166
    /**
167
     * @param int $meetingId
168
     *
169
     * @return MeetingEntity
170
     */
171
    public function setMeetingId($meetingId)
172
    {
173
        $this->meetingId = $meetingId;
174
175
        return $this;
176
    }
177
178
    /**
179
     * @return User
180
     */
181
    public function getUser()
182
    {
183
        return $this->user;
184
    }
185
186
    /**
187
     * @return Course
188
     */
189
    public function getCourse()
190
    {
191
        return $this->course;
192
    }
193
194
    /**
195
     * @return Session
196
     */
197
    public function getSession()
198
    {
199
        return $this->session;
200
    }
201
202
    /**
203
     * @return RegistrantEntity[]|ArrayCollection
204
     */
205
    public function getRegistrants()
206
    {
207
        return $this->registrants;
208
    }
209
210
    /**
211
     * @return RecordingEntity[]|ArrayCollection
212
     */
213
    public function getRecordings()
214
    {
215
        return $this->recordings;
216
    }
217
218
    /**
219
     * @ORM\PostLoad
220
     *
221
     * @throws Exception
222
     */
223
    public function postLoad()
224
    {
225
        if (!is_null($this->meetingListItemJson)) {
226
            $this->meetingListItem = MeetingListItem::fromJson($this->meetingListItemJson);
227
        }
228
        if (!is_null($this->meetingInfoGetJson)) {
229
            $this->meetingInfoGet = MeetingInfoGet::fromJson($this->meetingInfoGetJson);
230
        }
231
        $this->initializeDisplayableProperties();
232
    }
233
234
    /**
235
     * @ORM\PostUpdate
236
     *
237
     * @throws Exception
238
     */
239
    public function postUpdate()
240
    {
241
        $this->initializeDisplayableProperties();
242
    }
243
244
    /**
245
     * @ORM\PreFlush
246
     */
247
    public function preFlush()
248
    {
249
        if (!is_null($this->meetingListItem)) {
250
            $this->meetingListItemJson = json_encode($this->meetingListItem);
251
        }
252
        if (!is_null($this->meetingInfoGet)) {
253
            $this->meetingInfoGetJson = json_encode($this->meetingInfoGet);
254
        }
255
    }
256
257
    /**
258
     * @return MeetingListItem
259
     */
260
    public function getMeetingListItem()
261
    {
262
        return $this->meetingListItem;
263
    }
264
265
    /**
266
     * @return MeetingInfoGet
267
     */
268
    public function getMeetingInfoGet()
269
    {
270
        return $this->meetingInfoGet;
271
    }
272
273
    /**
274
     * @param User $user
275
     *
276
     * @return $this
277
     */
278
    public function setUser($user)
279
    {
280
        $this->user = $user;
281
282
        return $this;
283
    }
284
285
    /**
286
     * @param Course $course
287
     *
288
     * @return $this
289
     */
290
    public function setCourse($course)
291
    {
292
        $this->course = $course;
293
294
        return $this;
295
    }
296
297
    /**
298
     * @param Session $session
299
     *
300
     * @return $this
301
     */
302
    public function setSession($session)
303
    {
304
        $this->session = $session;
305
306
        return $this;
307
    }
308
309
    /**
310
     * @param MeetingListItem $meetingListItem
311
     *
312
     * @throws Exception
313
     *
314
     * @return MeetingEntity
315
     */
316
    public function setMeetingListItem($meetingListItem)
317
    {
318
        if (null === $this->meetingId) {
319
            $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...
320
        } elseif ($this->meetingId != $meetingListItem->id) {
321
            throw new Exception('the MeetingEntity identifier differs from the MeetingListItem identifier');
322
        }
323
        $this->meetingListItem = $meetingListItem;
324
325
        return $this;
326
    }
327
328
    /**
329
     * @param MeetingInfoGet $meetingInfoGet
330
     *
331
     * @throws Exception
332
     *
333
     * @return MeetingEntity
334
     */
335
    public function setMeetingInfoGet($meetingInfoGet)
336
    {
337
        if (null === $this->meetingId) {
338
            $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...
339
        } elseif ($this->meetingId != $meetingInfoGet->id) {
340
            throw new Exception('the MeetingEntity identifier differs from the MeetingInfoGet identifier');
341
        }
342
        $this->meetingInfoGet = $meetingInfoGet;
343
        $this->initializeDisplayableProperties();
344
345
        return $this;
346
    }
347
348
    /**
349
     * @return bool
350
     */
351
    public function isCourseMeeting()
352
    {
353
        return null !== $this->course;
354
    }
355
356
    /**
357
     * @return bool
358
     */
359
    public function isUserMeeting()
360
    {
361
        return null !== $this->user && null === $this->course;
362
    }
363
364
    /**
365
     * @return bool
366
     */
367
    public function isGlobalMeeting()
368
    {
369
        return null === $this->user && null === $this->course;
370
    }
371
372
    public function setStatus($status)
373
    {
374
        $this->meetingInfoGet->status = $status;
375
    }
376
377
    /**
378
     * Builds the list of users that can register into this meeting.
379
     * Zoom requires an email address, therefore users without an email address are excluded from the list.
380
     *
381
     * @return User[] the list of users
382
     */
383
    public function getRegistrableUsers()
384
    {
385
        $users = [];
386
        if (!$this->isCourseMeeting()) {
387
            $criteria = ['active' => true];
388
            $users = Database::getManager()->getRepository('ChamiloUserBundle:User')->findBy($criteria);
389
        } elseif (null === $this->session) {
390
            if (null !== $this->course) {
391
                /** @var CourseRelUser $courseRelUser */
392
                foreach ($this->course->getUsers() as $courseRelUser) {
393
                    $users[] = $courseRelUser->getUser();
394
                }
395
            }
396
        } else {
397
            if (null !== $this->course) {
398
                $subscriptions = $this->session->getUserCourseSubscriptionsByStatus($this->course, Session::STUDENT);
399
                if ($subscriptions) {
400
                    /** @var SessionRelCourseRelUser $sessionCourseUser */
401
                    foreach ($subscriptions as $sessionCourseUser) {
402
                        $users[] = $sessionCourseUser->getUser();
403
                    }
404
                }
405
            }
406
        }
407
408
        $activeUsersWithEmail = [];
409
        foreach ($users as $user) {
410
            if ($user->isActive() && !empty($user->getEmail())) {
411
                $activeUsersWithEmail[] = $user;
412
            }
413
        }
414
415
        return $activeUsersWithEmail;
416
    }
417
418
    /**
419
     * @return bool
420
     */
421
    public function requiresDateAndDuration()
422
    {
423
        return MeetingInfoGet::TYPE_SCHEDULED === $this->meetingInfoGet->type
424
            || MeetingInfoGet::TYPE_RECURRING_WITH_FIXED_TIME === $this->meetingInfoGet->type;
425
    }
426
427
    /**
428
     * @return bool
429
     */
430
    public function requiresRegistration()
431
    {
432
        return
433
            MeetingSettings::APPROVAL_TYPE_AUTOMATICALLY_APPROVE === $this->meetingInfoGet->settings->approval_type;
434
        /*return
435
            MeetingSettings::APPROVAL_TYPE_NO_REGISTRATION_REQUIRED != $this->meetingInfoGet->settings->approval_type;*/
436
    }
437
438
    /**
439
     * @return bool
440
     */
441
    public function hasCloudAutoRecordingEnabled()
442
    {
443
        return 'cloud' === $this->meetingInfoGet->settings->auto_recording;
444
    }
445
446
    /**
447
     * @param User $user
448
     *
449
     * @return bool
450
     */
451
    public function hasRegisteredUser($user)
452
    {
453
        return $this->getRegistrants()->exists(
454
            function (RegistrantEntity $registrantEntity) use (&$user) {
455
                return $registrantEntity->getUser() === $user;
456
            }
457
        );
458
    }
459
460
    /**
461
     * @param User $user
462
     *
463
     * @return RegistrantEntity|null
464
     */
465
    public function getRegistrant($user)
466
    {
467
        foreach ($this->getRegistrants() as $registrant) {
468
            if ($registrant->getUser() === $user) {
469
                return $registrant;
470
            }
471
        }
472
473
        return null;
474
    }
475
476
    /**
477
     * Generates a short presentation of the meeting for the future participant.
478
     * To be displayed above the "Enter meeting" link.
479
     *
480
     * @return string
481
     */
482
    public function getIntroduction()
483
    {
484
        $introduction = sprintf('<h1>%s</h1>', $this->meetingInfoGet->topic);
485
        if (!$this->isGlobalMeeting()) {
486
            $introduction .= sprintf('<p>%s (%s)</p>', $this->formattedStartTime, $this->formattedDuration);
487
        }
488
        if ($this->user) {
489
            $introduction .= sprintf('<p>%s</p>', $this->user->getFullname());
490
        } elseif ($this->isCourseMeeting()) {
491
            if (null === $this->session) {
492
                $introduction .= sprintf('<p class="main">%s</p>', $this->course);
493
            } else {
494
                $introduction .= sprintf('<p class="main">%s (%s)</p>', $this->course, $this->session);
495
            }
496
        }
497
        if (!empty($this->meetingInfoGet->agenda)) {
498
            $introduction .= sprintf('<p>%s</p>', $this->meetingInfoGet->agenda);
499
        }
500
501
        return $introduction;
502
    }
503
504
    /**
505
     * @throws Exception on unexpected start_time or duration
506
     */
507
    private function initializeDisplayableProperties()
508
    {
509
        $zoomPlugin = new \ZoomPlugin();
510
        $this->typeName = [
511
            API\Meeting::TYPE_INSTANT => $zoomPlugin->get_lang('InstantMeeting'),
512
            API\Meeting::TYPE_SCHEDULED => $zoomPlugin->get_lang('ScheduledMeeting'),
513
            API\Meeting::TYPE_RECURRING_WITH_NO_FIXED_TIME => $zoomPlugin->get_lang('RecurringWithNoFixedTime'),
514
            API\Meeting::TYPE_RECURRING_WITH_FIXED_TIME => $zoomPlugin->get_lang('RecurringWithFixedTime'),
515
        ][$this->meetingInfoGet->type];
516
        if (property_exists($this, 'status')) {
517
            $this->statusName = [
518
                'waiting' => $zoomPlugin->get_lang('Waiting'),
519
                'started' => $zoomPlugin->get_lang('Started'),
520
                'finished' => $zoomPlugin->get_lang('Finished'),
521
            ][$this->meetingInfoGet->status];
522
        }
523
        $this->startDateTime = null;
524
        $this->formattedStartTime = '';
525
        $this->durationInterval = null;
526
        $this->formattedDuration = '';
527
        if (!empty($this->meetingInfoGet->start_time)) {
528
            $this->startDateTime = new DateTime($this->meetingInfoGet->start_time);
529
            $this->startDateTime->setTimezone(new DateTimeZone(date_default_timezone_get()));
530
            $this->formattedStartTime = $this->startDateTime->format('Y-m-d H:i');
531
        }
532
533
        if (!empty($this->meetingInfoGet->duration)) {
534
            $now = new DateTime();
535
            $later = new DateTime();
536
            $later->add(new DateInterval('PT'.$this->meetingInfoGet->duration.'M'));
537
            $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...
538
            $this->formattedDuration = $this->durationInterval->format($zoomPlugin->get_lang('DurationFormat'));
539
        }
540
    }
541
}
542