Proyectos de Subversion LeadersLinked - Backend

Rev

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

Rev Autor Línea Nro. Línea
1 www 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;
17184 stevensc 8
use Laminas\View\Model\ViewModel;
17216 stevensc 9
use Laminas\Hydrator\ObjectPropertyHydrator;
1 www 10
use LeadersLinked\Library\Functions;
17002 efrain 11
use LeadersLinked\Mapper\MicrolearningTopicMapper;
17101 stevensc 12
use LeadersLinked\Mapper\MicrolearningCapsuleMapper;
17002 efrain 13
use LeadersLinked\Model\MicrolearningTopic;
14
use LeadersLinked\Form\Microlearning\TopicAddForm;
15
use LeadersLinked\Form\Microlearning\TopicEditForm;
16
use LeadersLinked\Library\Storage;
17107 stevensc 17
use LeadersLinked\Model\MicrolearningTopicCapsule;
18
use LeadersLinked\Mapper\MicrolearningTopicCapsuleMapper;
17178 stevensc 19
use LeadersLinked\Mapper\MicrolearningUserProgressMapper;
17187 stevensc 20
use LeadersLinked\Mapper\QueryMapper;
21
use LeadersLinked\Mapper\UserMapper;
22
use LeadersLinked\Mapper\MicrolearningTopicUserMapper;
23
use LeadersLinked\Model\MicrolearningTopicUser;
1 www 24
 
