Issues (3627)

plugins/MauticCitrixBundle/Helper/CitrixHelper.php (1 issue)

1
<?php
2
3
/*
4
 * @copyright   2016 Mautic Contributors. All rights reserved
5
 * @author      Mautic
6
 *
7
 * @link        http://mautic.org
8
 *
9
 * @license     GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
10
 */
11
12
namespace MauticPlugin\MauticCitrixBundle\Helper;
13
14
use Mautic\PluginBundle\Helper\IntegrationHelper;
15
use Mautic\PluginBundle\Integration\AbstractIntegration;
16
use MauticPlugin\MauticCitrixBundle\Api\GotoassistApi;
17
use MauticPlugin\MauticCitrixBundle\Api\GotomeetingApi;
18
use MauticPlugin\MauticCitrixBundle\Api\GototrainingApi;
19
use MauticPlugin\MauticCitrixBundle\Api\GotowebinarApi;
20
use Psr\Log\LoggerInterface;
21
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
22
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
23
use Symfony\Component\Routing\RouterInterface;
24
use Symfony\Component\Security\Core\Exception\AuthenticationException;
25
26
class CitrixHelper
27
{
28
    /**
29
     * @var LoggerInterface
30
     */
31
    private static $logger;
32
33
    /**
34
     * @var IntegrationHelper
35
     */
36
    private static $integrationHelper;
37
38
    /**
39
     * @var RouterInterface
40
     */
41
    private static $router;
42
43
    public static function init(IntegrationHelper $helper, LoggerInterface $logger, RouterInterface $router)
44
    {
45
        self::$logger            = $logger;
46
        self::$integrationHelper = $helper;
47
        self::$router            = $router;
48
    }
49
50
    /**
51
     * Get the API helper.
52
     *
53
     * @return GotomeetingApi
54
     */
55
    public static function getG2mApi()
56
    {
57
        static $g2mapi;
58
        if (null === $g2mapi) {
59
            $class  = '\\MauticPlugin\\MauticCitrixBundle\\Api\\GotomeetingApi';
60
            $g2mapi = new $class(self::getIntegration('Gotomeeting'));
61
        }
62
63
        return $g2mapi;
64
    }
65
66
    /**
67
     * Get the API helper.
68
     *
69
     * @return GotowebinarApi
70
     */
71
    public static function getG2wApi()
72
    {
73
        static $g2wapi;
74
        if (null === $g2wapi) {
75
            $class  = '\\MauticPlugin\\MauticCitrixBundle\\Api\\GotowebinarApi';
76
            $g2wapi = new $class(self::getIntegration('Gotowebinar'));
77
        }
78
79
        return $g2wapi;
80
    }
81
82
    /**
83
     * Get the API helper.
84
     *
85
     * @return GototrainingApi
86
     */
87
    public static function getG2tApi()
88
    {
89
        static $g2tapi;
90
        if (null === $g2tapi) {
91
            $class  = '\\MauticPlugin\\MauticCitrixBundle\\Api\\GototrainingApi';
92
            $g2tapi = new $class(self::getIntegration('Gototraining'));
93
        }
94
95
        return $g2tapi;
96
    }
97
98
    /**
99
     * Get the API helper.
100
     *
101
     * @return GotoassistApi
102
     */
103
    public static function getG2aApi()
104
    {
105
        static $g2aapi;
106
        if (null === $g2aapi) {
107
            $class  = '\\MauticPlugin\\MauticCitrixBundle\\Api\\GotoassistApi';
108
            $g2aapi = new $class(self::getIntegration('Gotoassist'));
109
        }
110
111
        return $g2aapi;
112
    }
113
114
    /**
115
     * @param        $msg
116
     * @param string $level
117
     */
118
    public static function log($msg, $level = 'error')
119
    {
120
        try {
121
            self::$logger->log($level, $msg);
122
        } catch (\Exception $ex) {
123
            // do nothing
124
        }
125
    }
126
127
    /**
128
     * @param array $results
129
     * @param       $key
130
     * @param       $value
131
     *
132
     * @return \Generator
133
     */
134
    public static function getKeyPairs($results, $key, $value)
135
    {
136
        /** @var array $results */
137
        foreach ($results as $result) {
138
            if (array_key_exists($key, $result) && array_key_exists($value, $result)) {
139
                yield $result[$key] => $result[$value];
140
            }
141
        }
142
    }
143
144
    /**
145
     * @param array $sessions
146
     * @param bool  $showAll  Wether or not to show only active sessions
147
     *
148
     * @return \Generator
149
     */
150
    public static function getAssistPairs($sessions, $showAll = false)
151
    {
152
        /** @var array $sessions */
153
        foreach ($sessions as $session) {
154
            if ($showAll || !in_array($session['status'], ['notStarted', 'abandoned'], true)) {
155
                yield $session['sessionId'] => sprintf('%s (%s)', $session['sessionId'], $session['status']);
156
            }
157
        }
158
    }
159
160
    /**
161
     * @param      $listType    string Can be one of 'webinar', 'meeting', 'training' or 'assist'
162
     * @param bool $onlyFutures
163
     *
164
     * @return array
165
     */
166
    public static function getCitrixChoices($listType, $onlyFutures = true)
167
    {
168
        try {
169
            // Check if integration is enabled
170
            if (!self::isAuthorized(self::listToIntegration($listType))) {
171
                throw new AuthenticationException('You are not authorized to view '.$listType);
172
            }
173
            $currentYear = date('Y');
174
            // TODO: the date range can be configured elsewhere
175
            $fromTime = ($currentYear - 10).'-01-01T00:00:00Z';
176
            $toTime   = ($currentYear + 10).'-01-01T00:00:00Z';
177
            if ('webinar' === $listType) {
178
                $url    = 'upcomingWebinars';
179
                $params = [];
180
                if (!$onlyFutures) {
181
                    $url                = 'historicalWebinars';
182
                    $params['fromTime'] = $fromTime;
183
                    $params['toTime']   = $toTime;
184
                }
185
                $results = self::getG2wApi()->request($url, $params);
186
187
                return iterator_to_array(self::getKeyPairs($results, 'webinarID', 'subject'));
188
            } else {
189
                if ('meeting' === $listType) {
190
                    $url    = 'upcomingMeetings';
191
                    $params = [];
192
                    if (!$onlyFutures) {
193
                        $url                 = 'historicalMeetings';
194
                        $params['startDate'] = $fromTime;
195
                        $params['endDate']   = $toTime;
196
                    }
197
                    $results = self::getG2mApi()->request($url, $params);
198
199
                    return iterator_to_array(self::getKeyPairs($results, 'meetingId', 'subject'));
200
                } else {
201
                    if ('training' === $listType) {
202
                        $results = self::getG2tApi()->request('trainings');
203
204
                        return iterator_to_array(self::getKeyPairs($results, 'trainingKey', 'name'));
205
                    } else {
206
                        if ('assist' === $listType) {
207
                            // show sessions in the last month
208
                            // times must be in ISO format: YYYY-MM-ddTHH:mm:ssZ
209
                            $params = [
210
                                'fromTime' => preg_filter(
211
                                    '/^(.+)[\+\-].+$/',
212
                                    '$1Z',
213
                                    date('c', strtotime('-1 month', time()))
214
                                ),
215
                                'toTime'      => preg_filter('/^(.+)[\+\-].+$/', '$1Z', date('c')),
216
                                'sessionType' => 'screen_sharing',
217
                            ];
218
                            $results = self::getG2aApi()->request('sessions', $params);
219
                            if ((array) $results && array_key_exists('sessions', $results)) {
220
                                return iterator_to_array(self::getAssistPairs($results['sessions']));
221
                            }
222
                        }
223
                    }
224
                }
225
            }
226
        } catch (\Exception $ex) {
227
            self::log($ex->getMessage());
228
        }
229
230
        return [];
231
    }
232
233
    /**
234
     * @param $integration string
235
     *
236
     * @return bool
237
     */
238
    public static function isAuthorized($integration)
239
    {
240
        $myIntegration = self::getIntegration($integration);
241
242
        return $myIntegration && $myIntegration->getIntegrationSettings() && $myIntegration->getIntegrationSettings()->getIsPublished();
243
    }
244
245
    /**
246
     * @param $integration
247
     *
248
     * @return AbstractIntegration
249
     */
250
    private static function getIntegration($integration)
251
    {
252
        try {
253
            return self::$integrationHelper->getIntegrationObject($integration);
254
        } catch (\Exception $e) {
255
            // do nothing
256
        }
257
258
        return null;
259
    }
260
261
    /**
262
     * @param $listType
263
     *
264
     * @return mixed
265
     */
266
    private static function listToIntegration($listType)
267
    {
268
        if (CitrixProducts::isValidValue($listType)) {
269
            return 'Goto'.$listType;
270
        }
271
272
        return '';
273
    }
274
275
    /**
276
     * @param string $str
277
     * @param int    $limit
278
     *
279
     * @return string
280
     */
281
    public static function getCleanString($str, $limit = 20)
282
    {
283
        $str = htmlentities(strtolower($str), ENT_NOQUOTES, 'utf-8');
284
        $str = preg_replace('#&([A-za-z])(?:acute|cedil|caron|circ|grave|orn|ring|slash|th|tilde|uml);#', '\1', $str);
285
        $str = preg_replace('#&([A-za-z]{2})(?:lig);#', '\1', $str);
286
        $str = preg_replace('#&[^;]+;#', '', $str);
287
288
        $availableChars = explode(' ', '0 1 2 3 4 5 6 7 8 9 a b c d e f g h i j k l m n o p q r s t u v w x y z');
289
        $safeStr        = '';
290
        $safeChar       = '';
291
        /** @var array $chars */
292
        $chars = str_split($str);
293
        foreach ($chars as $char) {
294
            if (!in_array($char, $availableChars, true)) {
295
                if ('-' !== $safeChar) {
296
                    $safeChar = '-';
297
                } else {
298
                    continue;
299
                }
300
            } else {
301
                $safeChar = $char;
302
            }
303
            $safeStr .= $safeChar;
304
        }
305
306
        return trim(substr($safeStr, 0, $limit), '-');
307
    }
308
309
    /**
310
     * @param $product
311
     * @param $productId
312
     * @param $email
313
     * @param $firstname
314
     * @param $lastname
315
     *
316
     * @return bool
317
     *
318
     * @throws \Symfony\Component\HttpKernel\Exception\BadRequestHttpException
319
     */
320
    public static function registerToProduct($product, $productId, $email, $firstname, $lastname)
321
    {
322
        try {
323
            $response = [];
324
            if (CitrixProducts::GOTOWEBINAR === $product) {
325
                $params = [
326
                    'email'     => $email,
327
                    'firstName' => $firstname,
328
                    'lastName'  => $lastname,
329
                ];
330
331
                $response = self::getG2wApi()->request(
332
                    'webinars/'.$productId.'/registrants?resendConfirmation=true',
333
                    $params,
334
                    'POST'
335
                );
336
            } else {
337
                if (CitrixProducts::GOTOTRAINING === $product) {
338
                    $params = [
339
                        'email'     => $email,
340
                        'givenName' => $firstname,
341
                        'surname'   => $lastname,
342
                    ];
343
344
                    $response = self::getG2tApi()->request(
345
                        'trainings/'.$productId.'/registrants',
346
                        $params,
347
                        'POST'
348
                    );
349
                }
350
            }
351
352
            return is_array($response) && array_key_exists('joinUrl', $response);
353
        } catch (\Exception $ex) {
354
            self::log('registerToProduct: '.$ex->getMessage());
355
            throw new BadRequestHttpException($ex->getMessage());
356
        }
357
    }
358
359
    /**
360
     * @param $product
361
     * @param $productId
362
     * @param $email
363
     * @param $firstname
364
     * @param $lastname
365
     *
366
     * @return bool
367
     *
368
     * @throws \Symfony\Component\HttpKernel\Exception\BadRequestHttpException
369
     */
370
    public static function startToProduct($product, $productId, $email, $firstname, $lastname)
371
    {
372
        try {
373
            if (CitrixProducts::GOTOMEETING === $product) {
374
                $response = self::getG2mApi()->request(
375
                    'meetings/'.$productId.'/start'
376
                );
377
378
                return (is_array($response) && array_key_exists('hostURL', $response)) ? $response['hostURL'] : '';
379
            } else {
380
                if (CitrixProducts::GOTOTRAINING === $product) {
381
                    $response = self::getG2tApi()->request(
382
                        'trainings/'.$productId.'/start'
383
                    );
384
385
                    return (is_array($response) && array_key_exists('hostURL', $response)) ? $response['hostURL'] : '';
386
                } else {
387
                    if (CitrixProducts::GOTOASSIST === $product) {
388
                        // TODO: use the sessioncallback to update attendance status
389
                        $router = self::$router;
390
                        $params = [
391
                            'sessionStatusCallbackUrl' => $router
392
                                ->generate(
393
                                    'mautic_citrix_sessionchanged',
394
                                    [],
395
                                    UrlGeneratorInterface::ABSOLUTE_URL
396
                                ),
397
                            'sessionType'      => 'screen_sharing',
398
                            'partnerObject'    => '',
399
                            'partnerObjectUrl' => '',
400
                            'customerName'     => $firstname.' '.$lastname,
401
                            'customerEmail'    => $email,
402
                            'machineUuid'      => '',
403
                        ];
404
405
                        $response = self::getG2aApi()->request(
406
                            'sessions',
407
                            $params,
408
                            'POST'
409
                        );
410
411
                        return (is_array($response)
412
                            && array_key_exists(
413
                                'startScreenSharing',
414
                                $response
415
                            )
416
                            && array_key_exists(
417
                                'launchUrl',
418
                                $response['startScreenSharing']
419
                            )) ? $response['startScreenSharing']['launchUrl'] : '';
420
                    }
421
                }
422
            }
423
        } catch (\Exception $ex) {
424
            self::log('startProduct: '.$ex->getMessage());
425
            throw new BadRequestHttpException($ex->getMessage());
426
        }
427
428
        return '';
429
    }
430
431
    /**
432
     * @param string $product
433
     * @param string $productId
434
     *
435
     * @return string
436
     *
437
     * @throws \Mautic\PluginBundle\Exception\ApiErrorException
438
     */
439
    public static function getEventName($product, $productId)
440
    {
441
        if (CitrixProducts::GOTOWEBINAR === $product) {
442
            $result = self::getG2wApi()->request($product.'s/'.$productId);
443
444
            return $result['subject'];
445
        } else {
446
            if (CitrixProducts::GOTOMEETING === $product) {
447
                $result = self::getG2mApi()->request($product.'s/'.$productId);
448
449
                return $result[0]['subject'];
450
            } else {
451
                if (CitrixProducts::GOTOTRAINING === $product) {
452
                    $result = self::getG2tApi()->request($product.'s/'.$productId);
453
454
                    return $result['name'];
455
                }
456
            }
457
        }
458
459
        return $productId;
460
    }
461
462
    /**
463
     * @param string $product
464
     * @param string $productId
465
     *
466
     * @return array
467
     *
468
     * @throws \Mautic\PluginBundle\Exception\ApiErrorException
469
     */
470
    public static function getRegistrants($product, $productId)
471
    {
472
        $result = [];
473
        switch ($product) {
474
            case CitrixProducts::GOTOWEBINAR:
475
                $result = self::getG2wApi()->request($product.'s/'.$productId.'/registrants');
476
                break;
477
478
            case CitrixProducts::GOTOTRAINING:
479
                $result = self::getG2tApi()->request($product.'s/'.$productId.'/registrants');
480
                break;
481
        }
482
483
        return self::extractContacts($result);
484
    }
485
486
    /**
487
     * @param string $product
488
     * @param string $productId
489
     *
490
     * @return array
491
     *
492
     * @throws \Mautic\PluginBundle\Exception\ApiErrorException
493
     */
494
    public static function getAttendees($product, $productId)
495
    {
496
        $result = [];
497
        switch ($product) {
498
            case CitrixProducts::GOTOWEBINAR:
499
                $result = self::getG2wApi()->request($product.'s/'.$productId.'/attendees');
500
                break;
501
502
            case CitrixProducts::GOTOMEETING:
503
                $result = self::getG2mApi()->request($product.'s/'.$productId.'/attendees');
504
                break;
505
506
            case CitrixProducts::GOTOTRAINING:
507
                $reports  = self::getG2tApi()->request($product.'s/'.$productId, [], 'GET', 'rest/reports');
508
                $sessions = array_column($reports, 'sessionKey');
0 ignored issues
show
It seems like $reports can also be of type string; however, parameter $array of array_column() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

508
                $sessions = array_column(/** @scrutinizer ignore-type */ $reports, 'sessionKey');
Loading history...
509
                foreach ($sessions as $session) {
510
                    $result = self::getG2tApi()->request(
511
                        'sessions/'.$session.'/attendees',
512
                        [],
513
                        'GET',
514
                        'rest/reports'
515
                    );
516
                    $arr    = array_column($result, 'email');
517
                    $result = array_merge($result, $arr);
518
                }
519
520
                break;
521
        }
522
523
        return self::extractContacts($result);
524
    }
525
526
    /**
527
     * @param $results
528
     *
529
     * @return array
530
     */
531
    protected static function extractContacts($results)
532
    {
533
        $contacts = [];
534
535
        foreach ($results as $result) {
536
            $emailKey = false;
537
            if (isset($result['attendeeEmail'])) {
538
                if (empty($result['attendeeEmail'])) {
539
                    // ignore
540
                    continue;
541
                }
542
                $emailKey = strtolower($result['attendeeEmail']);
543
                $names    = explode(' ', $result['attendeeName']);
544
                switch (count($names)) {
545
                    case 1:
546
                        $firstname = $names[0];
547
                        $lastname  = '';
548
                        break;
549
                    case 2:
550
                        list($firstname, $lastname) = $names;
551
                        break;
552
                    default:
553
                        $firstname = $names[0];
554
                        unset($names[0]);
555
                        $lastname = implode(' ', $names);
556
                }
557
558
                $contacts[$emailKey] = [
559
                    'firstname' => $firstname,
560
                    'lastname'  => $lastname,
561
                    'email'     => $result['attendeeEmail'],
562
                ];
563
            } elseif (!empty($result['email'])) {
564
                $emailKey            = strtolower($result['email']);
565
                $contacts[$emailKey] = [
566
                    'firstname' => (isset($result['firstName'])) ? $result['firstName'] : '',
567
                    'lastname'  => (isset($result['lastName'])) ? $result['lastName'] : '',
568
                    'email'     => $result['email'],
569
                    'joinUrl'   => (isset($result['joinUrl'])) ? $result['joinUrl'] : '',
570
                ];
571
            }
572
573
            if ($emailKey) {
574
                $eventDate = null;
575
                // Extract join/register time
576
                if (!empty($result['attendance']['joinTime'])) {
577
                    $eventDate = $result['attendance']['joinTime'];
578
                } elseif (!empty($result['joinTime'])) {
579
                    $eventDate = $result['joinTime'];
580
                } elseif (!empty($result['inSessionTimes']['joinTime'])) {
581
                    $eventDate = $result['inSessionTimes']['joinTime'];
582
                } elseif (!empty($result['registrationDate'])) {
583
                    $eventDate = $result['registrationDate'];
584
                }
585
586
                if ($eventDate) {
587
                    $contacts[$emailKey]['event_date'] = new \DateTime($eventDate);
588
                }
589
            }
590
        }
591
592
        return $contacts;
593
    }
594
}
595