Passed
Push — 1.11.x ( bce6cd...c146d9 )
by Angel Fernando Quiroz
12:25
created

google_meet/src/google_meet_plugin.class.php (1 issue)

1
<?php
2
3
/* For licensing terms, see /license.txt */
4
5
/**
6
 * Plugin class for the Google Meet plugin.
7
 *
8
 * @author Alex Aragón Calixto <[email protected]>
9
 */
10
class GoogleMeetPlugin extends Plugin
11
{
12
    const TABLE_MEET_LIST = 'plugin_google_meet_room';
13
    const SETTING_TITLE = 'tool_title';
14
    const SETTING_ENABLED = 'google_meet_enabled';
15
    const GOOGLE_MEET_URL = 'https://meet.google.com/';
16
17
    public $isCoursePlugin = true;
18
19
    protected function __construct()
20
    {
21
        parent::__construct(
22
            '1.0',
23
            '
24
                Alex Aragón Calixto',
25
            [
26
                self::SETTING_ENABLED => 'boolean',
27
                self::SETTING_TITLE => 'text',
28
            ]
29
        );
30
31
        $this->isAdminPlugin = true;
32
    }
33
34
    /**
35
     * @return string
36
     */
37
    public function getTitle()
38
    {
39
        $title = $this->get(self::SETTING_TITLE);
40
41
        if (!empty($title)) {
42
            return $title;
43
        }
44
45
        return $this->get_title();
46
    }
47
48
    /**
49
     * {@inheritdoc}
50
     */
51
    public function get_name()
52
    {
53
        return 'google_meet';
54
    }
55
56
    /**
57
     * Create a plugin instance.
58
     *
59
     * @return GoogleMeetPlugin
60
     */
61
    public static function create()
62
    {
63
        static $result = null;
64
65
        return $result ? $result : $result = new self();
66
    }
67
68
    /**
69
     * This method creates the tables required to this plugin and copies icons
70
     * to the right places.
71
     */
72
    public function install()
73
    {
74
        $sql = "CREATE TABLE IF NOT EXISTS ".self::TABLE_MEET_LIST." (
75
            id INT unsigned NOT NULL auto_increment PRIMARY KEY,
76
            meet_name VARCHAR(250) NULL,
77
            meet_url VARCHAR(250) NULL,
78
            meet_description VARCHAR(250) NULL,
79
            meet_color VARCHAR(7) NULL,
80
            type_meet INT NOT NULL,
81
            start_time DATETIME NULL,
82
            end_time DATETIME NULL,
83
            c_id INT NULL NOT NULL,
84
            session_id INT,
85
            activate INT
86
        )";
87
88
        Database::query($sql);
89
90
        // Copy icons into the main/img/icons folder
91
        $iconName = 'google_meet';
92
        $iconsList = [
93
            '64/'.$iconName.'.png',
94
            '64/'.$iconName.'_na.png',
95
            '32/'.$iconName.'.png',
96
            '32/'.$iconName.'_na.png',
97
            '22/'.$iconName.'.png',
98
            '22/'.$iconName.'_na.png',
99
        ];
100
        $sourceDir = api_get_path(SYS_PLUGIN_PATH).'google_meet/resources/img/';
101
        $destinationDir = api_get_path(SYS_CODE_PATH).'img/icons/';
102
        foreach ($iconsList as $icon) {
103
            $src = $sourceDir.$icon;
104
            $dest = $destinationDir.$icon;
105
            copy($src, $dest);
106
        }
107
    }
108
109
    /**
110
     * This method drops the plugin tables and icons.
111
     */
112
    public function uninstall()
