Proyectos de Subversion LeadersLinked - Services

Rev

Rev 618 | Rev 633 | Ir a la última revisión | | Comparar con el anterior | Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
119 efrain 1
<?php
2
declare(strict_types=1);
3
 
4
namespace LeadersLinked\Controller;
5
 
6
use Laminas\Mvc\Controller\AbstractActionController;
7
use Laminas\View\Model\JsonModel;
8
use LeadersLinked\Library\Functions;
283 www 9
use LeadersLinked\Mapper\MicrolearningCapsuleMapper;
119 efrain 10
use LeadersLinked\Mapper\QueryMapper;
11
use LeadersLinked\Mapper\UserMapper;
12
use Laminas\Db\Sql\Select;
283 www 13
use LeadersLinked\Mapper\MicrolearningCapsuleCommentMapper;
119 efrain 14
use LeadersLinked\Form\Service\CapsuleCommentForm;
283 www 15
use LeadersLinked\Model\MicrolearningCapsuleComment;
16
use LeadersLinked\Model\MicrolearningAnswer;
17
use LeadersLinked\Mapper\MicrolearningUserProgressMapper;
18
use LeadersLinked\Mapper\MicrolearningSlideMapper;
19
use LeadersLinked\Mapper\MicrolearningUserLogMapper;
20
use LeadersLinked\Model\MicrolearningUserLog;
21
use LeadersLinked\Mapper\MicrolearningTopicMapper;
119 efrain 22
use LeadersLinked\Mapper\CompanyMapper;
283 www 23
use LeadersLinked\Model\MicrolearningUserProgress;
24
use LeadersLinked\Mapper\MicrolearningExtendUserMapper;
25
use LeadersLinked\Mapper\MicrolearningExtendUserCompanyMapper;
26
use LeadersLinked\Mapper\MicrolearningExtendUserFunctionMapper;
27
use LeadersLinked\Mapper\MicrolearningExtendUserGroupMapper;
28
use LeadersLinked\Mapper\MicrolearningExtendUserInstitutionMapper;
29
use LeadersLinked\Mapper\MicrolearningExtendUserPartnerMapper;
30
use LeadersLinked\Mapper\MicrolearningExtendUserProgramMapper;
31
use LeadersLinked\Mapper\MicrolearningExtendUserStudentTypeMapper;
32
use LeadersLinked\Mapper\MicrolearningExtendUserSectorMapper;
33
use LeadersLinked\Mapper\MicrolearningQuizMapper;
34
use LeadersLinked\Mapper\MicrolearningQuestionMapper;
35
use LeadersLinked\Mapper\MicrolearningAnswerMapper;
36
use LeadersLinked\Model\MicrolearningSlide;
37
use LeadersLinked\Library\Storage;
302 www 38
use LeadersLinked\Mapper\MicrolearningTopicCapsuleMapper;
119 efrain 39
 
40
 
41
class MicrolearningUserAccessGrantedIds
42
{
43
    public $companies;
44
    public $topics;
45
    public $capsules;
46
 
47
 
48
    public function __construct()
49
    {
50
        $this->companies    = [];
51
        $this->topics       = [];
52
        $this->capsules     = [];
53
    }
54
}
55
 