25
class MicrolearningTopicController extends AbstractActionController
26
{
27
    /**
28
     *
16769 efrain 29
     * @var \Laminas\Db\Adapter\AdapterInterface
1 www 30
     */
31
    private $adapter;
32
 
33
    /**
34
     *
16769 efrain 35
     * @var \LeadersLinked\Cache\CacheInterface
1 www 36
     */
16769 efrain 37
    private $cache;
38
 
39
 
40
    /**
41
     *
42
     * @var \Laminas\Log\LoggerInterface
43
     */
1 www 44
    private $logger;
45
 
46
    /**
47
     *
48
     * @var array
49
     */
50
    private $config;
51
 
16769 efrain 52
 
1 www 53
    /**
54
     *
16769 efrain 55
     * @var \Laminas\Mvc\I18n\Translator
56
     */
57
    private $translator;
58
 
59
 
60
    /**
61
     *
62
     * @param \Laminas\Db\Adapter\AdapterInterface $adapter
63
     * @param \LeadersLinked\Cache\CacheInterface $cache
64
     * @param \Laminas\Log\LoggerInterface LoggerInterface $logger
1 www 65
     * @param array $config
16769 efrain 66
     * @param \Laminas\Mvc\I18n\Translator $translator
1 www 67
     */
16769 efrain 68
    public function __construct($adapter, $cache, $logger, $config, $translator)
1 www 69
    {
16769 efrain 70
        $this->adapter      = $adapter;
71
        $this->cache        = $cache;
72
        $this->logger       = $logger;
73
        $this->config       = $config;
74
        $this->translator   = $translator;
1 www 75
    }
76
 
77
    /**
78
     *
17178 stevensc 79
     * Generación del listado de tópicos
1 www 80
     * {@inheritDoc}
81
     * @see \Laminas\Mvc\Controller\AbstractActionController::indexAction()
17178 stevensc 82
     * @return JsonModel
1 www 83
     */
84
    public function indexAction()
85
    {
17178 stevensc 86
        try {
87
            $request = $this->getRequest();
88
 
89
            $currentUserPlugin = $this->plugin('currentUserPlugin');
90
            $currentCompany = $currentUserPlugin->getCompany();
91
            $currentUser    = $currentUserPlugin->getUser();
1 www 92
 
17178 stevensc 93
            if (!$request->isGet()) {
94
                return $this->createErrorResponse('ERROR_METHOD_NOT_ALLOWED');
95
            }
96
 
97
            if(!$currentCompany) {
98
                return $this->createErrorResponse('ERROR_COMPANY_NOT_FOUND');
99
            }
100
 
101
            if(!$currentUser) {
102
                return $this->createErrorResponse('ERROR_USER_NOT_FOUND');
103
            }
1 www 104
 
17178 stevensc 105
            if($this->isJsonRequest($request)) {
106
                return $this->handleJsonRequest($currentUser, $currentCompany);
107
            }
108
 
109
            return $this->handleHtmlRequest($currentCompany);
110
        } catch (\Exception $e) {
111
            $this->logger->err('Error in indexAction: ' . $e->getMessage());
112
            return $this->createErrorResponse('ERROR_INTERNAL_SERVER_ERROR');
113
        }
114
    }
115
 
116
    /**
117
     *
118
     * Agregar un tópico
119
     * {@inheritDoc}
120
     * @see \Laminas\Mvc\Controller\AbstractActionController::addAction()
121
     * @return JsonModel
122
     */
123
    public function addAction()
124
    {
125
        try {
126
            $request    = $this->getRequest();
127
 
128
            $currentUserPlugin  = $this->plugin('currentUserPlugin');
129
            $currentCompany     = $currentUserPlugin->getCompany();
130
            $currentUser        = $currentUserPlugin->getUser();
131
 
132
            if(!$currentCompany) {
133
                return $this->createErrorResponse('ERROR_COMPANY_NOT_FOUND');
134
            }
135
 
136
            if(!$currentUser) {
137
                return $this->createErrorResponse('ERROR_USER_NOT_FOUND');
138
            }
139
 
140
            if(!$request->isPost() && !$request->isGet()) {
141
                return $this->createErrorResponse('ERROR_METHOD_NOT_ALLOWED');
142
            }
143
 
144
            if($request->isGet()) {
145
                $capsuleMapper = MicrolearningCapsuleMapper::getInstance($this->adapter);
146
                $records =  $capsuleMapper->fetchAllByCompanyId($currentCompany->id);
1 www 147
 
17178 stevensc 148
                $capsules = [];
149
 
150
                foreach($records as $record) {
151
                    array_push($capsules, [
17215 stevensc 152
                        'uuid' => $record->uuid,
17178 stevensc 153
                        'name' => $record->name,
154
                    ]);
1 www 155
                }
17178 stevensc 156
 
157
                return new JsonModel([
158
                    'success' => true,
159
                    'data' => ['capsules' => $capsules]
160
                ]);
1 www 161
            }
17178 stevensc 162
 
163
            if($request->isPost()) {
164
                $form = new TopicAddForm($this->adapter, $currentCompany->id);
165
                $dataPost = array_merge($request->getPost()->toArray(), $request->getFiles()->toArray());
1 www 166
 
17178 stevensc 167
                $form->setData($dataPost);
1 www 168
 
17178 stevensc 169
                if(!$form->isValid()) {
170
                    $messages = [];
171
                    $form_messages = (array) $form->getMessages();
172
 
173
                    foreach($form_messages  as $fieldname => $field_messages)
174
                    {
175
                        $messages[$fieldname] = array_values($field_messages);
176
                    }
177
 
178
                    return new JsonModel([
179
                        'success'   => false,
180
                        'data'   => $messages
181
                    ]);
1 www 182
                }
183
 
17178 stevensc 184
                $dataPost = (array) $form->getData();
185
 
186
                $topic = new MicrolearningTopic();
17223 stevensc 187
                $topic->name = $dataPost['name'];
188
                $topic->description = $dataPost['description'];
189
                $topic->order = $dataPost['order'];
190
                $topic->status = $dataPost['status'];
191
                $topic->privacy = $dataPost['privacy'];
192
                $topic->type = $dataPost['type'];
193
                $topic->cost = $dataPost['cost'];
17178 stevensc 194
                $topic->company_id = $currentCompany->id;
195
                $topic->image = '';
196
                $topic->marketplace = '';
17216 stevensc 197
 
17178 stevensc 198
                $topicMapper = MicrolearningTopicMapper::getInstance($this->adapter);
1 www 199
 
17216 stevensc 200
                // First insert the topic to get the ID and UUID
17178 stevensc 201
                if(!$topicMapper->insert($topic)) {
202
                    return $this->createErrorResponse($topicMapper->getError());
203
                }
1 www 204
 
17216 stevensc 205
                // Get the complete topic with ID and UUID
17178 stevensc 206
                $topic = $topicMapper->fetchOne($topic->id);
17002 efrain 207
 
17216 stevensc 208
                // Now process images with the proper UUID
17214 stevensc 209
                $imageResult = $this->processTopicImages($request, $topic);
210
                if (!$imageResult['success']) {
211
                    return $this->createErrorResponse($imageResult['error']);
17178 stevensc 212
                }
1 www 213
 
17216 stevensc 214
                // Update topic with image filenames if processed
215
                if (!empty($imageResult['image_filename']) || !empty($imageResult['marketplace_filename'])) {
216
                    if (!empty($imageResult['image_filename'])) {
217
                        $topic->image = $imageResult['image_filename'];
218
                    }
219
                    if (!empty($imageResult['marketplace_filename'])) {
220
                        $topic->marketplace = $imageResult['marketplace_filename'];
221
                    }
222
 
223
                    if(!$topicMapper->update($topic)) {
224
                        return $this->createErrorResponse($topicMapper->getError());
225
                    }
226
                }
17002 efrain 227
 
17216 stevensc 228
                // Create capsule relations
17224 stevensc 229
                $result = $this->updateTopicCapsuleRelations($topic, $dataPost['capsule_uuid'], $currentCompany->id, $currentUser);
17216 stevensc 230
                if (!$result['success']) {
231
                    return $this->createErrorResponse($result['error']);
17178 stevensc 232
                }
1 www 233
 
17178 stevensc 234
                $this->logger->info('Se agrego el tópico ' . $topic->name, ['user_id' => $currentUser->id, 'ip' => Functions::getUserIP()]);
1 www 235
 
236
                return new JsonModel([
17178 stevensc 237
                    'success'   => true,
238
                    'data'   => 'LABEL_RECORD_ADDED'
1 www 239
                ]);
240
            }
17178 stevensc 241
        } catch (\Exception $e) {
242
            $this->logger->err('Error in addAction: ' . $e->getMessage());
243
            return $this->createErrorResponse('ERROR_INTERNAL_SERVER_ERROR');
1 www 244
        }
245
    }
17178 stevensc 246
 
247
    /**
248
     *
249
     * Borrar un tópico
250
     * {@inheritDoc}
251
     * @see \Laminas\Mvc\Controller\AbstractActionController::deleteAction()
252
     * @return JsonModel
253
     */
254
    public function deleteAction()
255
    {
256
        try {
257
            $request = $this->getRequest();
1 www 258
 
17178 stevensc 259
            $currentUserPlugin  = $this->plugin('currentUserPlugin');
260
            $currentCompany     = $currentUserPlugin->getCompany();
261
            $currentUser        = $currentUserPlugin->getUser();
262
 
263
            $id   = $this->params()->fromRoute('id');
264
 
265
            if(!$currentCompany) {
266
                return $this->createErrorResponse('ERROR_COMPANY_NOT_FOUND');
267
            }
268
 
269
            if(!$currentUser) {
270
                return $this->createErrorResponse('ERROR_USER_NOT_FOUND');
271
            }
272
 
273
            if(!$request->isPost()) {
274
                return $this->createErrorResponse('ERROR_METHOD_NOT_ALLOWED');
275
            }
276
 
277
            $topicMapper = MicrolearningTopicMapper::getInstance($this->adapter);
278
            $topic = $topicMapper->fetchOneByUuid($id);
1 www 279
 
17178 stevensc 280
            if(!$topic) {
281
                return $this->createErrorResponse('ERROR_TOPIC_NOT_FOUND');
282
            }
283
 
284
            if($topic->company_id != $currentCompany->id) {
285
                return $this->createErrorResponse('ERROR_UNAUTHORIZED');
286
            }
16943 efrain 287
 
17178 stevensc 288
            // Eliminar las relaciones con cápsulas primero
289
            $topicCapsuleMapper = MicrolearningTopicCapsuleMapper::getInstance($this->adapter);
290
 
291
            if(!$topicCapsuleMapper->deleteByTopicId($topic->id)) {
292
                return $this->createErrorResponse($topicCapsuleMapper->getError());
293
            }
17127 stevensc 294
 
17178 stevensc 295
            // Eliminar el progreso de los usuarios
296
            $userProgressMapper = MicrolearningUserProgressMapper::getInstance($this->adapter);
1 www 297
 
17178 stevensc 298
            if(!$userProgressMapper->deleteAllTopicProgressByTopicId($topic->id)) {
299
                return $this->createErrorResponse($userProgressMapper->getError());
17133 stevensc 300
            }
17127 stevensc 301
 
17178 stevensc 302
            // Eliminar archivos de almacenamiento
303
            $storage = Storage::getInstance($this->config, $this->adapter);
304
            $target_path = $storage->getPathMicrolearningTopic();
305
 
306
            if($topic->image) {
307
                if(!$storage->deleteFile($target_path, $topic->uuid, $topic->image)) {
308
                    return $this->createErrorResponse('ERROR_DELETING_FILE');
309
                }
310
            }
17127 stevensc 311
 
17178 stevensc 312
            if(!$topicMapper->delete($topic)) {
313
                return $this->createErrorResponse($topicMapper->getError());
17133 stevensc 314
            }
17127 stevensc 315
 
17178 stevensc 316
            if($topic->marketplace) {
317
                if(!$storage->deleteFile($target_path, $topic->uuid, $topic->marketplace)) {
318
                    return $this->createErrorResponse('ERROR_DELETING_FILE');
319
                }
320
            }
321
 
322
            // Registrar la acción en el log
323
            $this->logger->info('Se borro el tópico : ' . $topic->name, [
324
            'user_id' => $currentUser->id,
325
            'ip' => Functions::getUserIP()
326
            ]);
327
 
328
            return new JsonModel([
17133 stevensc 329
                'success' => true,
17178 stevensc 330
                'data' => 'LABEL_RECORD_DELETED'
331
            ]);
332
        } catch (\Exception $e) {
333
            $this->logger->err('Error in deleteAction: ' . $e->getMessage());
334
            return $this->createErrorResponse('ERROR_INTERNAL_SERVER_ERROR');
17133 stevensc 335
        }
17178 stevensc 336
    }
337
 
338
    /**
339
     *
340
     * Editar un tópico
341
     * {@inheritDoc}
342
     * @see \Laminas\Mvc\Controller\AbstractActionController::editAction()
343
     * @return JsonModel
344
     */
345
    public function editAction()
346
    {
347
        try {
348
            $request = $this->getRequest();
17127 stevensc 349
 
17178 stevensc 350
            $currentUserPlugin  = $this->plugin('currentUserPlugin');
351
            $currentCompany     = $currentUserPlugin->getCompany();
352
            $currentUser        = $currentUserPlugin->getUser();
17133 stevensc 353
 
17178 stevensc 354
            $id   = $this->params()->fromRoute('id');
17133 stevensc 355
 
17178 stevensc 356
            if(!$currentCompany) {
357
                return $this->createErrorResponse('ERROR_COMPANY_NOT_FOUND');
358
            }
359
 
360
            if(!$currentUser) {
361
                return $this->createErrorResponse('ERROR_USER_NOT_FOUND');
362
            }
363
 
364
            if(!$request->isPost() && !$request->isGet()) {
365
                return $this->createErrorResponse('ERROR_METHOD_NOT_ALLOWED');
366
            }
367
 
368
            if($request->isGet()) {
369
                $topicMapper = MicrolearningTopicMapper::getInstance($this->adapter);
370
                $topic = $topicMapper->fetchOneByUuid($id);
371
 
372
                if(!$topic) {
373
                    return $this->createErrorResponse('ERROR_TOPIC_NOT_FOUND');
1 www 374
                }
17178 stevensc 375
 
376
                if($topic->company_id != $currentCompany->id) {
377
                    return $this->createErrorResponse('ERROR_UNAUTHORIZED');
378
                }
1 www 379
 
17178 stevensc 380
                $capsuleMapper = MicrolearningCapsuleMapper::getInstance($this->adapter);
381
                $records =  $capsuleMapper->fetchAllByCompanyId($currentCompany->id);
382
 
383
                $capsules = [];
17214 stevensc 384
                $topicCapsuleMapper = MicrolearningTopicCapsuleMapper::getInstance($this->adapter);
17133 stevensc 385
 
17178 stevensc 386
                foreach($records as $record) {
17211 stevensc 387
                    $topicCapsule = $topicCapsuleMapper->fetchOneByTopicIdAndCapsuleId($topic->id, $record->id);
388
 
389
                    $selected = $topicCapsule ? true : false;
390
 
17178 stevensc 391
                    array_push($capsules, [
17215 stevensc 392
                        'uuid' => $record->uuid,
17178 stevensc 393
                        'name' => $record->name,
17211 stevensc 394
                        'selected' => $selected
17178 stevensc 395
                    ]);
396
                }
17133 stevensc 397
 
17178 stevensc 398
                $storage = Storage::getInstance($this->config, $this->adapter);
399
                $path = $storage->getPathMicrolearningTopic();
400
 
17133 stevensc 401
                $data = [
17178 stevensc 402
                    'success' => true,
403
                    'data' => [
404
                        'capsules' => $capsules,
405
                        'name' => $topic->name,
406
                        'description' => $topic->description,
407
                        'order' => $topic->order,
408
                        'status' => $topic->status,
409
                        'privacy' => $topic->privacy,
410
                        'type' => $topic->type,
411
                        'cost' => $topic->cost,
412
                        'image'=> $storage->getGenericImage($path, $topic->uuid, $topic->image),
413
                        'marketplace'=> $storage->getGenericImage($path, $topic->uuid, $topic->marketplace)
414
                    ]
17133 stevensc 415
                ];
17178 stevensc 416
 
17133 stevensc 417
                return new JsonModel($data);
418
            }
419
 
17178 stevensc 420
            if($request->isPost()) {
421
                $form = new  TopicEditForm($this->adapter, $currentCompany->id, $currentCompany->internal);
422
                $dataPost = array_merge($request->getPost()->toArray(), $request->getFiles()->toArray());
17133 stevensc 423
 
17178 stevensc 424
                $form->setData($dataPost);
425
 
426
                if(!$form->isValid()) {
427
                    $messages = [];
428
                    $form_messages = (array) $form->getMessages();
429
                    foreach($form_messages  as $fieldname => $field_messages)
430
                    {
431
 
432
                        $messages[$fieldname] = array_values($field_messages);
433
                    }
434
 
435
                    return new JsonModel([
436
                        'success'   => false,
437
                        'data'   => $messages
438
                    ]);
17133 stevensc 439
                }
17217 stevensc 440
 
17178 stevensc 441
                $topicMapper = MicrolearningTopicMapper::getInstance($this->adapter);
442
                $topic = $topicMapper->fetchOneByUuid($id);
17217 stevensc 443
 
17178 stevensc 444
                if(!$topic) {
445
                    return $this->createErrorResponse('ERROR_TOPIC_NOT_FOUND');
446
                }
17217 stevensc 447
 
17178 stevensc 448
                if($topic->company_id != $currentCompany->id) {
449
                    return $this->createErrorResponse('ERROR_UNAUTHORIZED');
450
                }
17216 stevensc 451
 
17217 stevensc 452
                $dataPost = (array) $form->getData();
17214 stevensc 453
 
17223 stevensc 454
                $topic->name = $dataPost['name'];
455
                $topic->description = $dataPost['description'];
456
                $topic->order = $dataPost['order'];
457
                $topic->status = $dataPost['status'];
458
                $topic->privacy = $dataPost['privacy'];
459
                $topic->type = $dataPost['type'];
460
                $topic->cost = $dataPost['cost'];
17219 stevensc 461
 
17216 stevensc 462
                // Update basic topic data first
17178 stevensc 463
                if(!$topicMapper->update($topic)) {
464
                    return $this->createErrorResponse($topicMapper->getError());
465
                }
17214 stevensc 466
 
467
                // Process images if uploaded
468
                $imageResult = $this->processTopicImages($request, $topic);
469
                if (!$imageResult['success']) {
470
                    return $this->createErrorResponse($imageResult['error']);
17178 stevensc 471
                }
472
 
17214 stevensc 473
                // Update topic with new image filenames if they were processed
474
                if (!empty($imageResult['image_filename']) || !empty($imageResult['marketplace_filename'])) {
475
                    if (!empty($imageResult['image_filename'])) {
476
                        $topic->image = $imageResult['image_filename'];
17178 stevensc 477
                    }
17214 stevensc 478
                    if (!empty($imageResult['marketplace_filename'])) {
479
                        $topic->marketplace = $imageResult['marketplace_filename'];
17178 stevensc 480
                    }
17214 stevensc 481
 
482
                    if(!$topicMapper->update($topic)) {
483
                        return $this->createErrorResponse($topicMapper->getError());
484
                    }
17178 stevensc 485
                }
17216 stevensc 486
 
487
                // Update capsule relations
17224 stevensc 488
                $result = $this->updateTopicCapsuleRelations($topic, $dataPost['capsule_uuid'], $currentCompany->id, $currentUser);
17216 stevensc 489
                if (!$result['success']) {
490
                    return $this->createErrorResponse($result['error']);
491
                }
17178 stevensc 492
 
493
                $this->logger->info('Se edito el tópico ' . $topic->name, ['user_id' => $currentUser->id, 'ip' => Functions::getUserIP()]);
494
 
17133 stevensc 495
                return new JsonModel([
17178 stevensc 496
                    'success'   => true,
497
                    'data'   => 'LABEL_RECORD_UPDATED'
17093 stevensc 498
                ]);
499
            }
17178 stevensc 500
        } catch (\Exception $e) {
501
            $this->logger->err('Error in editAction: ' . $e->getMessage());
502
            return $this->createErrorResponse('ERROR_INTERNAL_SERVER_ERROR');
17093 stevensc 503
        }
1 www 504
    }
17178 stevensc 505
 
17185 stevensc 506
    /**
507
     *
508
     * Obtener los usuarios de un tópico
509
     * {@inheritDoc}
510
     * @see \Laminas\Mvc\Controller\AbstractActionController::usersAction()
511
     * @return JsonModel
512
     */
513
    public function usersAction()
514
    {
515
        try {
516
            $request = $this->getRequest();
517
 
518
            $currentUserPlugin = $this->plugin('currentUserPlugin');
519
            $currentUser    = $currentUserPlugin->getUser();
520
            $currentCompany = $currentUserPlugin->getCompany();
521
 
522
            if(!$currentCompany) {
523
                return $this->createErrorResponse('ERROR_COMPANY_NOT_FOUND');
524
            }
525
 
526
            if(!$currentUser) {
527
                return $this->createErrorResponse('ERROR_USER_NOT_FOUND');
528
            }
529
 
530
            if(!$request->isGet()) {
531
                return $this->createErrorResponse('ERROR_METHOD_NOT_ALLOWED');
532
            }
533
 
534
            $topic_uuid = $this->params()->fromRoute('topic_uuid');
535
            $type = $this->params()->fromRoute('type');
536
 
537
            $topicMapper = MicrolearningTopicMapper::getInstance($this->adapter);
538
            $topic = $topicMapper->fetchOneByUuid($topic_uuid);
539
            if(!$topic) {
540
                $this->logger->err('Error in usersAction: ' . $topic_uuid);
541
                return $this->createErrorResponse('ERROR_TOPIC_NOT_FOUND');
542
            }
543
 
544
            if($topic->company_id != $currentCompany->id) {
545
                $this->logger->err('Error in usersAction: ' . $topic_uuid);
546
                return $this->createErrorResponse('ERROR_UNAUTHORIZED');
547
            }
548
 
549
            $queryMapper = QueryMapper::getInstance($this->adapter);
550
            $sql = $queryMapper->getSql();
551
            $select = $sql->select();
552
            $select->columns(['access', 'paid_from', 'paid_to', 'added_on']);
553
            $select->from(['tb1' => MicrolearningTopicUserMapper::_TABLE] );
554
            $select->join(['tb2' => UserMapper::_TABLE], 'tb1.user_id = tb2.id', ['uuid', 'first_name', 'last_name', 'email']);
555
            $select->where->equalTo('tb1.company_id', $topic->company_id);
556
            $select->where->equalTo('tb1.topic_id', $topic->id);
557
 
558
            if($type == 'active') {
559
                $now = date('Y-m-d H:i:s');
560
                $select->where->nest->equalTo('access', MicrolearningTopicUser::ACCESS_UNLIMITED)->or->nest()
561
                ->equalTo('access', MicrolearningTopicUser::ACCESS_PAY_PERIOD)
562
                ->and->lessThanOrEqualTo('paid_from', $now)->and->greaterThanOrEqualTo('paid_to', $now )->unnest()->unnest();
563
 
564
            }
565
 
566
            $select->order(['first_name', 'last_name', 'email']);
567
            $records  = $queryMapper->fetchAll($select);
568
 
569
            $items = [];
570
 
571
            foreach($records as $record)
572
            {
573
                switch($record['access'])
574
                {
575
                    case MicrolearningTopicUser::ACCESS_UNLIMITED :
576
                        $details['access'] = 'LABEL_UNLIMIT';
577
                        break;
578
 
579
                    case MicrolearningTopicUser::ACCESS_REVOKE :
580
                        $details['access'] = 'LABEL_REVOKED';
581
                        break;
582
 
583
                    case MicrolearningTopicUser::ACCESS_PAY_PERIOD :
584
                        $dt_paid_from = \DateTime::createFromFormat('Y-m-d', $record['paid_from']);
585
                        $dt_paid_to = \DateTime::createFromFormat('Y-m-d', $record['paid_to']);
586
 
587
                        $details['access'] = 'LABEL_PAY_PERIOD';
588
                        $details['paid_from'] = $dt_paid_from->format('d/m/Y');
589
                        $details['paid_to'] = $dt_paid_to->format('d/m/Y');
590
                        break;
591
 
592
                    case MicrolearningTopicUser::ACCESS_SUPENDED :
593
                        $dt_paid_from = \DateTime::createFromFormat('Y-m-d', $record['paid_from']);
594
                        $dt_paid_to = \DateTime::createFromFormat('Y-m-d', $record['paid_to']);
595
 
596
                        $details['access'] = 'LABEL_SUSPENDED';
597
                        $details['paid_from'] = $dt_paid_from->format('d/m/Y');
598
                        $details['paid_to'] = $dt_paid_to->format('d/m/Y');
599
                        break;
600
 
601
                    case MicrolearningTopicUser::ACCESS_CANCELLED :
602
                        $dt_paid_from = \DateTime::createFromFormat('Y-m-d', $record['paid_from']);
603
                        $dt_paid_to = \DateTime::createFromFormat('Y-m-d', $record['paid_to']);
604
 
605
                        $details['access'] = 'LABEL_CANCELLED';
606
                        $details['paid_from'] = $dt_paid_from->format('d/m/Y');
607
                        $details['paid_to'] = $dt_paid_to->format('d/m/Y');
608
                        break;
609
                }
610
 
611
 
612
                $item = [
613
                    'first_name' => $record['first_name'],
614
                    'last_name' => $record['last_name'],
615
                    'email' => $record['email'],
616
                    'details' => $details,
617
                ];
618
 
619
                array_push($items, $item);
620
            }
621
 
622
            return new JsonModel([
623
                'success' => true,
624
                'data' => [
625
                    'topic' => $topic->name,
626
                    'items' => $items,
627
                ]
628
            ]);
629
        } catch (\Exception $e) {
630
            $this->logger->err('Error in usersAction: ' . $e->getMessage());
631
            return $this->createErrorResponse('ERROR_INTERNAL_SERVER_ERROR');
632
        }
633
    }
634
 
17178 stevensc 635
     /**
636
     * Check if request is JSON
637
     * @param \Laminas\Http\Request $request
638
     * @return bool
1 www 639
     */
17178 stevensc 640
    private function isJsonRequest($request)
1 www 641
    {
17178 stevensc 642
        $headers = $request->getHeaders();
643
        if (!$headers->has('Accept')) {
644
            return false;
17133 stevensc 645
        }
646
 
17178 stevensc 647
        $accept = $headers->get('Accept');
648
        $prioritized = $accept->getPrioritized();
17133 stevensc 649
 
17178 stevensc 650
        foreach ($prioritized as $value) {
651
            if (strpos(trim($value->getRaw()), 'json') !== false) {
652
                return true;
653
            }
1 www 654
        }
655
 
17178 stevensc 656
        return false;
657
    }
1 www 658
 
17178 stevensc 659
    /**
660
     * Handle JSON request for datatable
661
     * @param \LeadersLinked\Model\User $currentUser
662
     * @param \LeadersLinked\Model\Company $currentCompany
663
     * @return \Laminas\View\Model\JsonModel
664
     */
665
    private function handleJsonRequest($currentUser, $currentCompany)
666
    {
667
        try {
668
            $search = $this->params()->fromQuery('search', []);
669
            $search = empty($search['value']) ? '' : Functions::sanitizeFilterString($search['value']);
670
 
671
            $recordsPerPage = intval($this->params()->fromQuery('length', 10), 10);
672
            $page = (intval($this->params()->fromQuery('start', 1), 10) / $recordsPerPage) + 1;
673
 
674
            $order = $this->params()->fromQuery('order', []);
675
            $orderField = empty($order[0]['column']) ? 99 : intval($order[0]['column'], 10);
676
            $orderDirection = empty($order[0]['dir']) ? 'ASC' : strtoupper(Functions::sanitizeFilterString($order[0]['dir']));
677
 
678
            $fields = ['name'];
679
            $orderField = isset($fields[$orderField]) ? $fields[$orderField] : 'name';
680
 
681
            if (!in_array($orderDirection, ['ASC', 'DESC'])) {
682
                $orderDirection = 'ASC';
683
            }
684
 
685
            $acl = $this->getEvent()->getViewModel()->getVariable('acl');
686
            $permissions = $this->getUserPermissions($acl, $currentUser);
687
 
688
            $topicMapper = MicrolearningTopicMapper::getInstance($this->adapter);
689
            $paginator = $topicMapper->fetchAllDataTableByCompanyId(
690
                $currentCompany->id,
691
                $search,
692
                $page,
693
                $recordsPerPage,
694
                $orderField,
695
                $orderDirection
696
            );
697
 
698
            $items = $this->prepareTopicItems($paginator->getCurrentItems(), $currentCompany, $permissions);
699
 
700
            $response = [
701
                'success' => true,
702
                'data' => [
703
                    'link_add' => $permissions['allowAdd'] ? $this->url()->fromRoute('microlearning/content/topics/add') : '',
704
                    'items' => $items,
705
                    'total' => $paginator->getTotalItemCount(),
706
                ]
707
            ];
708
 
709
            return new JsonModel($response);
710
 
711
        } catch (\Exception $e) {
712
            $this->logger->err('Error in handleJsonRequest: ' . $e->getMessage());
713
            return $this->createErrorResponse('ERROR_INTERNAL_SERVER_ERROR');
17133 stevensc 714
        }
17178 stevensc 715
    }
17133 stevensc 716
 
17178 stevensc 717
    /**
718
     * Handle HTML request for view
719
     * @param \LeadersLinked\Model\Company $currentCompany
720
     * @return \Laminas\View\Model\ViewModel
721
     */
722
    private function handleHtmlRequest($currentCompany)
723
    {
724
        $imageSize = $this->config['leaderslinked.image_sizes.microlearning_image_upload'];
725
        $marketplaceSize = $this->config['leaderslinked.image_sizes.marketplace'];
1 www 726
 
17178 stevensc 727
        $formAdd = new TopicAddForm($this->adapter, $currentCompany->id, $currentCompany->internal);
728
        $formEdit = new TopicEditForm($this->adapter, $currentCompany->id, $currentCompany->internal);
17002 efrain 729
 
17178 stevensc 730
        $this->layout()->setTemplate('layout/layout-backend.phtml');
731
        $viewModel = new ViewModel();
732
        $viewModel->setTemplate('leaders-linked/microlearning-topics/index.phtml');
733
        $viewModel->setVariables([
734
            'formAdd' => $formAdd,
735
            'formEdit' => $formEdit,
736
            'company_uuid' => $currentCompany->uuid,
737
            'image_size' => $imageSize,
738
            'marketplace_size' => $marketplaceSize,
17133 stevensc 739
        ]);
1 www 740
 
17178 stevensc 741
        return $viewModel;
742
    }
743
 
744
    /**
745
     * Get user permissions for topic actions
746
     * @param \Laminas\Permissions\Acl\Acl $acl
747
     * @param \LeadersLinked\Model\User $currentUser
748
     * @return array
749
     */
750
    private function getUserPermissions($acl, $currentUser)
751
    {
752
        return [
753
            'allowAdd' => $acl->isAllowed($currentUser->usertype_id, 'microlearning/content/topics/add'),
754
            'allowEdit' => $acl->isAllowed($currentUser->usertype_id, 'microlearning/content/topics/edit'),
755
            'allowDelete' => $acl->isAllowed($currentUser->usertype_id, 'microlearning/content/topics/delete'),
756
            'allowUsers' => $acl->isAllowed($currentUser->usertype_id, 'microlearning/content/topics/users')
757
        ];
758
    }
759
 
760
    /**
761
     * Create error response
762
     * @param string $message
763
     * @return \Laminas\View\Model\JsonModel
764
     */
765
    private function createErrorResponse($message)
766
    {
17133 stevensc 767
        return new JsonModel([
17178 stevensc 768
            'success' => false,
769
            'data' => $message
17133 stevensc 770
        ]);
1 www 771
    }
772
 
17178 stevensc 773
     /**
774
     * Prepare topic items for datatable
775
     * @param array $records
776
     * @param \LeadersLinked\Model\Company $currentCompany
777
     * @param array $permissions
778
     * @return array
779
     */
780
    private function prepareTopicItems($records, $currentCompany, $permissions)
1 www 781
    {
17178 stevensc 782
        $items = [];
783
        $microlearningTopicUserMapper = MicrolearningTopicUserMapper::getInstance($this->adapter);
784
        $storage = Storage::getInstance($this->config, $this->adapter);
785
        $path = $storage->getPathMicrolearningTopic();
17109 stevensc 786
 
17178 stevensc 787
        foreach ($records as $record) {
788
            $totalUsers = $microlearningTopicUserMapper->fetchCountUsersByCompanyIdAndTopicId($currentCompany->id, $record->id);
789
            $totalUsersActive = $microlearningTopicUserMapper->fetchCountUsersActiveByCompanyIdAndTopicId($currentCompany->id, $record->id);
790
 
791
            $status = $this->getTopicStatus($record->status);
792
            $privacy = $this->getTopicPrivacy($record->privacy);
793
            $type = $this->getTopicType($record->type);
794
 
795
            $items[] = [
796
                'name' => $record->name,
797
                'details' => [
798
                    'status' => $status,
799
                    'privacy' => $privacy,
800
                    'type' => $type,
801
                    'cost' => $record->cost,
802
                    'total_users' => $totalUsers,
803
                    'total_users_active' => $totalUsersActive,
804
                ],
805
                'images' => [
806
                    'image' => $storage->getGenericImage($path, $record->uuid, $record->image),
17195 stevensc 807
                    'marketplace' => $storage->getGenericImage($path, $record->uuid, $record->marketplace)
17178 stevensc 808
                ],
809
                'actions' => $this->prepareTopicActions($record, $permissions, $totalUsers, $totalUsersActive)
810
            ];
1 www 811
        }
17178 stevensc 812
 
813
        return $items;
814
    }
815
 
816
        /**
817
     * Get topic status label
818
     * @param int $status
819
     * @return string
820
     */
821
    private function getTopicStatus($status)
822
    {
823
        switch ($status) {
824
            case MicrolearningTopic::STATUS_ACTIVE:
825
                return 'LABEL_ACTIVE';
826
            case MicrolearningTopic::STATUS_INACTIVE:
827
                return 'LABEL_INACTIVE';
828
            default:
829
                return '';
1 www 830
        }
17178 stevensc 831
    }
832
 
833
    /**
834
     * Get topic privacy label
835
     * @param int $privacy
836
     * @return string
837
     */
838
    private function getTopicPrivacy($privacy)
839
    {
840
        switch ($privacy) {
841
            case MicrolearningTopic::PRIVACY_PUBLIC:
842
                return 'LABEL_PUBLIC';
843
            case MicrolearningTopic::PRIVACY_PRIVATE:
844
                return 'LABEL_PRIVATE';
845
            default:
846
                return '';
1 www 847
        }
848
    }
17178 stevensc 849
 
850
    /**
851
     * Get topic type label
852
     * @param int $type
853
     * @return string
854
     */
855
    private function getTopicType($type)
856
    {
857
        switch ($type) {
858
            case MicrolearningTopic::TYPE_FREE:
859
                return 'LABEL_FREE';
860
            case MicrolearningTopic::TYPE_PRIVATE:
861
                return 'LABEL_PRIVATE';
862
            case MicrolearningTopic::TYPE_SELLING:
863
                return 'LABEL_SELLING';
864
            default:
865
                return '';
866
        }
867
    }
868
 
869
     /**
870
     * Prepare topic actions
871
     * @param \LeadersLinked\Model\MicrolearningTopic $record
872
     * @param array $permissions
873
     * @param int $totalUsers
874
     * @param int $totalUsersActive
875
     * @return array
876
     */
877
    private function prepareTopicActions($record, $permissions, $totalUsers, $totalUsersActive)
878
    {
17188 stevensc 879
        $editDeleteParams = ['id' => $record->uuid];
17178 stevensc 880
 
881
        return [
17188 stevensc 882
            'link_edit' => $permissions['allowEdit'] ? $this->url()->fromRoute('microlearning/content/topics/edit', $editDeleteParams) : '',
883
            'link_delete' => $permissions['allowDelete'] ? $this->url()->fromRoute('microlearning/content/topics/delete', $editDeleteParams) : '',
17178 stevensc 884
            'link_total_users' => $permissions['allowUsers'] && $totalUsers ?
885
                $this->url()->fromRoute('microlearning/content/topics/users', [
886
                    'topic_uuid' => $record->uuid,
887
                    'type' => 'all'
888
                ]) : '',
889
            'link_total_users_actives' => $permissions['allowUsers'] && $totalUsersActive ?
890
                $this->url()->fromRoute('microlearning/content/topics/users', [
891
                    'topic_uuid' => $record->uuid,
892
                    'type' => 'active'
893
                ]) : ''
894
        ];
895
    }
17214 stevensc 896
 
897
    /**
898
     * Update topic capsule relations
899
     * @param \LeadersLinked\Model\MicrolearningTopic $topic
900
     * @param array $capsuleUuids
901
     * @param int $companyId
17224 stevensc 902
     * @param \LeadersLinked\Model\User $currentUser
17214 stevensc 903
     * @return array
904
     */
17224 stevensc 905
    private function updateTopicCapsuleRelations($topic, $capsuleUuids, $companyId, $currentUser)
17214 stevensc 906
    {
907
        try {
17224 stevensc 908
            // Ensure capsuleUuids is an array
909
            if (!is_array($capsuleUuids)) {
910
                $capsuleUuids = [];
911
            }
912
 
17214 stevensc 913
            $topicCapsuleMapper = MicrolearningTopicCapsuleMapper::getInstance($this->adapter);
914
            $topicCapsuleMapper->deleteByTopicId($topic->id);
915
 
916
            $capsuleMapper = MicrolearningCapsuleMapper::getInstance($this->adapter);
917
            foreach ($capsuleUuids as $capsuleUuid) {
918
                $capsule = $capsuleMapper->fetchOneByUuid($capsuleUuid);
919
 
920
                if ($capsule) {
921
                    $topicCapsule = new MicrolearningTopicCapsule();
922
                    $topicCapsule->topic_id = $topic->id;
923
                    $topicCapsule->capsule_id = $capsule->id;
924
                    $topicCapsule->company_id = $companyId;
925
                    $topicCapsuleMapper->insert($topicCapsule);
926
                }
927
            }
17224 stevensc 928
 
929
            $this->logger->info('Se actualizo la relacion de cápsulas del tópico ' . $topic->name, ['user_id' => $currentUser->id, 'ip' => Functions::getUserIP()]);
17214 stevensc 930
            return ['success' => true];
931
        } catch (\Exception $e) {
17224 stevensc 932
            $this->logger->err('Error in updateTopicCapsuleRelations: ' . $e->getMessage());
17214 stevensc 933
            return ['success' => false, 'error' => $e->getMessage()];
934
        }
935
    }
936
 
937
    /**
938
     * Process topic images
939
     * @param \Laminas\Http\Request $request
940
     * @param \LeadersLinked\Model\MicrolearningTopic $topic
941
     * @return array
942
     */
943
    private function processTopicImages($request, $topic)
944
    {
945
        try {
946
            $storage = Storage::getInstance($this->config, $this->adapter);
947
            $target_path = $storage->getPathMicrolearningTopic();
948
            $storage->setFiles($request->getFiles()->toArray());
949
 
950
            $result = [
951
                'success' => true,
952
                'image_filename' => '',
953
                'marketplace_filename' => ''
954
            ];
955
 
956
            // Process main image if uploaded
17219 stevensc 957
            if ($storage->setCurrentFilename('image')) {
17214 stevensc 958
                $target_size = $this->config['leaderslinked.image_sizes.microlearning_image_size'];
959
                list($target_width, $target_height) = explode('x', $target_size);
960
 
961
                $image_source_filename = $storage->getTmpFilename();
962
                $image_filename = 'topic-' . uniqid() . '.png';
963
                $image_target_filename = $storage->composePathToFilename(
964
                    Storage::TYPE_MICROLEARNING_TOPIC,
965
                    $topic->uuid,
966
                    $image_filename
967
                );
968
 
969
                if (!$storage->uploadImageCrop($image_source_filename, $image_target_filename, $target_width, $target_height)) {
970
                    return ['success' => false, 'error' => 'ERROR_UPLOAD_IMAGE'];
971
                }
972
 
973
                // Delete old image if exists
974
                if ($topic->image) {
975
                    $storage->deleteFile($target_path, $topic->uuid, $topic->image);
976
                }
977
 
978
                $result['image_filename'] = $image_filename;
979
            }
980
 
981
            // Process marketplace image if uploaded
982
            if ($storage->setCurrentFilename('marketplace')) {
983
                $target_size = $this->config['leaderslinked.image_sizes.microlearning_image_size'];
984
                list($target_width, $target_height) = explode('x', $target_size);
985
 
986
                $marketplace_source_filename = $storage->getTmpFilename();
987
                $marketplace_filename = 'marketplace-' . uniqid() . '.png';
988
                $marketplace_target_filename = $storage->composePathToFilename(
989
                    Storage::TYPE_MICROLEARNING_TOPIC,
990
                    $topic->uuid,
991
                    $marketplace_filename
992
                );
993
 
994
                if (!$storage->uploadImageCrop($marketplace_source_filename, $marketplace_target_filename, $target_width, $target_height)) {
995
                    return ['success' => false, 'error' => 'ERROR_UPLOAD_IMAGE'];
996
                }
997
 
998
                // Delete old marketplace image if exists
999
                if ($topic->marketplace) {
1000
                    $storage->deleteFile($target_path, $topic->uuid, $topic->marketplace);
1001
                }
1002
 
1003
                $result['marketplace_filename'] = $marketplace_filename;
1004
            }
1005
 
1006
            return $result;
1007
        } catch (\Exception $e) {
1008
            return ['success' => false, 'error' => $e->getMessage()];
1009
        }
1010
    }
1 www 1011
}