113
    {
114
        $this->deleteCourseToolLinks();
115
116
        $tablesToBeDeleted = [
117
            self::TABLE_MEET_LIST,
118
        ];
119
120
        foreach ($tablesToBeDeleted as $tableToBeDeleted) {
121
            $table = Database::get_main_table($tableToBeDeleted);
122
            $sql = "DROP TABLE IF EXISTS $table";
123
            Database::query($sql);
124
        }
125
        $dest1 = api_get_path(SYS_CODE_PATH).'img/icons/64/google_meet.png';
126
        $dest2 = api_get_path(SYS_CODE_PATH).'img/icons/64/google_meet_na.png';
127
        if (file_exists($dest1)) {
128
            @unlink($dest1);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for unlink(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

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

128
            /** @scrutinizer ignore-unhandled */ @unlink($dest1);

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
129
        }
130
        if (file_exists($dest2)) {
131
            @unlink($dest2);
132
        }
133
134
        $this->manageTab(false);
135
136
        // Remove icons from the main/img/icons folder
137
        $iconName = 'google_meet';
138
        $iconsList = [
139
            '64/'.$iconName.'.png',
140
            '64/'.$iconName.'_na.png',
141
            '32/'.$iconName.'.png',
142
            '32/'.$iconName.'_na.png',
143
            '22/'.$iconName.'.png',
144
            '22/'.$iconName.'_na.png',
145
        ];
146
        $destinationDir = api_get_path(SYS_CODE_PATH).'img/icons/';
147
        foreach ($iconsList as $icon) {
148
            $dest = $destinationDir.$icon;
149
            if (is_file($dest)) {
150
                @unlink($dest);
151
            }
152
        }
153
    }
154
155
    /**
156
     * {@inheritdoc}
157
     *
158
     * @return GoogleMeetPlugin
159
     */
160
    public function performActionsAfterConfigure()
161
    {
162
        $em = Database::getManager();
163
164
        $this->deleteCourseToolLinks();
165
166
        if ('true' === $this->get(self::SETTING_ENABLED)) {
167
            $courses = $em->createQuery('SELECT c.id FROM ChamiloCoreBundle:Course c')->getResult();
168
169
            foreach ($courses as $course) {
170
                $this->createLinkToCourseTool($this->getTitle(), $course['id']);
171
            }
172
        }
173
174
        return $this;
175
    }
176
177
    public function saveMeet($values)
178
    {
179
        if (!is_array($values) || empty($values['meet_name'])) {
180
            return false;
181
        }
182
        $table = Database::get_main_table(self::TABLE_MEET_LIST);
183
184
        $courseId = api_get_course_int_id();
185
        $sessionId = api_get_session_id();
186
        $url = self::filterUrl($values['meet_url']);
187
        if (!isset($values['type_meet'])) {
188
            $values['type_meet'] = 1;
189
        }
190
191
        $params = [
192
            'meet_name' => $values['meet_name'],
193
            'meet_url' => $url,
194
            'type_meet' => $values['type_meet'],
195
            'meet_description' => $values['meet_description'],
196
            'meet_color' => $values['meet_color'],
197
            'c_id' => $courseId,
198
            'start_time' => null,
199
            'end_time' => null,
200
            'session_id' => $sessionId,
201
            'activate' => 1,
202
        ];
203
204
        $id = Database::insert($table, $params);
205
206
        if ($id > 0) {
207
            return $id;
208
        }
209
    }
210
211
    public function listMeets($courseId, $sessionId = 0)
212
    {
213
        $list = [];
214
        $tableMeetList = Database::get_main_table(self::TABLE_MEET_LIST);
215
        $courseId = (int) $courseId;
216
        $sessionId = (int) $sessionId;
217
218
        $sql = "SELECT * FROM $tableMeetList WHERE c_id = $courseId AND session_id = $sessionId AND activate = 1";
219
220
        $result = Database::query($sql);
221
222
        if (Database::num_rows($result) > 0) {
223
            while ($row = Database::fetch_array($result)) {
224
                $action = Display::url(
225
                    Display::return_icon(
226
                        'delete.png',
227
                        get_lang('Delete'),
228
                        [],
229
                        ICON_SIZE_SMALL
230
                    ),
231
                    'meets.php?action=delete&id_room='.$row['id'],
232
                    [
233
                        'onclick' => 'javascript:if(!confirm('."'".
234
                            addslashes(api_htmlentities(get_lang("ConfirmYourChoice")))
235
                            ."'".')) return false;',
236
                    ]
237
                );
238
                $active = Display::return_icon('accept.png', null, [], ICON_SIZE_TINY);
239
                if (intval($row['activate']) != 1) {
240
                    $active = Display::return_icon('error.png', null, [], ICON_SIZE_TINY);
241
                }
242
243
                $list[] = [
244
                    'id' => $row['id'],
245
                    'meet_name' => $row['meet_name'],
246
                    'meet_url' => $row['meet_url'],
247
                    'meet_description' => $row['meet_description'],
248
                    'meet_color' => $row['meet_color'],
249
                    'type_meet' => $row['type_meet'],
250
                    'c_id' => $row['c_id'],
251
                    'start_time' => $row['start_time'],
252
                    'end_time' => $row['end_time'],
253
                    'session_id' => $row['session_id'],
254
                    'activate' => $active,
255
                    'actions' => $action,
256
                ];
257
            }
258
        }
259
260
        return $list;
261
    }
262
263
    public function getMeet($idMeet)
264
    {
265
        if (empty($idMeet)) {
266
            return false;
267
        }
268
        $meet = [];
269
        $tableMeetList = Database::get_main_table(self::TABLE_MEET_LIST);
270
        $idMeet = (int) $idMeet;
271
        $sql = "SELECT * FROM $tableMeetList WHERE id = $idMeet";
272
273
        $result = Database::query($sql);
274
        if (Database::num_rows($result) > 0) {
275
            while ($row = Database::fetch_array($result)) {
276
                $meet = [
277
                    'id' => $row['id'],
278
                    'meet_name' => $row['meet_name'],
279
                    'meet_url' => $row['meet_url'],
280
                    'meet_description' => $row['meet_description'],
281
                    'meet_color' => $row['meet_color'],
282
                    'type_meet' => $row['type_meet'],
283
                    'c_id' => $row['c_id'],
284
                    'start_time' => $row['start_time'],
285
                    'end_time' => $row['end_time'],
286
                    'session_id' => $row['session_id'],
287
                    'activate' => $row['activate'],
288
                ];
289
            }
290
        }
291
292
        return $meet;
293
    }
294
295
    public function updateMeet($values)
296
    {
297
        if (!is_array($values) || empty($values['meet_name'])) {
298
            return false;
299
        }
300
        $table = Database::get_main_table(self::TABLE_MEET_LIST);
301
302
        $courseId = api_get_course_int_id();
303
        $sessionId = api_get_session_id();
304
        $url = self::filterUrl($values['meet_url']);
305
        if (!isset($values['type_meet'])) {
306
            $values['type_meet'] = 1;
307
        }
308
309
        $params = [
310
            'meet_name' => $values['meet_name'],
311
            'meet_url' => $url,
312
            'type_meet' => $values['type_meet'],
313
            'meet_description' => $values['meet_description'],
314
            'meet_color' => $values['meet_color'],
315
            'c_id' => $courseId,
316
            'start_time' => null,
317
            'end_time' => null,
318
            'session_id' => $sessionId,
319
            'activate' => 1,
320
        ];
321
322
        Database::update(
323
            $table,
324
            $params,
325
            [
326
                'id = ?' => [
327
                    $values['id'],
328
                ],
329
            ]
330
        );
331
332
        return true;
333
    }
334
335
    /**
336
     * Delete a given meeting.
337
     *
338
     * @param int $idMeet Chamilo's internal ID of the meeting
339
     *
340
     * @return bool True on success, false on failure
341
     */
342
    public function deleteMeet($idMeet)
343
    {
344
        if (empty($idMeet)) {
345
            return false;
346
        }
347
        $idMeet = (int) $idMeet;
348
        $tableMeetList = Database::get_main_table(self::TABLE_MEET_LIST);
349
        $sql = "DELETE FROM $tableMeetList WHERE id = $idMeet";
350
        $result = Database::query($sql);
351
352
        if (Database::affected_rows($result) != 1) {
353
            return false;
354
        }
355
356
        return true;
357
    }
358
359
    /**
360
     * Delete links to the tool from the c_tool table.
361
     */
362
    private function deleteCourseToolLinks()
363
    {
364
        Database::getManager()
365
            ->createQuery('DELETE FROM ChamiloCourseBundle:CTool t WHERE t.category = :category AND t.link LIKE :link')
366
            ->execute(['category' => 'plugin', 'link' => 'google_meet/start.php%']);
367
    }
368
369
    /**
370
     * Do a bit of prevention on the meeting URL format.
371
     *
372
     * @param string $url The URL received from the user
373
     *
374
     * @return string Reformatted URL
375
     */
376
    private function filterUrl($url)
377
    {
378
        if (!empty($url)) {
379
            if (preg_match('#^'.self::GOOGLE_MEET_URL.'#', $url)) {
380
                // The URL starts with the right Google Meet protocol and domain, do nothing
381
            } elseif (preg_match('#^'.substr(self::GOOGLE_MEET_URL, 8).'#', $url)) {
382
                // The URL starts with meet.google.com without the protocol. Add it
383
                $url = 'https://'.$url;
384
            } else {
385
                // We assume it's just the meeting code. Add the full Google Meet prefix
386
                if (substr($url, 0, 1) === '/') {
387
                    // Remove prefixing slash, if any
388
                    $url = substr($url, 1);
389
                }
390
                $url = self::GOOGLE_MEET_URL.$url;
391
            }
392
        }
393
394
        return $url;
395
    }
396
}
397