56
class MicrolearningController extends AbstractActionController
57
{
58
 
59
    /**
60
     *
61
     * @var \Laminas\Db\Adapter\AdapterInterface
62
     */
63
    private $adapter;
64
 
65
    /**
66
     *
67
     * @var \LeadersLinked\Cache\CacheInterface
68
     */
69
    private $cache;
70
 
71
 
72
    /**
73
     *
74
     * @var \Laminas\Log\LoggerInterface
75
     */
76
    private $logger;
77
 
78
    /**
79
     *
80
     * @var array
81
     */
82
    private $config;
83
 
84
 
85
    /**
86
     *
87
     * @var \Laminas\Mvc\I18n\Translator
88
     */
89
    private $translator;
90
 
91
 
92
    /**
93
     *
94
     * @param \Laminas\Db\Adapter\AdapterInterface $adapter
95
     * @param \LeadersLinked\Cache\CacheInterface $cache
96
     * @param \Laminas\Log\LoggerInterface LoggerInterface $logger
97
     * @param array $config
98
     * @param \Laminas\Mvc\I18n\Translator $translator
99
     */
100
    public function __construct($adapter, $cache, $logger, $config, $translator)
101
    {
102
        $this->adapter      = $adapter;
103
        $this->cache        = $cache;
104
        $this->logger       = $logger;
105
        $this->config       = $config;
106
        $this->translator   = $translator;
107
    }
108
 
109
    public function indexAction()
110
    {
111
        $request = $this->getRequest();
112
 
113
        if($request->isGet()) {
114
            return new JsonModel([
115
                'success' => true,
116
                'data' =>  [
117
                    'link_companies' => $this->url()->fromRoute('microlearning/companies',[], ['force_canonical' => true]),
118
                    'link_timeline' => $this->url()->fromRoute('microlearning/timeline',[], ['force_canonical' => true]),
119
                    'link_last_capsule_in_progress' => $this->url()->fromRoute('microlearning/last-capsule-in-progress',[], ['force_canonical' => true]),
120
                    'link_profile' => $this->url()->fromRoute('microlearning/profile',[], ['force_canonical' => true]),
121
                    'link_topics' => $this->url()->fromRoute('microlearning/topics',[], ['force_canonical' => true]),
122
                    'link_capsules_pending' => $this->url()->fromRoute('microlearning/capsules-pending',[], ['force_canonical' => true]),
123
                    'link_capsules_completed' => $this->url()->fromRoute('microlearning/capsules-completed',[], ['force_canonical' => true]),
124
                    'link_capsules_in_progress' => $this->url()->fromRoute('microlearning/capsules-in-progress',[], ['force_canonical' => true]),
125
                ]
126
            ]);
127
        }
128
 
129
        return new JsonModel([
130
            'success' => false,
131
            'data' => 'ERROR_METHOD_NOT_ALLOWED'
132
        ]);
133
    }
590 stevensc 134
 
119 efrain 135
    public function companiesAction()
136
    {
137
 
138
        $request = $this->getRequest();
139
 
140
        if($request->isGet()) {
141
            $currentNetworkPlugin = $this->plugin('currentNetworkPlugin');
142
            $currentNetwork = $currentNetworkPlugin->getNetwork();
143
 
144
 
145
            $accessGrantedIds = $this->getAccessGranted();
146
            $companyMapper = CompanyMapper::getInstance($this->adapter);
147
            $records = $companyMapper->fetchAllByIdsAndNetworkId($accessGrantedIds->companies, $currentNetwork->id);
148
 
333 www 149
            $storage = Storage::getInstance($this->config, $this->adapter);
119 efrain 150
 
151
            $companies = [];
152
            foreach($records as $record)
153
            {
154
                array_push($companies, [
164 efrain 155
                    'uuid' => $record->uuid,
119 efrain 156
                    'name' => $record->name,
283 www 157
                    'image' => $storage->getCompanyImage($record),
119 efrain 158
                    'link_progress' => $this->url()->fromRoute('microlearning/progress',['id' => $record->uuid], ['force_canonical' => true]),
159
                ]);
160
            }
161
 
162
            return new JsonModel([
163
                'success' => true,
164
                'data' =>  $companies
165
            ]);
166
 
167
 
168
        }
169
        return new JsonModel([
170
            'success' => false,
171
            'data' => 'ERROR_METHOD_NOT_ALLOWED'
172
        ]);
173
    }
590 stevensc 174
 
119 efrain 175
    public function capsuleCommentsAction()
176
    {
177
 
178
        $request = $this->getRequest();
179
 
180
        if($request->isGet()) {
181
            $serviceDatetimeFormat = $this->config['leaderslinked.services.datetime'];
182
 
183
            $currentUserPlugin = $this->plugin('currentUserPlugin');
184
            $currentUser = $currentUserPlugin->getUser();
185
 
186
            $capsule_id = $this->params()->fromRoute('capsule_id');
187
 
283 www 188
            $capsuleMapper = MicrolearningCapsuleMapper::getInstance($this->adapter);
119 efrain 189
            $capsule = $capsuleMapper->fetchOneByUuid($capsule_id);
190
 
191
            if(!$capsule) {
192
                return new JsonModel([
193
                    'success' => false,
194
                    'data' => 'ERROR_CAPSULE_NOT_FOUND'
195
 
196
                ]);
197
            }
198
 
199
            $userMapper = UserMapper::getInstance($this->adapter);
200
            $users = [];
201
 
333 www 202
            $storage = Storage::getInstance($this->config, $this->adapter);
283 www 203
 
204
            $capsuleCommentMapper = MicrolearningCapsuleCommentMapper::getInstance($this->adapter);
119 efrain 205
            $records = $capsuleCommentMapper->fetchAllByCapsuleId($capsule->id);
206
 
207
            $comments = [];
208
            foreach($records as $record)
209
            {
210
 
211
                if(isset($users[$record->user_id])) {
212
 
213
                    $user = $users[$record->user_id];
214
 
215
                } else {
216
 
217
                    $user = $userMapper->fetchOne($record->user_id);
218
                    if(!$user) {
219
                        continue;
220
                    }
221
 
222
                    $users[$record->user_id] = $user;
223
 
224
 
225
                }
226
 
227
 
228
                $dt = \DateTime::createFromFormat('Y-m-d H:i:s', $record->added_on);
229
 
230
                array_push($comments, [
231
                    'date' => $dt->format($serviceDatetimeFormat),
283 www 232
                    'image' => $storage->getUserImage($user),
119 efrain 233
                    'fullname' => trim(trim($user->first_name) . ' ' . trim($user->last_name)),
234
                    'rating' => strval($record->rating),
235
                    'comment' => $record->comment,
236
                    'link_delete' => $record->user_id == $currentUser->id ? $this->url()->fromRoute('microlearning/capsules-comments/delete', ['capsule_id' => $capsule->uuid, 'comment_id' => $record->uuid], ['force_canonical' => true]) : '',
237
                ]);
238
            }
239
 
302 www 240
            $dataCountAndRatingAverage = $capsuleCommentMapper->fetchCountAndRatingAverage($capsule->company_id, $capsule->id);
119 efrain 241
 
242
            return new JsonModel([
243
                'success' => true,
244
                'data' => [
245
                    'comments' => $comments,
246
                    'capsule' => [
247
                        'total_comments' => strval($dataCountAndRatingAverage['total_comments']),
248
                        'total_rating' => strval($dataCountAndRatingAverage['total_rating'])
249
                    ]
250
                ]
251
 
252
            ]);
253
 
254
        }
255
 
256
        return new JsonModel([
257
            'success' => false,
258
            'data' => 'ERROR_METHOD_NOT_ALLOWED'
259
        ]);
260
    }
261
 
262
 
263
 
264
    public function capsuleDeleteMyCommentAction()
265
    {
266
 
267
        $request = $this->getRequest();
268
 
269
        if($request->isPost()) {
270
 
271
            $currentUserPlugin = $this->plugin('currentUserPlugin');
272
            $currentUser = $currentUserPlugin->getUser();
273
 
274
            $capsule_id = $this->params()->fromRoute('capsule_id');
275
            $comment_id = $this->params()->fromRoute('comment_id');
276
 
283 www 277
            $capsuleMapper = MicrolearningCapsuleMapper::getInstance($this->adapter);
119 efrain 278
            $capsule = $capsuleMapper->fetchOneByUuid($capsule_id);
279
 
280
            if(!$capsule) {
281
                return new JsonModel([
282
                    'success' => false,
283
                    'data' => 'ERROR_CAPSULE_NOT_FOUND'
284
 
626 stevensc 285
                ]);
119 efrain 286
            }
287
 
283 www 288
            $capsuleCommentMapper = MicrolearningCapsuleCommentMapper::getInstance($this->adapter);
119 efrain 289
            $capsuleComment = $capsuleCommentMapper->fetchOneByUuid($comment_id);
290
 
291
            if(!$capsuleComment) {
292
                return new JsonModel([
293
                    'success' => false,
294
                    'data' => 'ERROR_CAPSULE_COMMENT_NOT_FOUND',
295
                ]);
296
            }
297
 
298
            if($capsuleComment->capsule_id != $capsule->id || $capsuleComment->user_id != $currentUser->id) {
299
                return new JsonModel([
300
                    'success' => false,
301
                    'data' => 'ERROR_YOU_DO_NOT_HAVE_ACCESS_TO_THIS_CAPSULE_COMMENT',
302
                ]);
303
            }
304
 
305
 
306
            $result = $capsuleCommentMapper->delete($capsuleComment->id);
307
            if($result) {
302 www 308
                $dataCountAndRatingAverage = $capsuleCommentMapper->fetchCountAndRatingAverage($capsule->company_id, $capsule->id);
626 stevensc 309
 
119 efrain 310
                return new JsonModel([
311
                    'success' => true,
312
                    'data' => [
313
                        'message' => 'LABEL_CAPSULE_COMMENT_HAVE_BEEN_SUCCESSFULLY_DELETE',
314
                        'capsule' => [
315
                            'total_comments' => strval($dataCountAndRatingAverage['total_comments']),
316
                            'total_rating' => strval($dataCountAndRatingAverage['total_rating'])
317
                        ]
318
                    ],
319
 
320
                ]);
321
            } else {
322
                return new JsonModel([
323
                    'success' => false,
324
                    'data' => $capsuleCommentMapper->getError()
325
 
326
                ]);
327
            }
328
        }
329
 
330
        return new JsonModel([
331
            'success' => false,
332
            'data' => 'ERROR_METHOD_NOT_ALLOWED'
333
        ]);
334
    }
335
 
336
    public function capsuleAddMyCommentAction()
337
    {
338
 
339
        $request = $this->getRequest();
340
 
341
        if($request->isPost()) {
342
 
343
            $currentUserPlugin = $this->plugin('currentUserPlugin');
344
            $currentUser = $currentUserPlugin->getUser();
345
 
346
            $capsule_id = $this->params()->fromRoute('capsule_id');
347
 
348
 
283 www 349
            $capsuleMapper = MicrolearningCapsuleMapper::getInstance($this->adapter);
119 efrain 350
            $capsule = $capsuleMapper->fetchOneByUuid($capsule_id);
351
 
352
            if(!$capsule) {
353
                return new JsonModel([
354
                    'success' => false,
355
                    'data' => 'ERROR_CAPSULE_NOT_FOUND'
356
 
357
                ]);
358
 
359
            }
360
 
361
            $form = new  CapsuleCommentForm();
362
            $dataPost = $request->getPost()->toArray();
363
            $dataPost['added_on'] = $capsuleMapper->getDatebaseNow();
364
 
365
            $form->setData($dataPost);
366
 
367
            if($form->isValid()) {
368
                $dataPost = (array) $form->getData();
369
 
370
 
283 www 371
                $capsuleComment = new MicrolearningCapsuleComment();
119 efrain 372
                $capsuleComment->company_id = $capsule->company_id;
373
                $capsuleComment->capsule_id = $capsule->id;
374
                $capsuleComment->user_id = $currentUser->id;
375
                $capsuleComment->comment = $dataPost['comment'];
376
                $capsuleComment->rating = strval($dataPost['rating']);
377
                $capsuleComment->added_on =  $dataPost['added_on'];
378
 
379
 
283 www 380
                $capsuleCommentMapper = MicrolearningCapsuleCommentMapper::getInstance($this->adapter);
119 efrain 381
                $result = $capsuleCommentMapper->insert($capsuleComment);
382
                if($result) {
383
 
384
                    $capsuleComment = $capsuleCommentMapper->fetchOne($capsuleComment->id);
385
 
302 www 386
                    $dataCountAndRatingAverage = $capsuleCommentMapper->fetchCountAndRatingAverage($capsule->company_id,  $capsule->id);
119 efrain 387
 
388
 
389
 
390
                    return new JsonModel([
391
                        'success' => true,
392
                        'data' => [
393
                            'message' =>'LABEL_CAPSULE_COMMENT_HAVE_BEEN_SUCCESSFULLY_ADDED',
394
 
395
                            'comment' => [
396
                                'comment' => $capsuleComment->comment,
397
                                'rating' => $capsuleComment->rating,
398
                                'link_delete' => $this->url()->fromRoute('microlearning/capsules-comments/delete', ['capsule_id' => $capsule->uuid, 'comment_id' => $capsuleComment->uuid], ['force_canonical' => true])
399
                            ],
400
                            'capsule' => [
401
                                'total_comments' => strval($dataCountAndRatingAverage['total_comments']),
402
                                'total_rating' => strval($dataCountAndRatingAverage['total_rating'])
403
                            ]
404
                        ]
405
 
406
                    ]);
407
                } else {
408
                    return new JsonModel([
409
                        'success' => false,
410
                        'data' => $capsuleCommentMapper->getError()
411
 
412
                    ]);
413
                }
414
 
415
 
416
            } else {
417
                $messages = [];
418
                $form_messages = (array) $form->getMessages();
419
                foreach($form_messages  as $fieldname => $field_messages)
420
                {
421
 
422
                    $messages[$fieldname] = array_values($field_messages);
423
                }
424
 
425
                return new JsonModel([
426
                    'success'   => false,
427
                    'data'   => $messages
428
                ]);
429
            }
430
 
431
 
432
 
433
 
434
        }
435
 
436
        return new JsonModel([
437
            'success' => false,
438
            'data' => 'ERROR_METHOD_NOT_ALLOWED'
439
        ]);
440
    }
441
 
442
    public function lastCapsuleInProgressAction()
443
    {
444
        $request = $this->getRequest();
445
 
446
        if($request->isGet())
447
        {
448
            $currentUserPlugin = $this->plugin('currentUserPlugin');
449
            $currentUser = $currentUserPlugin->getUser();
450
 
451
            $accessGrantedIds = $this->getAccessGranted();
452
 
453
 
283 www 454
            $userProgressMapper = MicrolearningUserProgressMapper::getInstance($this->adapter);
119 efrain 455
            $userProgress = $userProgressMapper->fetchOneLastCapsuleInProgressByUserIdAndCapsuleIds($currentUser->id, $accessGrantedIds->capsules);
283 www 456
            $topicMapper = MicrolearningTopicMapper::getInstance($this->adapter);
119 efrain 457
 
458
            if($userProgress) {
333 www 459
                $storage = Storage::getInstance($this->config, $this->adapter);
283 www 460
                $path = $storage->getPathMicrolearningCapsule();
461
 
462
                $capsuleMapper = MicrolearningCapsuleMapper::getInstance($this->adapter);
119 efrain 463
                $capsule = $capsuleMapper->fetchOne($userProgress->capsule_id);
464
 
301 www 465
                $topic = $topicMapper->fetchOne($userProgress->topic_id);
466
 
283 www 467
                $capsuleCommentMapper = MicrolearningCapsuleCommentMapper::getInstance($this->adapter);
302 www 468
                $dataCountAndRatingAverage = $capsuleCommentMapper->fetchCountAndRatingAverage($capsule->company_id,  $capsule->id);
576 stevensc 469
                $image = $storage->getGenericImage($path, $topic->uuid, $capsule->image);
470
 
119 efrain 471
                $response = [
472
                    'success' => true,
473
                    'data' => [
164 efrain 474
                        'uuid'              => $capsule->uuid,
119 efrain 475
                        'name'              => $capsule->name ? $capsule->name : '',
476
                        'description'       => $capsule->description ? $capsule->description : '',
575 stevensc 477
                        'image'             => ($capsule->image && $topic) ? $storage->getGenericImage($path,  $topic->uuid, $capsule->image )  : '',
119 efrain 478
                        'total_comments'    => strval($dataCountAndRatingAverage['total_comments']),
479
                        'total_rating'      => strval($dataCountAndRatingAverage['total_rating']),
480
                        'completed'         => $userProgress->completed,
145 efrain 481
                        'progress'          => $userProgress->progress,
119 efrain 482
                        'added_on'          => $userProgress->added_on,
483
                        'updated_on'        => $userProgress->updated_on
484
                    ]
485
                ];
486
 
487
 
488
            } else {
489
                $response = [
490
                    'success' => true,
575 stevensc 491
                    'data' => []
119 efrain 492
                ];
493
            }
494
 
495
 
496
        } else {
497
 
498
            $response = [
499
                'success' => false,
500
                'data' => 'ERROR_METHOD_NOT_ALLOWED'
501
            ];
502
 
503
 
504
        }
505
 
506
        return new JsonModel($response);
507
    }
508
 
509
    public function capsulesPendingAction()
510
    {
511
        $request = $this->getRequest();
512
        if($request->isGet()) {
513
            $currentUserPlugin = $this->plugin('currentUserPlugin');
514
            $currentUser = $currentUserPlugin->getUser();
515
 
516
            $name = Functions::sanitizeFilterString($this->params()->fromQuery('name'));
245 efrain 517
            $order_field = Functions::sanitizeFilterString($this->params()->fromQuery('order_field'));
518
            $order_direction = Functions::sanitizeFilterString($this->params()->fromQuery('order_direction'));
119 efrain 519
 
245 efrain 520
            if(!in_array($order_field,['name', 'added_on'] )) {
521
                $order_field = 'name';
522
            }
119 efrain 523
 
245 efrain 524
            if(!in_array( $order_direction,['asc', 'desc'])) {
558 stevensc 525
                $order_direction = 'asc'; // Corregido: asignar a $order_direction
245 efrain 526
            }
527
 
283 www 528
            $userProgressMapper = MicrolearningUserProgressMapper::getInstance($this->adapter);
529
            $capsuleMapper = MicrolearningCapsuleMapper::getInstance($this->adapter);
558 stevensc 530
            $topicCapsuleMapper = MicrolearningTopicCapsuleMapper::getInstance($this->adapter); // Añadido
283 www 531
            $topicMapper = MicrolearningTopicMapper::getInstance($this->adapter);
558 stevensc 532
            $capsuleCommentMapper = MicrolearningCapsuleCommentMapper::getInstance($this->adapter); // Reordenado
119 efrain 533
 
534
            $accessGranted = $this->getAccessGranted();
558 stevensc 535
 
536
            // $topics = []; // Ya no es necesario cachear tópicos aquí
537
            $capsulesData = []; // Renombrado
119 efrain 538
 
333 www 539
            $storage = Storage::getInstance($this->config, $this->adapter);
283 www 540
            $path = $storage->getPathMicrolearningCapsule();
541
 
119 efrain 542
            foreach($accessGranted->capsules as $capsule_id)
543
            {
558 stevensc 544
                // 1. Verificar progreso (debe ser nulo para pendiente)
119 efrain 545
                $userProgress = $userProgressMapper->fetchOneByUseridAndCapsuleId($currentUser->id, $capsule_id);
546
                if($userProgress) {
547
                    continue;
548
                }
558 stevensc 549
 
550
                // 2. Obtener detalles de la cápsula
119 efrain 551
                $capsule = $capsuleMapper->fetchOne($capsule_id);
558 stevensc 552
                if(!$capsule) { // Añadir verificación por si la cápsula no existe
553
                    continue;
554
                }
119 efrain 555
 
558 stevensc 556
                // 3. Filtrar por nombre
119 efrain 557
                if($name) {
558
                    if(empty($name) || stripos($capsule->name, $name) === false) {
559
                        continue;
560
                    }
561
                }
562
 
558 stevensc 563
                // 4. Obtener Tópico asociado válido
564
                $topic = null;
565
                $topic_uuid_for_links = null;
566
                $relation = $topicCapsuleMapper->fetchOneByCapsuleId($capsule->id);
567
                if ($relation && in_array($relation->topic_id, $accessGranted->topics)) {
568
                    $topic = $topicMapper->fetchOne($relation->topic_id);
569
                    if ($topic) {
570
                        $topic_uuid_for_links = $topic->uuid;
571
                    }
572
                }
573
 
574
                // 5. Obtener datos de comentarios
302 www 575
                $dataCountAndRatingAverage = $capsuleCommentMapper->fetchCountAndRatingAverage($capsule->company_id,  $capsule->id);
119 efrain 576
 
558 stevensc 577
                // 6. Construir enlace slides
578
                $link_slides = $topic_uuid_for_links ? $this->url()->fromRoute('microlearning/slides', ['topic_id' => $topic_uuid_for_links,  'capsule_id' => $capsule->uuid], ['force_canonical' => true]) : '';
119 efrain 579
 
558 stevensc 580
                // 7. Añadir al array de resultados
581
                array_push($capsulesData, [
119 efrain 582
                    'uuid'              => $capsule->uuid,
583
                    'name'              => $capsule->name ? $capsule->name : '',
584
                    'description'       => $capsule->description ? $capsule->description : '',
283 www 585
                    'image'             => $capsule->image ? $storage->getGenericImage($path, $capsule->uuid, $capsule->image)  : '',
119 efrain 586
                    'position'          => $capsule->order,
587
                    'link_comments'     => $this->url()->fromRoute('microlearning/capsules-comments', ['capsule_id' => $capsule->uuid], ['force_canonical' => true]),
588
                    'link_comment_add'  => $this->url()->fromRoute('microlearning/capsules-comments/add', ['capsule_id' => $capsule->uuid],['force_canonical' => true]),
558 stevensc 589
                    'link_slides'       => $link_slides, // Usar enlace construido
119 efrain 590
                    'total_comments'    => strval($dataCountAndRatingAverage['total_comments']),
591
                    'total_rating'      => strval($dataCountAndRatingAverage['total_rating']),
191 efrain 592
                    'progress'          => 0,
119 efrain 593
                    'added_on'          => $capsule->added_on,
594
                    'updated_on'        => $capsule->updated_on,
595
                ]);
596
            }
597
 
558 stevensc 598
            // 8. Ordenar
245 efrain 599
 
600
            if($order_field == 'name') {
601
                if($order_direction == 'asc') {
558 stevensc 602
                    usort($capsulesData, function($a, $b) {
245 efrain 603
                        return strcasecmp($a['name'], $b['name']);
604
                    });
605
                } else {
558 stevensc 606
                    usort($capsulesData, function($a, $b) {
245 efrain 607
                        $result = strcasecmp($a['name'], $b['name']);
558 stevensc 608
                        if($result < 0) { return 1; } else if($result > 0) { return -1; } else { return 0; } // Simplificado
245 efrain 609
                    });
119 efrain 610
                }
611
 
245 efrain 612
            }
613
 
614
            if($order_field == 'added_on') {
615
                if($order_direction == 'asc') {
558 stevensc 616
                    usort($capsulesData, function($a, $b) {
245 efrain 617
                        return strcasecmp($a['added_on'], $b['added_on']);
618
                    });
619
                } else {
558 stevensc 620
                    usort($capsulesData, function($a, $b) {
245 efrain 621
                        $result = strcasecmp($a['added_on'], $b['added_on']);
558 stevensc 622
                        if($result < 0) { return 1; } else if($result > 0) { return -1; } else { return 0; } // Simplificado
245 efrain 623
                    });
624
                }
119 efrain 625
 
558 stevensc 626
            }
119 efrain 627
 
558 stevensc 628
            // 9. Retornar
119 efrain 629
            return new JsonModel([
630
                'success' => true,
558 stevensc 631
                'data' => $capsulesData
119 efrain 632
            ]);
633
 
634
 
635
 
636
        }
637
 
638
        return new JsonModel([
639
            'success' => false,
640
            'data' => 'ERROR_METHOD_NOT_ALLOWED'
641
        ]);
642
 
643
    }
644
 
645
    public function capsulesCompletedAction()
646
    {
647
        $request = $this->getRequest();
648
        if($request->isGet()) {
649
            $currentUserPlugin = $this->plugin('currentUserPlugin');
650
            $currentUser = $currentUserPlugin->getUser();
651
 
652
            $name = Functions::sanitizeFilterString($this->params()->fromQuery('name'));
245 efrain 653
            $order_field = Functions::sanitizeFilterString($this->params()->fromQuery('order_field'));
654
            $order_direction = Functions::sanitizeFilterString($this->params()->fromQuery('order_direction'));
119 efrain 655
 
246 efrain 656
            if(!in_array($order_field,['name', 'added_on','last_access_on'] )) {
245 efrain 657
                $order_field = 'name';
658
            }
119 efrain 659
 
245 efrain 660
            if(!in_array( $order_direction,['asc', 'desc'])) {
661
                $order_field = 'asc';
662
            }
663
 
283 www 664
            $userProgressMapper = MicrolearningUserProgressMapper::getInstance($this->adapter);
665
            $capsuleMapper = MicrolearningCapsuleMapper::getInstance($this->adapter);
558 stevensc 666
            $topicCapsuleMapper = MicrolearningTopicCapsuleMapper::getInstance($this->adapter);
667
            $topicMapper = MicrolearningTopicMapper::getInstance($this->adapter);
283 www 668
            $capsuleCommentMapper = MicrolearningCapsuleCommentMapper::getInstance($this->adapter);
119 efrain 669
 
670
            $accessGranted = $this->getAccessGranted();
671
 
558 stevensc 672
            $capsulesData = [];
119 efrain 673
 
333 www 674
            $storage = Storage::getInstance($this->config, $this->adapter);
283 www 675
            $path = $storage->getPathMicrolearningCapsule();
676
 
119 efrain 677
            foreach($accessGranted->capsules as $capsule_id)
678
            {
558 stevensc 679
                // 1. Verificar progreso
119 efrain 680
                $userProgress = $userProgressMapper->fetchOneByUseridAndCapsuleId($currentUser->id, $capsule_id);
681
                if(!$userProgress) {
682
                    continue;
683
                }
684
 
685
                if(!$userProgress->completed) {
686
                    continue;
687
                }
688
 
558 stevensc 689
                // 2. Obtener detalles de la cápsula
119 efrain 690
                $capsule = $capsuleMapper->fetchOne($capsule_id);
558 stevensc 691
                if(!$capsule) {
692
                    continue;
693
                }
119 efrain 694
 
558 stevensc 695
                // 3. Filtrar por nombre
119 efrain 696
                if($name) {
697
                    if(empty($name) || stripos($capsule->name, $name) === false) {
698
                        continue;
699
                    }
700
                }
701
 
558 stevensc 702
                // 4. Obtener Tópico asociado válido
703
                $topic = null;
704
                $topic_uuid_for_links = null;
705
                $relation = $topicCapsuleMapper->fetchOneByCapsuleId($capsule->id);
706
                if ($relation && in_array($relation->topic_id, $accessGranted->topics)) {
707
                    $topic = $topicMapper->fetchOne($relation->topic_id);
708
                    if ($topic) {
709
                        $topic_uuid_for_links = $topic->uuid;
710
                    }
711
                }
712
 
713
                // 5. Obtener datos de comentarios
302 www 714
                $dataCountAndRatingAverage = $capsuleCommentMapper->fetchCountAndRatingAverage($capsule->company_id, $capsule->id);
119 efrain 715
 
558 stevensc 716
                // 6. Construir enlace slides
717
                $link_slides = $topic_uuid_for_links ? $this->url()->fromRoute('microlearning/slides', ['topic_id' => $topic_uuid_for_links,  'capsule_id' => $capsule->uuid], ['force_canonical' => true]) : '';
119 efrain 718
 
558 stevensc 719
                // 7. Añadir al array de resultados
720
                array_push($capsulesData, [
119 efrain 721
                    'uuid'              => $capsule->uuid,
722
                    'name'              => $capsule->name ? $capsule->name : '',
723
                    'description'       => $capsule->description ? $capsule->description : '',
283 www 724
                    'image'             => $capsule->image ? $storage->getGenericImage($path, $capsule->uuid, $capsule->image)  : '',
119 efrain 725
                    'position'          => $capsule->order,
726
                    'link_comments'     => $this->url()->fromRoute('microlearning/capsules-comments', ['capsule_id' => $capsule->uuid], ['force_canonical' => true]),
727
                    'link_comment_add'  => $this->url()->fromRoute('microlearning/capsules-comments/add', ['capsule_id' => $capsule->uuid],['force_canonical' => true]),
558 stevensc 728
                    'link_slides'       => $link_slides,
119 efrain 729
                    'total_comments'    => strval($dataCountAndRatingAverage['total_comments']),
730
                    'total_rating'      => strval($dataCountAndRatingAverage['total_rating']),
145 efrain 731
                    'progress'          => $userProgress->progress,
119 efrain 732
                    'added_on'          => $capsule->added_on,
246 efrain 733
                    'last_access_on'    => $userProgress->updated_on,
119 efrain 734
                    'updated_on'        => $capsule->updated_on,
735
                ]);
736
            }
737
 
558 stevensc 738
            // 8. Ordenar (lógica de ordenación permanece igual, usando $capsulesData)
245 efrain 739
            if($order_field == 'name') {
740
                if($order_direction == 'asc') {
558 stevensc 741
                    usort($capsulesData, function($a, $b) {
245 efrain 742
                        return strcasecmp($a['name'], $b['name']);
743
                    });
744
                } else {
558 stevensc 745
                    usort($capsulesData, function($a, $b) {
245 efrain 746
                        $result = strcasecmp($a['name'], $b['name']);
558 stevensc 747
                        if($result < 0) { return 1; } else if($result > 0) { return -1; } else { return 0; }
245 efrain 748
                    });
119 efrain 749
                }
245 efrain 750
            }
751
 
752
            if($order_field == 'added_on') {
753
                if($order_direction == 'asc') {
558 stevensc 754
                    usort($capsulesData, function($a, $b) {
245 efrain 755
                        return strcasecmp($a['added_on'], $b['added_on']);
756
                    });
757
                } else {
558 stevensc 758
                    usort($capsulesData, function($a, $b) {
245 efrain 759
                        $result = strcasecmp($a['added_on'], $b['added_on']);
558 stevensc 760
                        if($result < 0) { return 1; } else if($result > 0) { return -1; } else { return 0; }
245 efrain 761
                    });
762
                }
763
            }
246 efrain 764
 
765
            if($order_field == 'last_access_on') {
766
                if($order_direction == 'asc') {
558 stevensc 767
                    usort($capsulesData, function($a, $b) {
246 efrain 768
                        return strcasecmp($a['last_access_on'], $b['last_access_on']);
769
                    });
770
                } else {
558 stevensc 771
                    usort($capsulesData, function($a, $b) {
246 efrain 772
                        $result = strcasecmp($a['last_access_on'], $b['last_access_on']);
558 stevensc 773
                        if($result < 0) { return 1; } else if($result > 0) { return -1; } else { return 0; }
246 efrain 774
                    });
775
                }
776
            }
777
 
778
 
779
 
780
 
119 efrain 781
 
782
            return new JsonModel([
783
                'success' => true,
558 stevensc 784
                'data' => $capsulesData
119 efrain 785
            ]);
786
 
787
        }
788
 
789
        return new JsonModel([
790
            'success' => false,
791
            'data' => 'ERROR_METHOD_NOT_ALLOWED'
792
        ]);
793
    }
794
 
795
    public function capsulesInProgressAction()
796
    {
797
        $request = $this->getRequest();
798
        if($request->isGet()) {
799
            $currentUserPlugin = $this->plugin('currentUserPlugin');
800
            $currentUser = $currentUserPlugin->getUser();
801
 
802
            $name = Functions::sanitizeFilterString($this->params()->fromQuery('name'));
245 efrain 803
            $order_field = Functions::sanitizeFilterString($this->params()->fromQuery('order_field'));
804
            $order_direction = Functions::sanitizeFilterString($this->params()->fromQuery('order_direction'));
119 efrain 805
 
246 efrain 806
            if(!in_array($order_field,['name', 'added_on', 'last_access_on'] )) {
245 efrain 807
                $order_field = 'name';
808
            }
119 efrain 809
 
245 efrain 810
            if(!in_array( $order_direction,['asc', 'desc'])) {
558 stevensc 811
                $order_direction = 'asc';
245 efrain 812
            }
813
 
283 www 814
            $userProgressMapper = MicrolearningUserProgressMapper::getInstance($this->adapter);
815
            $capsuleMapper = MicrolearningCapsuleMapper::getInstance($this->adapter);
558 stevensc 816
            $topicCapsuleMapper = MicrolearningTopicCapsuleMapper::getInstance($this->adapter);
817
            $topicMapper = MicrolearningTopicMapper::getInstance($this->adapter);
283 www 818
            $capsuleCommentMapper = MicrolearningCapsuleCommentMapper::getInstance($this->adapter);
119 efrain 819
 
820
            $accessGranted = $this->getAccessGranted();
821
 
558 stevensc 822
            $capsulesData = [];
119 efrain 823
 
333 www 824
            $storage = Storage::getInstance($this->config, $this->adapter);
283 www 825
            $path = $storage->getPathMicrolearningCapsule();
826
 
119 efrain 827
            foreach($accessGranted->capsules as $capsule_id)
828
            {
558 stevensc 829
                // 1. Verificar progreso
119 efrain 830
                $userProgress = $userProgressMapper->fetchOneByUseridAndCapsuleId($currentUser->id, $capsule_id);
558 stevensc 831
                if(!$userProgress || $userProgress->completed) { // Si no hay progreso o ya está completada
119 efrain 832
                    continue;
833
                }
558 stevensc 834
 
835
                // 2. Obtener detalles de la cápsula
836
                $capsule = $capsuleMapper->fetchOne($capsule_id);
837
                if(!$capsule) {
119 efrain 838
                    continue;
839
                }
840
 
558 stevensc 841
                // 3. Filtrar por nombre
119 efrain 842
                if($name) {
843
                    if(empty($name) || stripos($capsule->name, $name) === false) {
844
                        continue;
845
                    }
846
                }
847
 
558 stevensc 848
                // 4. Obtener Tópico asociado válido
849
                $topic = null;
850
                $topic_uuid_for_links = null;
851
                $relation = $topicCapsuleMapper->fetchOneByCapsuleId($capsule->id);
852
                if ($relation && in_array($relation->topic_id, $accessGranted->topics)) {
853
                    $topic = $topicMapper->fetchOne($relation->topic_id);
854
                    if ($topic) {
855
                        $topic_uuid_for_links = $topic->uuid;
856
                    }
857
                }
119 efrain 858
 
558 stevensc 859
                // 5. Obtener datos de comentarios
302 www 860
                $dataCountAndRatingAverage = $capsuleCommentMapper->fetchCountAndRatingAverage($capsule->company_id,  $capsule->id);
119 efrain 861
 
558 stevensc 862
                // 6. Construir enlace slides
863
                $link_slides = $topic_uuid_for_links ? $this->url()->fromRoute('microlearning/slides', ['topic_id' => $topic_uuid_for_links,  'capsule_id' => $capsule->uuid], ['force_canonical' => true]) : '';
119 efrain 864
 
558 stevensc 865
                // 7. Añadir al array de resultados
866
                array_push($capsulesData, [
119 efrain 867
                    'uuid'              => $capsule->uuid,
868
                    'name'              => $capsule->name ? $capsule->name : '',
869
                    'description'       => $capsule->description ? $capsule->description : '',
283 www 870
                    'image'             => $capsule->image ? $storage->getGenericImage($path, $capsule->uuid, $capsule->image)  : '',
119 efrain 871
                    'position'          => $capsule->order,
872
                    'link_comments'     => $this->url()->fromRoute('microlearning/capsules-comments', ['capsule_id' => $capsule->uuid], ['force_canonical' => true]),
873
                    'link_comment_add'  => $this->url()->fromRoute('microlearning/capsules-comments/add', ['capsule_id' => $capsule->uuid],['force_canonical' => true]),
558 stevensc 874
                    'link_slides'       => $link_slides,
119 efrain 875
                    'total_comments'    => strval($dataCountAndRatingAverage['total_comments']),
876
                    'total_rating'      => strval($dataCountAndRatingAverage['total_rating']),
585 stevensc 877
                    'progress'          => $userProgress->progress,
878
                    'last_access_on'    => $userProgress->updated_on,
879
                    'added_on'          => $capsule->added_on,
880
                    'updated_on'        => $capsule->updated_on,
119 efrain 881
                ]);
882
            }
883
 
558 stevensc 884
            // 8. Ordenar (lógica de ordenación permanece igual, usando $capsulesData)
245 efrain 885
            if($order_field == 'name') {
886
                if($order_direction == 'asc') {
558 stevensc 887
                    usort($capsulesData, function($a, $b) {
245 efrain 888
                        return strcasecmp($a['name'], $b['name']);
889
                    });
890
                } else {
558 stevensc 891
                    usort($capsulesData, function($a, $b) {
245 efrain 892
                        $result = strcasecmp($a['name'], $b['name']);
558 stevensc 893
                        if($result < 0) { return 1; } else if($result > 0) { return -1; } else { return 0; }
245 efrain 894
                    });
119 efrain 895
                }
245 efrain 896
            }
897
 
898
            if($order_field == 'added_on') {
899
                if($order_direction == 'asc') {
558 stevensc 900
                    usort($capsulesData, function($a, $b) {
245 efrain 901
                        return strcasecmp($a['added_on'], $b['added_on']);
902
                    });
903
                } else {
558 stevensc 904
                    usort($capsulesData, function($a, $b) {
245 efrain 905
                        $result = strcasecmp($a['added_on'], $b['added_on']);
558 stevensc 906
                        if($result < 0) { return 1; } else if($result > 0) { return -1; } else { return 0; }
245 efrain 907
                    });
908
                }
909
            }
246 efrain 910
 
911
            if($order_field == 'last_access_on') {
912
                if($order_direction == 'asc') {
558 stevensc 913
                    usort($capsulesData, function($a, $b) {
246 efrain 914
                        return strcasecmp($a['last_access_on'], $b['last_access_on']);
915
                    });
916
                } else {
558 stevensc 917
                    usort($capsulesData, function($a, $b) {
246 efrain 918
                        $result = strcasecmp($a['last_access_on'], $b['last_access_on']);
558 stevensc 919
                        if($result < 0) { return 1; } else if($result > 0) { return -1; } else { return 0; }
246 efrain 920
                    });
921
                }
922
            }
245 efrain 923
 
246 efrain 924
 
119 efrain 925
            return new JsonModel([
926
                'success' => true,
558 stevensc 927
                'data' => $capsulesData
119 efrain 928
            ]);
929
        }
930
 
931
        return new JsonModel([
932
            'success' => false,
933
            'data' => 'ERROR_METHOD_NOT_ALLOWED'
934
        ]);
935
    }
936
 
937
 
938
    public function timelineAction()
939
    {
940
 
941
        $request = $this->getRequest();
942
        if($request->isGet()) {
943
            $currentUserPlugin = $this->plugin('currentUserPlugin');
944
            $currentUser = $currentUserPlugin->getUser();
945
 
946
 
947
            $page = intval($this->params()->fromQuery('page'), 10);
948
 
949
            $activities = [
283 www 950
                MicrolearningUserLog::ACTIVITY_SIGNIN            => 'LABEL_MICROLEARNING_ACTIVITY_SIGNIN',
951
                MicrolearningUserLog::ACTIVITY_SIGNOUT           => 'LABEL_MICROLEARNING_ACTIVITY_SIGNOUT',
952
                MicrolearningUserLog::ACTIVITY_START_TOPIC       => 'LABEL_MICROLEARNING_ACTIVITY_START_TOPIC',
953
                MicrolearningUserLog::ACTIVITY_START_CAPSULE     => 'LABEL_MICROLEARNING_ACTIVITY_START_CAPSULE',
954
                MicrolearningUserLog::ACTIVITY_VIEW_SLIDE        => 'LABEL_MICROLEARNING_ACTIVITY_VIEW_SLIDE',
955
                MicrolearningUserLog::ACTIVITY_TAKE_A_TEST       => 'LABEL_MICROLEARNING_ACTIVITY_TAKE_A_TEST',
956
                MicrolearningUserLog::ACTIVITY_RETAKE_A_TEST     => 'LABEL_MICROLEARNING_ACTIVITY_RETAKE_A_TEST',
957
                MicrolearningUserLog::ACTIVITY_APPROVED_TEST     => 'LABEL_MICROLEARNING_ACTIVITY_APPROVED_TEST',
958
                MicrolearningUserLog::ACTIVITY_COMPLETED_CAPSULE => 'LABEL_MICROLEARNING_ACTIVITY_COMPLETED_CAPSULE',
959
                MicrolearningUserLog::ACTIVITY_COMPLETED_TOPIC   => 'LABEL_MICROLEARNING_ACTIVITY_COMPLETED_TOPIC',
119 efrain 960
            ];
961
 
962
 
963
 
283 www 964
            $microlearningUserLogMapper = MicrolearningUserLogMapper::getInstance($this->adapter);
965
            $paginator = $microlearningUserLogMapper->getAllMessagesPaginatorByUserId($currentUser->id, $page);
119 efrain 966
 
967
            $items = [];
968
            foreach($paginator as $record)
969
            {
970
                $dt = \DateTime::createFromFormat('Y-m-d H:i:s', $record->added_on);
971
 
972
                array_push($items, [
973
                    'activity' => $activities[$record->activity],
974
                    'added_on' => $dt->format('d/m/Y H:i a')
975
                ]);
976
            }
977
 
978
 
979
            return new JsonModel([
980
                'success' => true,
981
                'data' => [
982
                    'total' => [
983
                        'count' => $paginator->getTotalItemCount(),
984
                        'pages' => $paginator->getPages()->pageCount,
985
                    ],
986
                    'current' => [
987
                        'items'    => $items,
988
                        'page'     => $paginator->getCurrentPageNumber(),
989
                        'count'    => $paginator->getCurrentItemCount(),
990
                    ]
991
                ]
992
            ]);
993
 
994
 
995
        } else {
996
            return new JsonModel([
997
                'success' => false,
998
                'data' => 'ERROR_METHOD_NOT_ALLOWED'
999
            ]);
1000
        }
1001
    }
1002
 
1003
    /**
1004
     * Valores para la generación de los gráficos de progreso
1005
     * Para las repuesta afirmativa
1006
     * [
1007
     *  'success' => true,
1008
     *      'data' => [
1009
     *          'topicTotal' => cantidad total de tópicos,
1010
     *          'topicStarted' => cantidad de tópicos iniciados,
1011
     *          'topicIncompleted' => cantidad de tópicos incompletos,
1012
     *          'topicCompleted' => cantidad de tópicos completos,
1013
     *          'percentCompleted' => % de diapositivas completados ,
1014
     *          'percentIncompleted' => % de diapositivas incompletos ,
1015
     *          'percentWithoutReturning' => % de cápsulas sin retorno después de completada,
1016
     *          'percentWithReturning' => % de cápsulas con retorno después de completada,
558 stevensc 1017
     *      ],
119 efrain 1018
     * ]
1019
     *
1020
     *
1021
     *  En caso contrario
1022
     *  [
1023
     *      'success' => false,
1024
     *      'data' => mensaje de error
1025
     *  ]
1026
     *
1027
     *
1028
     * @return \Laminas\View\Model\JsonModel
1029
     */
1030
    public function progressAction()
1031
    {
1032
 
1033
        $request = $this->getRequest();
1034
        if($request->isGet()) {
1035
            $currentUserPlugin = $this->plugin('currentUserPlugin');
1036
            $currentUser = $currentUserPlugin->getUser();
1037
 
1038
 
1039
            $accessGrantedIds = $this->getAccessGranted();
1040
            $id = $this->params()->fromRoute('id');
1041
 
1042
            $companyMapper = CompanyMapper::getInstance($this->adapter);
1043
            $company = $companyMapper->fetchOneByUuid($id);
1044
 
1045
            if(!$company) {
1046
                $response = [
1047
                    'success' => false,
1048
                    'data' => 'ERROR_COMPANY_NOT_FOUND',
1049
                ];
1050
 
1051
 
1052
                return new JsonModel($response);
1053
            }
1054
 
1055
            if(!in_array($company->id, $accessGrantedIds->companies)) {
1056
                $response = [
1057
                    'success' => false,
1058
                    'data' => 'ERROR_YOU_DO_NOT_HAVE_ACCESS_TO_THIS_COMPANY',
1059
                ];
1060
 
1061
 
1062
                return new JsonModel($response);
1063
            }
1064
 
1065
            $capsuleTotal              = 0;
1066
            $capsuleCompleted          = 0;
1067
            $capsuleWithReturning      = 0;
1068
            $capsuleWithoutReturning   = 0;
1069
            $capsuleStarted            = 0;
1070
            $capsuleToStart            = 0;
1071
            $percentCompleted          = 0;
1072
            $percentIncompleted        = 100;
1073
 
283 www 1074
            $topicMapper = MicrolearningTopicMapper::getInstance($this->adapter);
119 efrain 1075
            $topics = $topicMapper->fetchAllActiveByCompanyIdAndIds($company->id, $accessGrantedIds->topics);
1076
 
283 www 1077
            $progressMapper = MicrolearningUserProgressMapper::getInstance($this->adapter);
119 efrain 1078
 
302 www 1079
            $topicCapsuleMapper = MicrolearningTopicCapsuleMapper::getInstance($this->adapter);
119 efrain 1080
 
1081
            foreach($topics as $topic)
1082
            {
302 www 1083
                $resultCount = $topicCapsuleMapper->fetchCountByCompanyIdAndTopicId($company->id, $topic->id);
119 efrain 1084
                $capsuleTotal =  $capsuleTotal + $resultCount;
1085
 
1086
                $resultCount = $progressMapper->fetchCountCapsulesCompletedByIdAndTopicId($currentUser->id, $topic->id);
1087
                $capsuleCompleted = $capsuleCompleted + $resultCount;
1088
 
1089
                $resultCount = $progressMapper->fetchCountCapsulesCompletedWithReturningByIdAndTopicId($currentUser->id, $topic->id);
1090
                $capsuleWithReturning = $capsuleWithReturning + $resultCount;
1091
 
1092
                $resultCount = $progressMapper->fetchCountCapsulesCompletedWithoutReturningByIdAndTopicId($currentUser->id, $topic->id);
1093
                $capsuleWithoutReturning = $capsuleWithoutReturning + $resultCount;
1094
 
1095
                $resultCount = $progressMapper->fetchCountCapsulesCompletedByIdAndTopicId($currentUser->id, $topic->id);
1096
                $capsuleStarted = $capsuleStarted + $resultCount;
1097
            }
1098
 
1099
            $capsuleToStart = $capsuleTotal -  $capsuleStarted;
1100
 
1101
            if($capsuleTotal > 0) {
1102
                $percentCompleted = ($capsuleCompleted * 100) /  $capsuleTotal;
1103
                $percentIncompleted = 100 - $percentCompleted;
1104
            }
1105
 
1106
            return new JsonModel([
1107
                'success' => true,
1108
                'data' => [
1109
                    'capsuleTotal' => $capsuleTotal,
1110
                    'capsuleCompleted' => $capsuleCompleted,
1111
                    'capsuleStarted' => $capsuleStarted,
1112
                    'capsuleToStart' => $capsuleToStart,
1113
                    'percentCompleted' => number_format($percentCompleted, 2, '.', ','),
1114
                    'percentIncompleted' => number_format($percentIncompleted, 2, '.', ','),
1115
                    'capsuleWithReturning' => $capsuleWithReturning,
1116
                    'capsuleWithoutReturning' => $capsuleWithoutReturning,
1117
                ],
1118
            ]);
1119
 
1120
 
1121
        } else {
1122
            return new JsonModel([
1123
                'success' => false,
1124
                'data' => 'ERROR_METHOD_NOT_ALLOWED'
1125
            ]);
1126
        }
1127
    }
1128
 
1129
 
1130
    public function topicsAction()
1131
    {
1132
        $request = $this->getRequest();
626 stevensc 1133
 
119 efrain 1134
        if($request->isGet()) {
1135
            $currentUserPlugin = $this->plugin('currentUserPlugin');
1136
            $currentUser = $currentUserPlugin->getUser();
1137
 
1138
            $data = [];
1139
            $accessGrantedIds = $this->getAccessGranted();
1140
 
283 www 1141
            $userProgressMapper = MicrolearningUserProgressMapper::getInstance($this->adapter);
1142
            $topicMapper = MicrolearningTopicMapper::getInstance($this->adapter);
119 efrain 1143
 
333 www 1144
            $storage = Storage::getInstance($this->config, $this->adapter);
283 www 1145
            $path = $storage->getPathMicrolearningTopic();
119 efrain 1146
 
1147
            foreach($accessGrantedIds->topics as $id)
1148
            {
1149
                $topic = $topicMapper->fetchOne($id);
1150
                if(!$topic) {
1151
                    continue;
1152
                }
1153
 
1154
                $userProgress = $userProgressMapper->fetchOneByUserIdAndTopicId($currentUser->id, $id);
1155
                if($userProgress) {
1156
                    $progress = $userProgress->progress;
1157
                    $completed = $userProgress->completed;
1158
                } else {
1159
                    $progress = 0;
1160
                    $completed = 0;
1161
                }
1162
 
1163
 
1164
 
1165
                array_push($data, [
164 efrain 1166
                    'uuid'          => $topic->uuid,
119 efrain 1167
                    'name'          => $topic->name ? $topic->name : '',
1168
                    'description'   => $topic->description ? $topic->description : '',
283 www 1169
                    'image'         => $topic->image ? $storage->getGenericImage($path, $topic->uuid, $topic->image) : '',
119 efrain 1170
                    'progress'      => $progress,
1171
                    'completed'     => $completed,
1172
                    'order'         => $topic->order,
1173
                    'added_on'      => $topic->added_on,
564 stevensc 1174
                    'updated_on'    => $topic->updated_on
119 efrain 1175
                ]);
1176
            }
1177
 
1178
            usort($data, function($a, $b) {
1179
 
1180
                $result =  $a['order'] <=> $b['order'];
1181
                if(0 == $result) {
1182
                    $result = strcasecmp($a['added_on'], $b['added_on']);
1183
                    if(0 == $result) {
1184
                        $result = strcasecmp($a['name'], $b['name']);
1185
                    }
1186
                }
1187
 
1188
                if($result < 0) {
1189
                    return 1;
1190
                } else if($result > 0) {
1191
                    return -1;
1192
                } else  {
1193
                    return  0;
1194
                }
1195
            });
1196
 
1197
 
1198
 
1199
                return new JsonModel([
1200
                    'success' => true,
1201
                    'data' => $data
1202
                ]);
1203
 
1204
        } else {
1205
            return new JsonModel([
1206
                'success' => false,
1207
                'data' => 'ERROR_METHOD_NOT_ALLOWED'
1208
            ]);
1209
        }
1210
    }
1211
 
161 efrain 1212
    public function getTopicAction()
1213
    {
563 stevensc 1214
        // Handle GET request
161 efrain 1215
        $request = $this->getRequest();
1216
        if($request->isGet()) {
563 stevensc 1217
            // Get current user
161 efrain 1218
            $currentUserPlugin = $this->plugin('currentUserPlugin');
1219
            $currentUser = $currentUserPlugin->getUser();
563 stevensc 1220
 
1221
            // Get topic ID from route
161 efrain 1222
            $id = $this->params()->fromRoute('id');
283 www 1223
            $topicMapper = MicrolearningTopicMapper::getInstance($this->adapter);
161 efrain 1224
            $topic = $topicMapper->fetchOneByUuid($id);
563 stevensc 1225
 
1226
            // Return error if topic not found
161 efrain 1227
            if(!$topic) {
1228
                return new JsonModel([
1229
                    'success' => false,
1230
                    'data' => 'ERROR_TOPIC_NOT_FOUND'
1231
                ]);
1232
            }
563 stevensc 1233
 
1234
            // Check if current user has access to the topic
161 efrain 1235
            $accessGrantedIds = $this->getAccessGranted();
1236
            if(!in_array($topic->id, $accessGrantedIds->topics)) {
1237
                return new JsonModel([
1238
                    'success' => false,
1239
                    'data' => 'ERROR_YOU_DO_NOT_HAVE_ACCESS_TO_THIS_TOPIC'
1240
                ]);
1241
            }
563 stevensc 1242
 
1243
            // Get user progress for this topic
283 www 1244
            $userProgressMapper = MicrolearningUserProgressMapper::getInstance($this->adapter);
563 stevensc 1245
            $userProgress = $userProgressMapper->fetchOneByUserIdAndTopicId($currentUser->id, $topic->id);
161 efrain 1246
 
580 stevensc 1247
            $progress = $userProgress->progress ?? 0;
1248
            $completed = $userProgress->completed ?? 0;
563 stevensc 1249
 
1250
            // Initialize storage service to get image paths
333 www 1251
            $storage = Storage::getInstance($this->config, $this->adapter);
563 stevensc 1252
            $pathTopic = $storage->getPathMicrolearningTopic();
1253
 
1254
            // Fetch associated capsules using the private helper method
1255
            $capsulesData = $this->_getCapsulesByTopic($topic, $storage);
1256
 
1257
            // Prepare data for JSON response
161 efrain 1258
            $data = [
165 efrain 1259
                'uuid'          => $topic->uuid,
161 efrain 1260
                'name'          => $topic->name ? $topic->name : '',
1261
                'description'   => $topic->description ? $topic->description : '',
563 stevensc 1262
                'image'         => $topic->image ? $storage->getGenericImage($pathTopic, $topic->uuid, $topic->image) : '',
161 efrain 1263
                'progress'      => $progress,
1264
                'completed'     => $completed,
1265
                'order'         => $topic->order,
1266
                'added_on'      => $topic->added_on,
1267
                'updated_on'    => $topic->updated_on,
563 stevensc 1268
                'total_capsules' => count($capsulesData),
1269
                'capsules'      => $capsulesData,
161 efrain 1270
            ];
563 stevensc 1271
 
161 efrain 1272
            return new JsonModel([
1273
                'success' => true,
1274
                'data' => $data
1275
            ]);
563 stevensc 1276
 
161 efrain 1277
        } else {
563 stevensc 1278
            // Return error if not a GET request
161 efrain 1279
            return new JsonModel([
1280
                'success' => false,
1281
                'data' => 'ERROR_METHOD_NOT_ALLOWED'
1282
            ]);
1283
        }
1284
    }
563 stevensc 1285
 
1286
    /**
580 stevensc 1287
     * @param MicrolearningTopic $topic The topic object.
1288
     * @param Storage $storage The storage object.
1289
     * @return array The capsules data.
563 stevensc 1290
     */
1291
    private function _getCapsulesByTopic($topic, $storage)
1292
    {
578 stevensc 1293
        $data = [];
584 stevensc 1294
        $accessGrantedIds = $this->getAccessGranted();
563 stevensc 1295
 
578 stevensc 1296
        if (!$topic) {
1297
            return $data;
1298
        }
1299
 
584 stevensc 1300
        if (!in_array($topic->id, $accessGrantedIds->topics)) {
578 stevensc 1301
            return $data;
584 stevensc 1302
        }
578 stevensc 1303
 
1304
        $currentUserPlugin = $this->plugin('currentUserPlugin');
1305
        $currentUser = $currentUserPlugin->getUser();
1306
 
1307
        $topicCapsuleMapper = MicrolearningTopicCapsuleMapper::getInstance($this->adapter);
574 stevensc 1308
        $topicCapsuleRelations = $topicCapsuleMapper->fetchAllActiveByTopicId($topic->id);
1309
 
581 stevensc 1310
        $userProgressMapper = MicrolearningUserProgressMapper::getInstance($this->adapter);
1311
        $capsuleCommentMapper = MicrolearningCapsuleCommentMapper::getInstance($this->adapter);
578 stevensc 1312
 
581 stevensc 1313
        $path = $storage->getPathMicrolearningCapsule();
1314
 
578 stevensc 1315
        foreach ($topicCapsuleRelations as $relation) {
584 stevensc 1316
            if(!in_array($relation->capsule_id, $accessGrantedIds->capsules)) {
1317
                continue;
1318
            }
578 stevensc 1319
 
581 stevensc 1320
            $capsuleMapper = MicrolearningCapsuleMapper::getInstance($this->adapter);
1321
            $capsule = $capsuleMapper->fetchOne($relation->capsule_id);
563 stevensc 1322
 
581 stevensc 1323
            if(!$capsule) {
1324
                continue;
1325
            }
1326
 
578 stevensc 1327
            $userProgress = $userProgressMapper->fetchOneByUseridAndCapsuleId($currentUser->id, $capsule->id);
1328
            $progress = $userProgress->progress ?? 0;
1329
            $completed = $userProgress->completed ?? 0;
1330
            $dataCountAndRatingAverage = $capsuleCommentMapper->fetchCountAndRatingAverage($capsule->company_id, $capsule->id);
1331
            $image = $capsule->image ? $storage->getGenericImage($path, $capsule->uuid, $capsule->image) : '';
1332
            $total_comments = strval($dataCountAndRatingAverage['total_comments']);
1333
            $total_rating = strval($dataCountAndRatingAverage['total_rating']);
1334
 
581 stevensc 1335
            array_push($data, [
578 stevensc 1336
                'uuid'              => $capsule->uuid,
1337
                'name'              => $capsule->name ? $capsule->name : '',
1338
                'description'       => $capsule->description ? $capsule->description : '',
1339
                'image'             => $image,
1340
                'total_comments'    => $total_comments,
1341
                'total_rating'      => $total_rating,
1342
                'progress'          => $progress,
1343
                'completed'         => $completed,
1344
                'added_on'          => $capsule->added_on,
1345
                'updated_on'        => $capsule->updated_on,
581 stevensc 1346
            ]);
563 stevensc 1347
        }
578 stevensc 1348
 
581 stevensc 1349
        return $data;
563 stevensc 1350
    }
586 stevensc 1351
 
1352
    /**
1353
     * @param MicrolearningCapsule $capsule The capsule object.
1354
     * @param Storage $storage The storage object.
1355
     * @return array The slides data.
1356
     */
1357
    private function _getSlidesByCapsule($capsule, $storage)
1358
    {
1359
        $data = [];
1360
        $accessGrantedIds = $this->getAccessGranted();
1361
 
1362
        if (!$capsule) {
1363
            return $data;
1364
        }
1365
 
1366
        if (!in_array($capsule->id, $accessGrantedIds->capsules)) {
1367
            return $data;
1368
        }
1369
 
1370
        $currentUserPlugin = $this->plugin('currentUserPlugin');
1371
        $currentUser = $currentUserPlugin->getUser();
1372
 
1373
        $slideMapper = MicrolearningSlideMapper::getInstance($this->adapter);
1374
        $userProgressMapper = MicrolearningUserProgressMapper::getInstance($this->adapter);
1375
        $quizMapper = MicrolearningQuizMapper::getInstance($this->adapter);
1376
 
1377
        $path = $storage->getPathMicrolearningSlide();
587 stevensc 1378
        $slides = $slideMapper->fetchAllByCompanyIdAndCapsuleId($capsule->company_id, $capsule->id);
586 stevensc 1379
 
1380
        foreach ($slides as $slide) {
1381
            $userProgress = $userProgressMapper->fetchOneByUserIdAndSlideId($currentUser->id, $slide->id);
1382
            $completed = $userProgress ? $userProgress->completed : 0;
1383
 
1384
            $quiz_uuid = '';
1385
            $quiz_data = [];
1386
            $link_take_a_test = '';
1387
 
1388
            if ($slide->quiz_id) {
1389
                $quiz = $quizMapper->fetchOne($slide->quiz_id);
1390
                if ($quiz) {
1391
                    $quiz_uuid = $quiz->uuid;
1392
                    $quiz_data = $this->getQuiz($slide->quiz_id);
1393
                    $link_take_a_test = $this->url()->fromRoute('microlearning/take-a-test', ['slide_id' => $slide->uuid], ['force_canonical' => true]);
1394
                }
1395
            }
1396
 
1397
            array_push($data, [
1398
                'quiz'                  => $quiz_uuid,
1399
                'quiz_data'             => $quiz_data,
1400
                'uuid'                  => $slide->uuid,
1401
                'name'                  => $slide->name ? $slide->name : '',
1402
                'description'           => $slide->description ? $slide->description : '',
1403
                'type'                  => $slide->type,
1404
                'background'            => $slide->background ? $storage->getGenericImage($path, $slide->uuid, $slide->background) : '',
1405
                'file'                  => $slide->file ? $storage->getGenericFile($path, $slide->uuid, $slide->file) : '',
1406
                'order'                 => $slide->order,
1407
                'completed'             => $completed,
1408
                'link_take_a_test'      => $link_take_a_test,
1409
                'added_on'              => $slide->added_on,
1410
                'updated_on'            => $slide->updated_on,
1411
            ]);
1412
        }
1413
 
1414
        // Sort slides by order, then by added_on, then by name
1415
        usort($data, function($a, $b) {
1416
            $result = $a['order'] <=> $b['order'];
1417
            if (0 == $result) {
1418
                $result = strcasecmp($a['added_on'], $b['added_on']);
1419
                if (0 == $result) {
1420
                    $result = strcasecmp($a['name'], $b['name']);
1421
                }
1422
            }
1423
 
1424
            if ($result < 0) {
1425
                return 1;
1426
            } else if ($result > 0) {
1427
                return -1;
1428
            } else {
1429
                return 0;
1430
            }
1431
        });
1432
 
1433
        return $data;
1434
    }
1435
 
119 efrain 1436
    public function capsulesAction()
1437
    {
1438
        $request = $this->getRequest();
1439
        if($request->isGet()) {
580 stevensc 1440
            $currentUserPlugin = $this->plugin('currentUserPlugin');
1441
            $currentUser = $currentUserPlugin->getUser();
584 stevensc 1442
 
1443
            $topic_id_param = $this->params()->fromRoute('topic_id');
283 www 1444
            $topicMapper = MicrolearningTopicMapper::getInstance($this->adapter);
580 stevensc 1445
            $topic = $topicMapper->fetchOneByUuid($topic_id_param);
584 stevensc 1446
 
119 efrain 1447
            if(!$topic) {
1448
                return new JsonModel([
1449
                    'success' => false,
1450
                    'data' => 'ERROR_TOPIC_NOT_FOUND'
1451
                ]);
1452
            }
584 stevensc 1453
 
580 stevensc 1454
            $accessGrantedIds = $this->getAccessGranted();
584 stevensc 1455
 
119 efrain 1456
            if(!in_array($topic->id, $accessGrantedIds->topics)) {
1457
                return new JsonModel([
1458
                    'success' => false,
1459
                    'data' => 'ERROR_YOU_DO_NOT_HAVE_ACCESS_TO_THIS_TOPIC'
1460
                ]);
1461
            }
584 stevensc 1462
 
333 www 1463
            $storage = Storage::getInstance($this->config, $this->adapter);
584 stevensc 1464
            // Use the _getCapsulesByTopic method to fetch capsules
1465
            $data = $this->_getCapsulesByTopic($topic, $storage);
580 stevensc 1466
 
584 stevensc 1467
            // The _getCapsulesByTopic method already returns capsules with the required data structure.
1468
            // We just need to sort them.
1469
 
580 stevensc 1470
            usort($data, function($a, $b) {
584 stevensc 1471
 
580 stevensc 1472
                $result =  $a['order'] <=> $b['order'];
1473
                if(0 == $result) {
1474
                    $result = strcasecmp($a['added_on'], $b['added_on']);
1475
                    if(0 == $result) {
1476
                        $result = strcasecmp($a['name'], $b['name']);
1477
                    }
1478
                }
584 stevensc 1479
 
580 stevensc 1480
                if($result < 0) {
1481
                    return 1;
1482
                } else if($result > 0) {
1483
                    return -1;
1484
                } else  {
1485
                    return  0;
1486
                }
1487
            });
584 stevensc 1488
 
1489
            return new JsonModel([
1490
                'success' => true,
1491
                'data' => $data
1492
            ]);
1493
 
119 efrain 1494
        } else {
1495
            return new JsonModel([
1496
                'success' => false,
1497
                'data' => 'ERROR_METHOD_NOT_ALLOWED'
1498
            ]);
1499
        }
1500
    }
1501
 
235 efrain 1502
    public function takeTestAction()
1503
    {
1504
        $request = $this->getRequest();
1505
        if($request->isPost()) {
1506
            $currentUserPlugin = $this->plugin('currentUserPlugin');
1507
            $currentUser = $currentUserPlugin->getUser();
1508
 
1509
            $slide_id = $this->params()->fromRoute('slide_id');
283 www 1510
            $slideMapper = MicrolearningSlideMapper::getInstance($this->adapter);
235 efrain 1511
            $slide = $slideMapper->fetchOneByUuid($slide_id);
1512
 
1513
            if(!$slide) {
1514
                return new JsonModel([
1515
                    'success' => false,
1516
                    'data' => 'ERROR_SLIDE_NOT_FOUND'
1517
                ]);
1518
            }
1519
 
283 www 1520
            if($slide->type != MicrolearningSlide::TYPE_QUIZ) {
235 efrain 1521
                return new JsonModel([
1522
                    'success' => false,
1523
                    'data' => 'ERROR_SLIDE_IS_NOT_QUIZ'
1524
                ]);
1525
            }
1526
 
1527
 
1528
 
283 www 1529
            $capsuleMapper = MicrolearningCapsuleMapper::getInstance($this->adapter);
235 efrain 1530
            $capsule = $capsuleMapper->fetchOne($slide->capsule_id);
1531
 
1532
            if(!$capsule) {
1533
                return new JsonModel([
1534
                    'success' => false,
1535
                    'data' => 'ERROR_CAPSULE_NOT_FOUND'
1536
                ]);
1537
            }
1538
 
1539
            $accessGrantedIds = $this->getAccessGranted();
1540
 
1541
            if(!in_array($capsule->id, $accessGrantedIds->capsules)) {
1542
                return new JsonModel([
1543
                    'success' => false,
1544
                    'data' => 'ERROR_YOU_DO_NOT_HAVE_ACCESS_TO_THIS_CAPSULE'
1545
                ]);
1546
            }
1547
 
283 www 1548
            $userLogMapper = MicrolearningUserLogMapper::getInstance($this->adapter);
235 efrain 1549
            $userLog = $userLogMapper->fetchOneTakeATestByUserIdAndSlideId($currentUser->id, $slide->id);
1550
 
1551
            if($userLog) {
283 www 1552
                $activity = MicrolearningUserLog::ACTIVITY_RETAKE_A_TEST;
235 efrain 1553
            } else {
283 www 1554
                $activity = MicrolearningUserLog::ACTIVITY_TAKE_A_TEST;
235 efrain 1555
            }
1556
 
1557
            $added_on = $userLogMapper->getDatebaseNow();
1558
 
283 www 1559
            $userLog = new MicrolearningUserLog();
235 efrain 1560
            $userLog->activity      = $activity;
1561
            $userLog->user_id       = $currentUser->id;
1562
            $userLog->company_id    = $slide->company_id;
1563
            $userLog->topic_id      = $slide->topic_id;
1564
            $userLog->capsule_id    = $slide->capsule_id;
1565
            $userLog->slide_id      = $slide->id;
1566
            $userLog->added_on      = $added_on;
1567
 
1568
            if($userLogMapper->insert($userLog)) {
1569
                return new JsonModel([
1570
                    'success' => true,
1571
                ]);
1572
            } else {
1573
                return new JsonModel([
1574
                    'success' => false,
1575
                    'data' => $userLogMapper->getError()
1576
                ]);
1577
            }
1578
 
1579
 
1580
 
1581
 
1582
 
1583
 
1584
 
1585
        } else {
1586
            return new JsonModel([
1587
                'success' => false,
1588
                'data' => 'ERROR_METHOD_NOT_ALLOWED'
1589
            ]);
1590
        }
1591
    }
1592
 
161 efrain 1593
    public function getCapsuleAction()
1594
    {
1595
        $request = $this->getRequest();
587 stevensc 1596
 
161 efrain 1597
        if($request->isGet()) {
1598
            $currentUserPlugin = $this->plugin('currentUserPlugin');
1599
            $currentUser = $currentUserPlugin->getUser();
1600
 
558 stevensc 1601
            $capsule_uuid = $this->params()->fromRoute('id');
283 www 1602
            $capsuleMapper = MicrolearningCapsuleMapper::getInstance($this->adapter);
558 stevensc 1603
            $capsule = $capsuleMapper->fetchOneByUuid($capsule_uuid);
161 efrain 1604
 
1605
            if(!$capsule) {
1606
                return new JsonModel([
1607
                    'success' => false,
1608
                    'data' => 'ERROR_CAPSULE_NOT_FOUND'
1609
                ]);
1610
            }
1611
 
1612
            $accessGrantedIds = $this->getAccessGranted();
1613
 
1614
            if(!in_array($capsule->id, $accessGrantedIds->capsules)) {
1615
                return new JsonModel([
1616
                    'success' => false,
1617
                    'data' => 'ERROR_YOU_DO_NOT_HAVE_ACCESS_TO_THIS_CAPSULE'
1618
                ]);
1619
            }
1620
 
283 www 1621
            $userProgressMapper = MicrolearningUserProgressMapper::getInstance($this->adapter);
1622
            $capsuleCommentMapper = MicrolearningCapsuleCommentMapper::getInstance($this->adapter);
161 efrain 1623
 
1624
            $userProgress = $userProgressMapper->fetchOneByUseridAndCapsuleId($currentUser->id, $capsule->id);
587 stevensc 1625
            $progress = $userProgress->progress ?? 0;
1626
            $completed = $userProgress->completed ?? 0;
244 efrain 1627
 
586 stevensc 1628
            $dataCountAndRatingAverage = $capsuleCommentMapper->fetchCountAndRatingAverage($capsule->company_id, $capsule->id);
244 efrain 1629
 
587 stevensc 1630
            // Get comments data
1631
            $userMapper = UserMapper::getInstance($this->adapter);
333 www 1632
            $storage = Storage::getInstance($this->config, $this->adapter);
587 stevensc 1633
            $serviceDatetimeFormat = $this->config['leaderslinked.services.datetime'];
1634
 
1635
            $comments = [];
1636
            $records = $capsuleCommentMapper->fetchAllByCapsuleId($capsule->id);
1637
            foreach($records as $record) {
1638
                $user = $userMapper->fetchOne($record->user_id);
1639
                if(!$user) {
1640
                    continue;
1641
                }
1642
 
1643
                $dt = \DateTime::createFromFormat('Y-m-d H:i:s', $record->added_on);
1644
 
1645
                array_push($comments, [
597 stevensc 1646
                    'uuid' => $record->uuid,
587 stevensc 1647
                    'date' => $dt->format($serviceDatetimeFormat),
1648
                    'image' => $storage->getUserImage($user),
1649
                    'fullname' => trim(trim($user->first_name) . ' ' . trim($user->last_name)),
1650
                    'rating' => strval($record->rating),
1651
                    'comment' => $record->comment,
597 stevensc 1652
                    'link_delete' => $record->user_id == $currentUser->id ? $this->url()->fromRoute('microlearning/capsules-comments/delete', ['capsule_id' => $capsule->uuid, 'comment_id' => $record->uuid], ['force_canonical' => true]) : ''
587 stevensc 1653
                ]);
1654
            }
1655
 
1656
            $storage = Storage::getInstance($this->config, $this->adapter);
283 www 1657
            $path = $storage->getPathMicrolearningCapsule();
244 efrain 1658
 
586 stevensc 1659
            $slides = $this->_getSlidesByCapsule($capsule, $storage);
1660
 
161 efrain 1661
            $data = [
586 stevensc 1662
                'uuid'              => $capsule->uuid,
1663
                'name'              => $capsule->name ? $capsule->name : '',
1664
                'description'       => $capsule->description ? $capsule->description : '',
1665
                'image'             => $capsule->image ? $storage->getGenericImage($path, $capsule->uuid, $capsule->image) : '',
1666
                'link_comment_add'  => $this->url()->fromRoute('microlearning/capsules-comments/add', ['capsule_id' => $capsule->uuid], ['force_canonical' => true]),
1667
                'total_comments'    => strval($dataCountAndRatingAverage['total_comments']),
1668
                'total_rating'      => strval($dataCountAndRatingAverage['total_rating']),
587 stevensc 1669
                'comments'          => $comments,
586 stevensc 1670
                'progress'          => $progress,
1671
                'completed'         => $completed,
1672
                'total_slides'      => count($slides),
1673
                'slides'            => $slides,
1674
                'order'             => $capsule->order,
1675
                'added_on'          => $capsule->added_on,
1676
                'updated_on'        => $capsule->updated_on,
161 efrain 1677
            ];
586 stevensc 1678
 
161 efrain 1679
            return new JsonModel([
1680
                'success' => true,
1681
                'data' => $data
1682
            ]);
1683
        }
586 stevensc 1684
 
1685
        return new JsonModel([
1686
            'success' => false,
1687
            'data' => 'ERROR_METHOD_NOT_ALLOWED'
1688
        ]);
161 efrain 1689
    }
1690
 
119 efrain 1691
    public function slidesAction()
1692
    {
1693
        $request = $this->getRequest();
1694
        if($request->isGet()) {
1695
            $currentUserPlugin = $this->plugin('currentUserPlugin');
1696
            $currentUser = $currentUserPlugin->getUser();
1697
 
1698
 
1699
 
1700
            $topic_id = $this->params()->fromRoute('topic_id');
283 www 1701
            $topicMapper = MicrolearningTopicMapper::getInstance($this->adapter);
119 efrain 1702
            $topic = $topicMapper->fetchOneByUuid($topic_id);
1703
 
1704
            if(!$topic) {
1705
                return new JsonModel([
1706
                    'success' => false,
1707
                    'data' => 'ERROR_TOPIC_NOT_FOUND'
1708
                ]);
1709
            }
1710
 
1711
            $accessGrantedIds = $this->getAccessGranted();
1712
 
1713
            if(!in_array($topic->id, $accessGrantedIds->topics)) {
1714
                return new JsonModel([
1715
                    'success' => false,
1716
                    'data' => 'ERROR_YOU_DO_NOT_HAVE_ACCESS_TO_THIS_TOPIC'
1717
                ]);
1718
            }
1719
 
1720
            $capsule_id = $this->params()->fromRoute('capsule_id');
283 www 1721
            $capsuleMapper = MicrolearningCapsuleMapper::getInstance($this->adapter);
119 efrain 1722
            $capsule = $capsuleMapper->fetchOneByUuid($capsule_id);
1723
 
1724
            if(!$capsule) {
1725
                return new JsonModel([
1726
                    'success' => false,
1727
                    'data' => 'ERROR_CAPSULE_NOT_FOUND'
1728
                ]);
1729
            }
1730
 
1731
 
1732
 
1733
            if(!in_array($capsule->id, $accessGrantedIds->capsules)) {
1734
                return new JsonModel([
1735
                    'success' => false,
1736
                    'data' => 'ERROR_YOU_DO_NOT_HAVE_ACCESS_TO_THIS_CAPSULE'
1737
                ]);
1738
            }
1739
 
1740
 
1741
 
1742
            $data = [];
1743
 
283 www 1744
            $quizMapper = MicrolearningQuizMapper::getInstance($this->adapter);
119 efrain 1745
 
283 www 1746
            $slideMapper = MicrolearningSlideMapper::getInstance($this->adapter);
1747
            $userProgressMapper = MicrolearningUserProgressMapper::getInstance($this->adapter);
119 efrain 1748
 
333 www 1749
            $storage = Storage::getInstance($this->config, $this->adapter);
283 www 1750
            $path = $storage->getPathMicrolearningSlide();
119 efrain 1751
 
1752
            $slides = $slideMapper->fetchAllByCompanyIdAndTopicIdAndCapsuleId($capsule->company_id, $capsule->topic_id, $capsule->id);
1753
            foreach($slides as $slide)
1754
            {
1755
 
1756
 
1757
                $userProgress = $userProgressMapper->fetchOneByUserIdAndSlideId($currentUser->id, $slide->id);
1758
                if($userProgress) {
224 efrain 1759
                    $completed =  $userProgress->completed ;
119 efrain 1760
                } else {
1761
                    $completed = 0;
1762
                }
1763
 
235 efrain 1764
 
230 efrain 1765
 
235 efrain 1766
                $link_take_a_test = '';
230 efrain 1767
                if($slide->quiz_id) {
235 efrain 1768
 
283 www 1769
                    $quizMapper = MicrolearningQuizMapper::getInstance($this->adapter);
230 efrain 1770
                    $quiz = $quizMapper->fetchOne($slide->quiz_id);
1771
                    if($quiz) {
1772
                        $quiz_uuid = $quiz->uuid;
235 efrain 1773
                        $quiz_data = $this->getQuiz($slide->quiz_id);
1774
                        $link_take_a_test = $this->url()->fromRoute('microlearning/take-a-test', ['slide_id' => $slide->uuid], ['force_canonical' => true]);
230 efrain 1775
                    }
235 efrain 1776
 
1777
                }
119 efrain 1778
 
1779
 
1780
                array_push($data, [
235 efrain 1781
                    'quiz'                  => $quiz_uuid,
1782
                    'quiz_data'             => $quiz_data,
1783
                    'uuid'                  => $slide->uuid,
1784
                    'name'                  => $slide->name ? $slide->name : '',
1785
                    'description'           => $slide->description ? $slide->description : '',
1786
                    'type'                  => $slide->type,
283 www 1787
                    'background'            => $slide->background ? $storage->getGenericImage($path, $slide->uuid, $slide->background) : '',
1788
                    'file'                  => $slide->file ? $storage->getGenericFile($path, $slide->uuid, $slide->file) : '',
235 efrain 1789
                    'order'                 => $slide->order,
1790
                    'completed'             => $completed,
236 efrain 1791
                    'link_take_a_test'      => $link_take_a_test,
235 efrain 1792
                    'added_on'              => $slide->added_on,
1793
                    'updated_on'            => $slide->updated_on,
119 efrain 1794
                ]);
1795
 
1796
 
1797
 
1798
            }
1799
 
1800
            usort($data, function($a, $b) {
1801
 
1802
                $result =  $a['order'] <=> $b['order'];
1803
                if(0 == $result) {
1804
                    $result = strcasecmp($a['added_on'], $b['added_on']);
1805
                    if(0 == $result) {
1806
                        $result = strcasecmp($a['name'], $b['name']);
1807
                    }
1808
                }
1809
 
1810
                if($result < 0) {
1811
                    return 1;
1812
                } else if($result > 0) {
1813
                    return -1;
1814
                } else  {
1815
                    return  0;
1816
                }
1817
            });
1818
 
1819
 
1820
 
1821
                return new JsonModel([
1822
                    'success' => true,
1823
                    'data' => $data
1824
                ]);
1825
 
1826
        } else {
1827
            return new JsonModel([
1828
                'success' => false,
1829
                'data' => 'ERROR_METHOD_NOT_ALLOWED'
1830
            ]);
1831
        }
1832
    }
1833
 
229 efrain 1834
    private function getQuiz($id)
1835
    {
1836
        $serviceDatetimeFormat = $this->config['leaderslinked.services.datetime'];
1837
 
1838
        $data = [];
1839
 
283 www 1840
        $quizMapper = MicrolearningQuizMapper::getInstance($this->adapter);
229 efrain 1841
        $quiz = $quizMapper->fetchOne($id);
1842
 
1843
        if(!$quiz) {
1844
            return [];
1845
        }
1846
 
1847
        $companyMapper = CompanyMapper::getInstance($this->adapter);
1848
        $company = $companyMapper->fetchOne($quiz->company_id);
1849
 
283 www 1850
        $questionMapper = MicrolearningQuestionMapper::getInstance($this->adapter);
1851
        $answerMapper = MicrolearningAnswerMapper::getInstance($this->adapter);
229 efrain 1852
 
1853
        $record_questions = [];
1854
        $questions = $questionMapper->fetchAllByQuizId($quiz->id);
1855
        foreach($questions as $question)
1856
        {
1857
            $record_answers = [];
1858
 
1859
            $answers = $answerMapper->fetchAllByQuizIdAndQuestionId($question->quiz_id, $question->id);
1860
            foreach($answers as $answer)
1861
            {
1862
                $dtAddedOn = \DateTime::createFromFormat('Y-m-d H:i:s', $answer->added_on);
1863
                $dtUpdatedOn = \DateTime::createFromFormat('Y-m-d H:i:s', $answer->updated_on);
1864
 
1865
                array_push($record_answers, [
1866
                    'uuid' => $answer->uuid,
1867
                    'text' => trim($answer->text),
1868
                    'correct' => $answer->correct ? $answer->correct  : 0 ,
1869
                    'points' => strval(intval($answer->points, 10)),
1870
                    'added_on'  => $dtAddedOn->format($serviceDatetimeFormat),
1871
                    'updated_on'    => $dtUpdatedOn->format($serviceDatetimeFormat),
1872
                ]);
1873
            }
1874
 
1875
            $dtAddedOn = \DateTime::createFromFormat('Y-m-d H:i:s', $question->added_on);
1876
            $dtUpdatedOn = \DateTime::createFromFormat('Y-m-d H:i:s', $question->updated_on);
1877
 
1878
            array_push($record_questions, [
1879
                'uuid'          => $question->uuid,
1880
                'text'          => trim($question->text),
1881
                'type'          => $question->type,
1882
                'maxlength'     => strval($question->maxlength),
1883
                'points'        => strval($question->points),
1884
                'answers'       => $record_answers,
1885
                'added_on'      => $dtAddedOn->format($serviceDatetimeFormat),
1886
                'updated_on'    => $dtUpdatedOn->format($serviceDatetimeFormat),
1887
            ]);
1888
        }
1889
 
1890
        $dtAddedOn = \DateTime::createFromFormat('Y-m-d H:i:s', $quiz->added_on);
1891
        $dtUpdatedOn = \DateTime::createFromFormat('Y-m-d H:i:s', $quiz->updated_on);
1892
 
1893
        array_push($data, [
1894
            'uuid' => $quiz->uuid,
1895
            'name' => $quiz->name,
1896
            'text' => trim($quiz->text ? $quiz->text : ''),
1897
            'failed' => trim($quiz->failed ? $quiz->failed : ''),
1898
            'points' => strval($quiz->points),
1899
            'minimum_points_required' => strval($quiz->minimum_points_required),
1900
            'max_time' => $quiz->max_time ? $quiz->max_time : 5,
1901
            'company_uuid' => $company->uuid,
1902
            'company_name' => $company->name,
1903
            'company_image' => $this->url()->fromRoute('services/storage',['type' => 'company', 'code' => $company->uuid, 'filename' => $company->image], ['force_canonical' => true]),
1904
            'questions'     => $record_questions,
1905
            'added_on'      => $dtAddedOn->format($serviceDatetimeFormat),
1906
            'updated_on'    => $dtUpdatedOn->format($serviceDatetimeFormat),
1907
        ]);
1908
 
1909
        return $data;
1910
 
1911
    }
161 efrain 1912
 
229 efrain 1913
 
161 efrain 1914
    public function getSlideAction()
1915
    {
1916
        $request = $this->getRequest();
1917
        if($request->isGet()) {
1918
            $currentUserPlugin = $this->plugin('currentUserPlugin');
1919
            $currentUser = $currentUserPlugin->getUser();
1920
 
1921
            $id = $this->params()->fromRoute('id');
283 www 1922
            $slideMapper = MicrolearningSlideMapper::getInstance($this->adapter);
161 efrain 1923
            $slide = $slideMapper->fetchOneByUuid($id);
1924
 
1925
            if(!$slide) {
1926
                return new JsonModel([
1927
                    'success' => false,
1928
                    'data' => 'ERROR_SLIDE_NOT_FOUND'
1929
                ]);
1930
            }
1931
 
1932
            $accessGrantedIds = $this->getAccessGranted();
1933
 
1934
 
1935
 
1936
            if(!in_array($slide->capsule_id, $accessGrantedIds->capsules)) {
1937
                return new JsonModel([
1938
                    'success' => false,
1939
                    'data' => 'ERROR_YOU_DO_NOT_HAVE_ACCESS_TO_THIS_CAPSULE'
1940
                ]);
1941
            }
1942
 
283 www 1943
            $slideMapper = MicrolearningSlideMapper::getInstance($this->adapter);
1944
            $userProgressMapper = MicrolearningUserProgressMapper::getInstance($this->adapter);
161 efrain 1945
 
1946
            $userProgress = $userProgressMapper->fetchOneByUserIdAndSlideId($currentUser->id, $slide->id);
1947
            if($userProgress) {
1948
                $completed = $userProgress->completed;
1949
            } else {
1950
                $completed = 0;
1951
            }
235 efrain 1952
 
1953
            $quiz_uuid = '';
1954
            $quiz_data = [];
1955
            $link_take_a_test = '';
1956
            if($slide->quiz_id) {
1957
 
283 www 1958
                $quizMapper = MicrolearningQuizMapper::getInstance($this->adapter);
235 efrain 1959
                $quiz = $quizMapper->fetchOne($slide->quiz_id);
1960
                if($quiz) {
1961
                    $quiz_uuid = $quiz->uuid;
1962
                    $quiz_data = $this->getQuiz($slide->quiz_id);
1963
                    $link_take_a_test = $this->url()->fromRoute('microlearning/take-a-test', ['slide_id' => $slide->uuid], ['force_canonical' => true]);
1964
                }
161 efrain 1965
 
235 efrain 1966
            }
161 efrain 1967
 
333 www 1968
            $storage = Storage::getInstance($this->config, $this->adapter);
283 www 1969
            $path = $storage->getPathMicrolearningSlide();
618 stevensc 1970
 
1971
            $image = $storage->getGenericImage($path, $slide->uuid, $slide->background);
1972
            $file = $storage->getGenericFile($path, $slide->uuid, $slide->file);
161 efrain 1973
 
1974
            $data =[
235 efrain 1975
                'quiz'              => $quiz_uuid,
1976
                'quiz_data'         => $quiz_data,
1977
                'uuid'              => $slide->uuid,
1978
                'name'              => $slide->name ? $slide->name : '',
1979
                'description'       => $slide->description ? $slide->description : '',
1980
                'type'              => $slide->type,
618 stevensc 1981
                'background'        => $image,
1982
                'file'              => $file,
235 efrain 1983
                'order'             => $slide->order,
1984
                'completed'         => $completed,
1985
                'link_take_a_test'  => $link_take_a_test,
1986
                'added_on'          => $slide->added_on,
1987
                'updated_on'        => $slide->updated_on,
161 efrain 1988
            ];
1989
 
1990
            return new JsonModel([
1991
                'success' => true,
1992
                'data' => $data
1993
            ]);
1994
 
1995
        } else {
1996
            return new JsonModel([
1997
                'success' => false,
1998
                'data' => 'ERROR_METHOD_NOT_ALLOWED'
1999
            ]);
2000
        }
2001
    }
2002
 
119 efrain 2003
    public function profileAction()
2004
    {
2005
        $request = $this->getRequest();
2006
        if($request->isGet()) {
2007
            $currentUserPlugin = $this->plugin('currentUserPlugin');
2008
            $currentUser = $currentUserPlugin->getUser();
2009
 
2010
 
2011
            $accessGrantedIds = $this->getAccessGranted();
2012
 
2013
            $companyMapper = CompanyMapper::getInstance($this->adapter);
283 www 2014
            $companyExtendUserMapper = MicrolearningExtendUserMapper::getInstance($this->adapter);
2015
            $companyExtendUserCompanyMapper = MicrolearningExtendUserCompanyMapper::getInstance($this->adapter);
2016
            $companyExtendUserFunctionMapper = MicrolearningExtendUserFunctionMapper::getInstance($this->adapter);
2017
            $companyExtendUserGroupMapper = MicrolearningExtendUserGroupMapper::getInstance($this->adapter);
2018
            $companyExtendUserInstitutionMapper = MicrolearningExtendUserInstitutionMapper::getInstance($this->adapter);
2019
            $companyExtendUserPartnerMapper = MicrolearningExtendUserPartnerMapper::getInstance($this->adapter);
2020
            $companyExtendUserProgramMapper = MicrolearningExtendUserProgramMapper::getInstance($this->adapter);
2021
            $companyExtendUserStudentTypeMapper = MicrolearningExtendUserStudentTypeMapper::getInstance($this->adapter);
2022
            $companyExtendUserSectorMapper = MicrolearningExtendUserSectorMapper::getInstance($this->adapter);
119 efrain 2023
 
333 www 2024
            $storage = Storage::getInstance($this->config, $this->adapter);
283 www 2025
 
119 efrain 2026
 
2027
            $data = [];
2028
            foreach($accessGrantedIds->companies as $company_id)
2029
            {
2030
                $company = $companyMapper->fetchOne($company_id);
2031
                if(!$company) {
2032
                    continue;
2033
                }
2034
 
2035
                $record = [
2036
                    'name' => $company->name,
283 www 2037
                    'image' => $storage->getCompanyImage($company),
119 efrain 2038
                    'details' => [],
2039
                ];
2040
 
2041
                $companyExtendUser = $companyExtendUserMapper->fetchOneByCompanyIdAndUserId($company->id, $currentUser->id);
2042
                if(!$companyExtendUser) {
2043
                    continue;
2044
                }
2045
 
2046
                if($companyExtendUser->extend_company_id) {
2047
 
2048
                    $extendedCompany = $companyExtendUserCompanyMapper->fetchOne($companyExtendUser->company_id);
2049
                    if($extendedCompany) {
2050
                        array_push($record['details'],[
2051
                            'uuid' => $extendedCompany->uuid,
2052
                            'label' => 'LABEL_COMPANY',
2053
                            'value' => $extendedCompany->name
2054
                        ]);
2055
                    }
2056
                }
2057
 
2058
                if($companyExtendUser->extend_function_id) {
2059
                    $extendedFunction = $companyExtendUserFunctionMapper->fetchOne($companyExtendUser->extend_function_id);
2060
                    if($extendedFunction) {
2061
                        array_push($record['details'],[
2062
                            'uuid' => $extendedFunction->uuid,
2063
                            'label' => 'LABEL_FUNCTION',
2064
                            'value' => $extendedFunction->name
2065
                        ]);
2066
                    }
2067
                }
2068
 
2069
                if($companyExtendUser->extend_group_id) {
2070
                    $extendedGroup = $companyExtendUserGroupMapper->fetchOne($companyExtendUser->extend_group_id);
2071
                    if($extendedGroup) {
2072
                        array_push($record['details'],[
2073
                            'uuid' => $extendedGroup->uuid,
2074
                            'label' => 'LABEL_GROUP',
2075
                            'value' => $extendedGroup->name
2076
                        ]);
2077
                    }
2078
                }
2079
 
2080
                if($companyExtendUser->extend_institution_id) {
2081
                    $extendedInstitution= $companyExtendUserInstitutionMapper->fetchOne($companyExtendUser->extend_institution_id);
2082
                    if($extendedInstitution) {
2083
                        array_push($record['details'],[
2084
                            'uuid' => $extendedInstitution->uuid,
2085
                            'label' => 'LABEL_INSTITUTION',
2086
                            'value' => $extendedInstitution->name
2087
                        ]);
2088
                    }
2089
                }
2090
 
2091
                if($companyExtendUser->extend_program_id) {
2092
                    $extendedProgram = $companyExtendUserProgramMapper->fetchOne($companyExtendUser->extend_program_id);
2093
                    if($extendedProgram) {
2094
                        array_push($record['details'],[
2095
                            'uuid' => $extendedProgram->uuid,
2096
                            'label' => 'LABEL_PROGRAM',
2097
                            'value' => $extendedProgram->name
2098
                        ]);
2099
 
2100
                    }
2101
                }
2102
 
2103
                if($companyExtendUser->extend_sector_id) {
2104
                    $extendedSector = $companyExtendUserSectorMapper->fetchOne($companyExtendUser->extend_sector_id);
2105
                    if($extendedSector) {
2106
                        array_push($record['details'],[
2107
                            'uuid' => $extendedSector->uuid,
2108
                            'label' => 'LABEL_SECTOR',
2109
                            'value' => $extendedSector->name
2110
                        ]);
2111
                    }
2112
                }
2113
 
2114
                if($companyExtendUser->extend_partner_id) {
2115
                    $extendedPartner = $companyExtendUserPartnerMapper->fetchOne($companyExtendUser->extend_partner_id);
2116
                    if($extendedPartner) {
2117
                        array_push($record['details'],[
2118
                            'uuid' => $extendedPartner->uuid,
2119
                            'label' => 'LABEL_PARTNER',
2120
                            'value' => $extendedPartner->name
2121
                        ]);
2122
                    }
2123
                }
2124
 
2125
                if($companyExtendUser->extend_student_type_id) {
2126
                    $extendedStudentType = $companyExtendUserStudentTypeMapper->fetchOne($companyExtendUser->extend_student_type_id);
2127
                    if($extendedStudentType) {
2128
                        array_push($record['details'],[
2129
                            'uuid' => $extendedStudentType->uuid,
2130
                            'label' => 'LABEL_TYPE',
2131
                            'value' => $extendedStudentType->name
2132
                        ]);
2133
                    }
2134
                }
2135
 
2136
                array_push($data, $record);
2137
            }
2138
 
2139
            return new JsonModel([
2140
                'success' => true,
2141
                'data' => $data
2142
            ]);
2143
 
2144
        } else {
2145
            return new JsonModel([
2146
                'success' => false,
2147
                'data' => 'ERROR_METHOD_NOT_ALLOWED'
2148
            ]);
2149
        }
2150
    }
590 stevensc 2151
 
2152
    /**
2153
     *
2154
     * @return \Laminas\View\Model\JsonModel
2155
     */
167 efrain 2156
    public function syncAction()
2157
    {
2158
        $request = $this->getRequest();
590 stevensc 2159
        if (!$request->isPost()) {
2160
            return new JsonModel(['success' => false, 'data' => 'ERROR_INVALID_REQUEST']);
2161
        }
167 efrain 2162
 
590 stevensc 2163
        $slide_uuid = $this->params()->fromRoute('slide_uuid');
2164
        $topic_uuid = $this->params()->fromRoute('topic_uuid');
283 www 2165
 
590 stevensc 2166
        if (empty($slide_uuid) || empty($topic_uuid)) {
2167
            return new JsonModel(['success' => false, 'data' => 'ERROR_MISSING_PARAMETERS']);
167 efrain 2168
        }
590 stevensc 2169
 
2170
        $currentUser = $this->plugin('currentUserPlugin')->getUser();
2171
        $user_id = $currentUser->id ?? null;
2172
        if (!$user_id) {
2173
            return new JsonModel(['success' => false, 'data' => 'ERROR_USER_NOT_FOUND']);
2174
        }
2175
 
2176
        $accessGrantedIds = $this->getAccessGranted();
2177
 
2178
        // Obtener Slide
2179
        $slideMapper = MicrolearningSlideMapper::getInstance($this->adapter);
2180
        $slide = $slideMapper->fetchOneByUuid($slide_uuid);
2181
        if (!$slide) {
2182
            return new JsonModel(['success' => false, 'data' => 'ERROR_SLIDE_NOT_FOUND']);
2183
        }
2184
 
2185
        // Obtener Cápsula
2186
        $capsuleMapper = MicrolearningCapsuleMapper::getInstance($this->adapter);
2187
        $capsule = $capsuleMapper->fetchById($slide->capsule_id);
2188
        if (!$capsule || !in_array($capsule->id, $accessGrantedIds->capsules)) {
2189
            return new JsonModel(['success' => false, 'data' => 'ERROR_CAPSULE_ACCESS_DENIED']);
2190
        }
2191
 
2192
        // Obtener Tópico
2193
        $topicMapper = MicrolearningTopicMapper::getInstance($this->adapter);
2194
        $topic = $topicMapper->fetchOneByUuid($topic_uuid);
2195
        if (!$topic || !in_array($topic->id, $accessGrantedIds->topics)) {
2196
            return new JsonModel(['success' => false, 'data' => 'ERROR_TOPIC_ACCESS_DENIED']);
2197
        }
2198
 
2199
        // Validar que la cápsula pertenece al tópico
2200
        $topicCapsuleMapper = MicrolearningTopicCapsuleMapper::getInstance($this->adapter);
2201
        $relation = $topicCapsuleMapper->fetchOneByTopicIdAndCapsuleId($topic->id, $capsule->id);
2202
        if (!$relation) {
2203
            return new JsonModel(['success' => false, 'data' => 'ERROR_CAPSULE_DOES_NOT_BELONG_TO_TOPIC']);
2204
        }
2205
 
2206
        // Marcar slide como visto
2207
        $progressMapper = MicrolearningUserProgressMapper::getInstance($this->adapter);
2208
        $progressMapper->markSlideViewed($user_id, $topic->id, $capsule->id, $slide->id);
2209
 
2210
        $data = 'LABEL_THE_USER_PROGRESS_FOR_THIS_SLIDE_HAS_BEEN_COMPLETED';
2211
 
2212
        // Si vio todos los slides → marcar cápsula como completada
2213
        if ($progressMapper->hasViewedAllSlidesInCapsule($user_id, $capsule->id)) {
2214
            $progressMapper->markCapsuleCompleted($user_id, $topic->id, $capsule->id);
2215
            $data = 'LABEL_THE_USER_PROGRESS_FOR_THIS_CAPSULE_HAS_BEEN_COMPLETED';
2216
        }
2217
 
2218
        // Si completó todas las cápsulas del tópico → marcar tópico como completado
2219
        if ($progressMapper->hasCompletedAllCapsulesInTopic($user_id, $topic->id)) {
2220
            $progressMapper->markTopicCompleted($user_id, $topic->id);
2221
            $data = 'LABEL_THE_USER_PROGRESS_FOR_THIS_TOPIC_HAS_BEEN_COMPLETED';
2222
        }
2223
 
2224
        return new JsonModel(['success' => true, 'data' => $data]);
2225
    }
167 efrain 2226
 
119 efrain 2227
    /**
2228
     *
2229
     * @return \LeadersLinked\Controller\MicrolearningUserAccessGrantedIds
2230
     */
2231
    private function getAccessGranted()
2232
    {
2233
        $currentUserPlugin = $this->plugin('currentUserPlugin');
2234
        $currentUser = $currentUserPlugin->getUser();
2235
 
626 stevensc 2236
        $topicUserMapper = MicrolearningTopicUserMapper::getInstance($this->adapter);
2237
        $now = $topicUserMapper->getDatebaseNow();
119 efrain 2238
 
626 stevensc 2239
        $records = $topicUserMapper->fetchAllActiveByUserId($currentUser->id);
119 efrain 2240
 
2241
        $accessGrantedIds = new MicrolearningUserAccessGrantedIds();
2242
 
2243
        foreach($records as $record)
2244
        {
626 stevensc 2245
            if($record->access != MicrolearningTopicUser::ACCESS_UNLIMITED && $record->access != MicrolearningTopicUser::ACCESS_PAY_PERIOD) {
119 efrain 2246
                continue;
2247
            }
626 stevensc 2248
            if($record->access == MicrolearningTopicUser::ACCESS_PAY_PERIOD) {
119 efrain 2249
                if($now < $record->paid_from || $now > $record->paid_to) {
2250
                    continue;
2251
                }
2252
            }
626 stevensc 2253
 
2254
            // Verificar si la empresa está en la lista de empresas permitidas
119 efrain 2255
            if(!in_array($record->company_id, $accessGrantedIds->companies )) {
2256
                array_push($accessGrantedIds->companies, $record->company_id);
2257
            }
2258
 
626 stevensc 2259
            // Verificar si el tópico está en la lista de tópicos permitidos
119 efrain 2260
            if(!in_array($record->topic_id, $accessGrantedIds->topics )) {
2261
                array_push( $accessGrantedIds->topics, $record->topic_id);
2262
            }
2263
        }
2264
 
2265
        return $accessGrantedIds;
2266
    }
2267
 
590 stevensc 2268
    /**
2269
     * Marks a slide as completed and cascades completion status to capsule and topic if needed
2270
     *
2271
     * @return \Laminas\View\Model\JsonModel
2272
     */
2273
    public function completeSlideAction()
2274
    {
2275
        $request = $this->getRequest();
2276
        if($request->isPost()) {
2277
            $currentUserPlugin = $this->plugin('currentUserPlugin');
2278
            $currentUser = $currentUserPlugin->getUser();
2279
 
2280
            $slide_uuid = $this->params()->fromRoute('slide_uuid');
2281
            $topic_uuid = $this->params()->fromRoute('topic_uuid');
2282
            $capsule_uuid = $this->params()->fromRoute('capsule_uuid');
2283
 
2284
            if(empty($slide_uuid) || empty($topic_uuid) || empty($capsule_uuid)) {
2285
                return new JsonModel([
2286
                    'success' => false,
2287
                    'data' => 'ERROR_INVALID_PARAMETERS'
2288
                ]);
2289
            }
2290
 
2291
            // Get slide
2292
            $slideMapper = MicrolearningSlideMapper::getInstance($this->adapter);
2293
            $slide = $slideMapper->fetchOneByUuid($slide_uuid);
2294
 
2295
            if(!$slide) {
2296
                return new JsonModel([
2297
                    'success' => false,
2298
                    'data' => 'ERROR_SLIDE_NOT_FOUND'
2299
                ]);
2300
            }
2301
 
2302
            // Get capsule
2303
            $capsuleMapper = MicrolearningCapsuleMapper::getInstance($this->adapter);
2304
            $capsule = $capsuleMapper->fetchOneByUuid($capsule_uuid);
2305
 
2306
            if(!$capsule) {
2307
                return new JsonModel([
2308
                    'success' => false,
2309
                    'data' => 'ERROR_CAPSULE_NOT_FOUND'
2310
                ]);
2311
            }
2312
 
2313
            // Get topic
2314
            $topicMapper = MicrolearningTopicMapper::getInstance($this->adapter);
2315
            $topic = $topicMapper->fetchOneByUuid($topic_uuid);
2316
 
2317
            if(!$topic) {
2318
                return new JsonModel([
2319
                    'success' => false,
2320
                    'data' => 'ERROR_TOPIC_NOT_FOUND'
2321
                ]);
2322
            }
2323
 
2324
            // Update slide progress
2325
            $userProgressMapper = MicrolearningUserProgressMapper::getInstance($this->adapter);
2326
            $slideProgress = $userProgressMapper->fetchOneByUserIdAndSlideId($currentUser->id, $slide->id);
2327
            $updated_on = $userProgressMapper->getDatebaseNow();
2328
 
2329
            if(!$slideProgress) {
2330
                $slideProgress = new MicrolearningUserProgress();
2331
                $slideProgress->user_id = $currentUser->id;
2332
                $slideProgress->slide_id = $slide->id;
2333
                $slideProgress->topic_id = $topic->id;
2334
                $slideProgress->capsule_id = $capsule->id;
2335
            }
2336
 
2337
            $slideProgress->completed = 1;
2338
            $slideProgress->updated_on = $updated_on;
2339
 
2340
            if($userProgressMapper->update($slideProgress)) {
2341
                $closeCapsule = false;
2342
                $closeTopic = false;
2343
            }
2344
 
2345
            // Check if capsule is completed
2346
            $capsuleProgress = $userProgressMapper->fetchOneByUserIdAndCapsuleId($currentUser->id, $capsule->id);
2347
 
2348
            $capsuleProgress->total_slides = $slideMapper->fetchTotalCountByCompanyIdAndCapsuleId($capsule->company_id, $capsule->id);
2349
            $capsuleProgress->view_slides = $userProgressMapper->fetchCountAllSlideCompletedByUserIdAndCapsuleId($currentUser->id, $capsule->id);
2350
 
2351
            if($capsuleProgress->total_slides) {
2352
                $capsuleProgress->progress = ($capsuleProgress->view_slides * 100) / $capsuleProgress->total_slides;
2353
                $capsuleProgress->progress = $capsuleProgress->progress > 100 ? 100 : $capsuleProgress->progress;
2354
            }
2355
 
2356
            if(!$userProgressMapper->update($capsuleProgress)) {
2357
                return new JsonModel([
2358
                    'success' => false,
2359
                    'data' => $userProgressMapper->getError()
2360
                ]);
2361
            }
2362
 
2363
            if($capsuleProgress->progress >= 100) {
2364
                $closeCapsule = true;
2365
            }
2366
 
2367
            // Check if topic is completed
2368
            $topicProgress = $userProgressMapper->fetchOneByUserIdAndTopicId($currentUser->id, $topic->id);
2369
            if($topicProgress->completed) {
2370
                $closeTopic = true;
2371
            }
2372
 
2373
 
2374
            // Prepare response
2375
            $data = 'LABEL_THE_USER_PROGRESS_FOR_THIS_SLIDE_HAS_BEEN_COMPLETED';
2376
 
2377
            if($closeCapsule) {
2378
                $data = 'LABEL_THE_USER_PROGRESS_FOR_THIS_CAPSULE_HAS_BEEN_COMPLETED';
2379
            }
2380
 
2381
            if($closeTopic) {
2382
                $data = 'LABEL_THE_USER_PROGRESS_FOR_THIS_TOPIC_HAS_BEEN_COMPLETED';
2383
            }
2384
 
2385
            return new JsonModel([
2386
                'success' => true,
2387
                'data' => $data
2388
            ]);
2389
        }
2390
 
2391
        return new JsonModel([
2392
            'success' => false,
2393
            'data' => 'ERROR_METHOD_NOT_ALLOWED'
2394
        ]);
2395
    }
119 efrain 2396
}