Proyectos de Subversion LeadersLinked - Services

Rev

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