Proyectos de Subversion LeadersLinked - Backend

Rev

Rev 17224 | Rev 17226 | 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
                }
17225 stevensc 466
 
467
                $this->logger->info('Se actualizo el tópico ' . $topic->name, ['user_id' => $currentUser->id, 'ip' => Functions::getUserIP()]);
17214 stevensc 468
 
469
                // Process images if uploaded
470
                $imageResult = $this->processTopicImages($request, $topic);
471
                if (!$imageResult['success']) {
472
                    return $this->createErrorResponse($imageResult['error']);
17178 stevensc 473
                }
474
 
17214 stevensc 475
                // Update topic with new image filenames if they were processed
476
                if (!empty($imageResult['image_filename']) || !empty($imageResult['marketplace_filename'])) {
477
                    if (!empty($imageResult['image_filename'])) {
478
                        $topic->image = $imageResult['image_filename'];
17178 stevensc 479
                    }
17214 stevensc 480
                    if (!empty($imageResult['marketplace_filename'])) {
481
                        $topic->marketplace = $imageResult['marketplace_filename'];
17178 stevensc 482
                    }
17214 stevensc 483
 
484
                    if(!$topicMapper->update($topic)) {
485
                        return $this->createErrorResponse($topicMapper->getError());
486
                    }
17225 stevensc 487
 
488
                    $this->logger->info('Se actualizo la imagen del tópico ' . $topic->name, ['user_id' => $currentUser->id, 'ip' => Functions::getUserIP()]);
17178 stevensc 489
                }
17216 stevensc 490
 
491
                // Update capsule relations
17224 stevensc 492
                $result = $this->updateTopicCapsuleRelations($topic, $dataPost['capsule_uuid'], $currentCompany->id, $currentUser);
17216 stevensc 493
                if (!$result['success']) {
494
                    return $this->createErrorResponse($result['error']);
495
                }
17178 stevensc 496
 
497
                $this->logger->info('Se edito el tópico ' . $topic->name, ['user_id' => $currentUser->id, 'ip' => Functions::getUserIP()]);
498
 
17133 stevensc 499
                return new JsonModel([
17178 stevensc 500
                    'success'   => true,
501
                    'data'   => 'LABEL_RECORD_UPDATED'
17093 stevensc 502
                ]);
503
            }
17178 stevensc 504
        } catch (\Exception $e) {
505
            $this->logger->err('Error in editAction: ' . $e->getMessage());
506
            return $this->createErrorResponse('ERROR_INTERNAL_SERVER_ERROR');
17093 stevensc 507
        }
1 www 508
    }
17178 stevensc 509
 
17185 stevensc 510
    /**
511
     *
512
     * Obtener los usuarios de un tópico
513
     * {@inheritDoc}
514
     * @see \Laminas\Mvc\Controller\AbstractActionController::usersAction()
515
     * @return JsonModel
516
     */
517
    public function usersAction()
518
    {
519
        try {
520
            $request = $this->getRequest();
521
 
522
            $currentUserPlugin = $this->plugin('currentUserPlugin');
523
            $currentUser    = $currentUserPlugin->getUser();
524
            $currentCompany = $currentUserPlugin->getCompany();
525
 
526
            if(!$currentCompany) {
527
                return $this->createErrorResponse('ERROR_COMPANY_NOT_FOUND');
528
            }
529
 
530
            if(!$currentUser) {
531
                return $this->createErrorResponse('ERROR_USER_NOT_FOUND');
532
            }
533
 
534
            if(!$request->isGet()) {
535
                return $this->createErrorResponse('ERROR_METHOD_NOT_ALLOWED');
536
            }
537
 
538
            $topic_uuid = $this->params()->fromRoute('topic_uuid');
539
            $type = $this->params()->fromRoute('type');
540
 
541
            $topicMapper = MicrolearningTopicMapper::getInstance($this->adapter);
542
            $topic = $topicMapper->fetchOneByUuid($topic_uuid);
543
            if(!$topic) {
544
                $this->logger->err('Error in usersAction: ' . $topic_uuid);
545
                return $this->createErrorResponse('ERROR_TOPIC_NOT_FOUND');
546
            }
547
 
548
            if($topic->company_id != $currentCompany->id) {
549
                $this->logger->err('Error in usersAction: ' . $topic_uuid);
550
                return $this->createErrorResponse('ERROR_UNAUTHORIZED');
551
            }
552
 
553
            $queryMapper = QueryMapper::getInstance($this->adapter);
554
            $sql = $queryMapper->getSql();
555
            $select = $sql->select();
556
            $select->columns(['access', 'paid_from', 'paid_to', 'added_on']);
557
            $select->from(['tb1' => MicrolearningTopicUserMapper::_TABLE] );
558
            $select->join(['tb2' => UserMapper::_TABLE], 'tb1.user_id = tb2.id', ['uuid', 'first_name', 'last_name', 'email']);
559
            $select->where->equalTo('tb1.company_id', $topic->company_id);
560
            $select->where->equalTo('tb1.topic_id', $topic->id);
561
 
562
            if($type == 'active') {
563
                $now = date('Y-m-d H:i:s');
564
                $select->where->nest->equalTo('access', MicrolearningTopicUser::ACCESS_UNLIMITED)->or->nest()
565
                ->equalTo('access', MicrolearningTopicUser::ACCESS_PAY_PERIOD)
566
                ->and->lessThanOrEqualTo('paid_from', $now)->and->greaterThanOrEqualTo('paid_to', $now )->unnest()->unnest();
567
 
568
            }
569
 
570
            $select->order(['first_name', 'last_name', 'email']);
571
            $records  = $queryMapper->fetchAll($select);
572
 
573
            $items = [];
574
 
575
            foreach($records as $record)
576
            {
577
                switch($record['access'])
578
                {
579
                    case MicrolearningTopicUser::ACCESS_UNLIMITED :
580
                        $details['access'] = 'LABEL_UNLIMIT';
581
                        break;
582
 
583
                    case MicrolearningTopicUser::ACCESS_REVOKE :
584
                        $details['access'] = 'LABEL_REVOKED';
585
                        break;
586
 
587
                    case MicrolearningTopicUser::ACCESS_PAY_PERIOD :
588
                        $dt_paid_from = \DateTime::createFromFormat('Y-m-d', $record['paid_from']);
589
                        $dt_paid_to = \DateTime::createFromFormat('Y-m-d', $record['paid_to']);
590
 
591
                        $details['access'] = 'LABEL_PAY_PERIOD';
592
                        $details['paid_from'] = $dt_paid_from->format('d/m/Y');
593
                        $details['paid_to'] = $dt_paid_to->format('d/m/Y');
594
                        break;
595
 
596
                    case MicrolearningTopicUser::ACCESS_SUPENDED :
597
                        $dt_paid_from = \DateTime::createFromFormat('Y-m-d', $record['paid_from']);
598
                        $dt_paid_to = \DateTime::createFromFormat('Y-m-d', $record['paid_to']);
599
 
600
                        $details['access'] = 'LABEL_SUSPENDED';
601
                        $details['paid_from'] = $dt_paid_from->format('d/m/Y');
602
                        $details['paid_to'] = $dt_paid_to->format('d/m/Y');
603
                        break;
604
 
605
                    case MicrolearningTopicUser::ACCESS_CANCELLED :
606
                        $dt_paid_from = \DateTime::createFromFormat('Y-m-d', $record['paid_from']);
607
                        $dt_paid_to = \DateTime::createFromFormat('Y-m-d', $record['paid_to']);
608
 
609
                        $details['access'] = 'LABEL_CANCELLED';
610
                        $details['paid_from'] = $dt_paid_from->format('d/m/Y');
611
                        $details['paid_to'] = $dt_paid_to->format('d/m/Y');
612
                        break;
613
                }
614
 
615
 
616
                $item = [
617
                    'first_name' => $record['first_name'],
618
                    'last_name' => $record['last_name'],
619
                    'email' => $record['email'],
620
                    'details' => $details,
621
                ];
622
 
623
                array_push($items, $item);
624
            }
625
 
626
            return new JsonModel([
627
                'success' => true,
628
                'data' => [
629
                    'topic' => $topic->name,
630
                    'items' => $items,
631
                ]
632
            ]);
633
        } catch (\Exception $e) {
634
            $this->logger->err('Error in usersAction: ' . $e->getMessage());
635
            return $this->createErrorResponse('ERROR_INTERNAL_SERVER_ERROR');
636
        }
637
    }
638
 
17178 stevensc 639
     /**
640
     * Check if request is JSON
641
     * @param \Laminas\Http\Request $request
642
     * @return bool
1 www 643
     */
17178 stevensc 644
    private function isJsonRequest($request)
1 www 645
    {
17178 stevensc 646
        $headers = $request->getHeaders();
647
        if (!$headers->has('Accept')) {
648
            return false;
17133 stevensc 649
        }
650
 
17178 stevensc 651
        $accept = $headers->get('Accept');
652
        $prioritized = $accept->getPrioritized();
17133 stevensc 653
 
17178 stevensc 654
        foreach ($prioritized as $value) {
655
            if (strpos(trim($value->getRaw()), 'json') !== false) {
656
                return true;
657
            }
1 www 658
        }
659
 
17178 stevensc 660
        return false;
661
    }
1 www 662
 
17178 stevensc 663
    /**
664
     * Handle JSON request for datatable
665
     * @param \LeadersLinked\Model\User $currentUser
666
     * @param \LeadersLinked\Model\Company $currentCompany
667
     * @return \Laminas\View\Model\JsonModel
668
     */
669
    private function handleJsonRequest($currentUser, $currentCompany)
670
    {
671
        try {
672
            $search = $this->params()->fromQuery('search', []);
673
            $search = empty($search['value']) ? '' : Functions::sanitizeFilterString($search['value']);
674
 
675
            $recordsPerPage = intval($this->params()->fromQuery('length', 10), 10);
676
            $page = (intval($this->params()->fromQuery('start', 1), 10) / $recordsPerPage) + 1;
677
 
678
            $order = $this->params()->fromQuery('order', []);
679
            $orderField = empty($order[0]['column']) ? 99 : intval($order[0]['column'], 10);
680
            $orderDirection = empty($order[0]['dir']) ? 'ASC' : strtoupper(Functions::sanitizeFilterString($order[0]['dir']));
681
 
682
            $fields = ['name'];
683
            $orderField = isset($fields[$orderField]) ? $fields[$orderField] : 'name';
684
 
685
            if (!in_array($orderDirection, ['ASC', 'DESC'])) {
686
                $orderDirection = 'ASC';
687
            }
688
 
689
            $acl = $this->getEvent()->getViewModel()->getVariable('acl');
690
            $permissions = $this->getUserPermissions($acl, $currentUser);
691
 
692
            $topicMapper = MicrolearningTopicMapper::getInstance($this->adapter);
693
            $paginator = $topicMapper->fetchAllDataTableByCompanyId(
694
                $currentCompany->id,
695
                $search,
696
                $page,
697
                $recordsPerPage,
698
                $orderField,
699
                $orderDirection
700
            );
701
 
702
            $items = $this->prepareTopicItems($paginator->getCurrentItems(), $currentCompany, $permissions);
703
 
704
            $response = [
705
                'success' => true,
706
                'data' => [
707
                    'link_add' => $permissions['allowAdd'] ? $this->url()->fromRoute('microlearning/content/topics/add') : '',
708
                    'items' => $items,
709
                    'total' => $paginator->getTotalItemCount(),
710
                ]
711
            ];
712
 
713
            return new JsonModel($response);
714
 
715
        } catch (\Exception $e) {
716
            $this->logger->err('Error in handleJsonRequest: ' . $e->getMessage());
717
            return $this->createErrorResponse('ERROR_INTERNAL_SERVER_ERROR');
17133 stevensc 718
        }
17178 stevensc 719
    }
17133 stevensc 720
 
17178 stevensc 721
    /**
722
     * Handle HTML request for view
723
     * @param \LeadersLinked\Model\Company $currentCompany
724
     * @return \Laminas\View\Model\ViewModel
725
     */
726
    private function handleHtmlRequest($currentCompany)
727
    {
728
        $imageSize = $this->config['leaderslinked.image_sizes.microlearning_image_upload'];
729
        $marketplaceSize = $this->config['leaderslinked.image_sizes.marketplace'];
1 www 730
 
17178 stevensc 731
        $formAdd = new TopicAddForm($this->adapter, $currentCompany->id, $currentCompany->internal);
732
        $formEdit = new TopicEditForm($this->adapter, $currentCompany->id, $currentCompany->internal);
17002 efrain 733
 
17178 stevensc 734
        $this->layout()->setTemplate('layout/layout-backend.phtml');
735
        $viewModel = new ViewModel();
736
        $viewModel->setTemplate('leaders-linked/microlearning-topics/index.phtml');
737
        $viewModel->setVariables([
738
            'formAdd' => $formAdd,
739
            'formEdit' => $formEdit,
740
            'company_uuid' => $currentCompany->uuid,
741
            'image_size' => $imageSize,
742
            'marketplace_size' => $marketplaceSize,
17133 stevensc 743
        ]);
1 www 744
 
17178 stevensc 745
        return $viewModel;
746
    }
747
 
748
    /**
749
     * Get user permissions for topic actions
750
     * @param \Laminas\Permissions\Acl\Acl $acl
751
     * @param \LeadersLinked\Model\User $currentUser
752
     * @return array
753
     */
754
    private function getUserPermissions($acl, $currentUser)
755
    {
756
        return [
757
            'allowAdd' => $acl->isAllowed($currentUser->usertype_id, 'microlearning/content/topics/add'),
758
            'allowEdit' => $acl->isAllowed($currentUser->usertype_id, 'microlearning/content/topics/edit'),
759
            'allowDelete' => $acl->isAllowed($currentUser->usertype_id, 'microlearning/content/topics/delete'),
760
            'allowUsers' => $acl->isAllowed($currentUser->usertype_id, 'microlearning/content/topics/users')
761
        ];
762
    }
763
 
764
    /**
765
     * Create error response
766
     * @param string $message
767
     * @return \Laminas\View\Model\JsonModel
768
     */
769
    private function createErrorResponse($message)
770
    {
17133 stevensc 771
        return new JsonModel([
17178 stevensc 772
            'success' => false,
773
            'data' => $message
17133 stevensc 774
        ]);
1 www 775
    }
776
 
17178 stevensc 777
     /**
778
     * Prepare topic items for datatable
779
     * @param array $records
780
     * @param \LeadersLinked\Model\Company $currentCompany
781
     * @param array $permissions
782
     * @return array
783
     */
784
    private function prepareTopicItems($records, $currentCompany, $permissions)
1 www 785
    {
17178 stevensc 786
        $items = [];
787
        $microlearningTopicUserMapper = MicrolearningTopicUserMapper::getInstance($this->adapter);
788
        $storage = Storage::getInstance($this->config, $this->adapter);
789
        $path = $storage->getPathMicrolearningTopic();
17109 stevensc 790
 
17178 stevensc 791
        foreach ($records as $record) {
792
            $totalUsers = $microlearningTopicUserMapper->fetchCountUsersByCompanyIdAndTopicId($currentCompany->id, $record->id);
793
            $totalUsersActive = $microlearningTopicUserMapper->fetchCountUsersActiveByCompanyIdAndTopicId($currentCompany->id, $record->id);
794
 
795
            $status = $this->getTopicStatus($record->status);
796
            $privacy = $this->getTopicPrivacy($record->privacy);
797
            $type = $this->getTopicType($record->type);
798
 
799
            $items[] = [
800
                'name' => $record->name,
801
                'details' => [
802
                    'status' => $status,
803
                    'privacy' => $privacy,
804
                    'type' => $type,
805
                    'cost' => $record->cost,
806
                    'total_users' => $totalUsers,
807
                    'total_users_active' => $totalUsersActive,
808
                ],
809
                'images' => [
810
                    'image' => $storage->getGenericImage($path, $record->uuid, $record->image),
17195 stevensc 811
                    'marketplace' => $storage->getGenericImage($path, $record->uuid, $record->marketplace)
17178 stevensc 812
                ],
813
                'actions' => $this->prepareTopicActions($record, $permissions, $totalUsers, $totalUsersActive)
814
            ];
1 www 815
        }
17178 stevensc 816
 
817
        return $items;
818
    }
819
 
820
        /**
821
     * Get topic status label
822
     * @param int $status
823
     * @return string
824
     */
825
    private function getTopicStatus($status)
826
    {
827
        switch ($status) {
828
            case MicrolearningTopic::STATUS_ACTIVE:
829
                return 'LABEL_ACTIVE';
830
            case MicrolearningTopic::STATUS_INACTIVE:
831
                return 'LABEL_INACTIVE';
832
            default:
833
                return '';
1 www 834
        }
17178 stevensc 835
    }
836
 
837
    /**
838
     * Get topic privacy label
839
     * @param int $privacy
840
     * @return string
841
     */
842
    private function getTopicPrivacy($privacy)
843
    {
844
        switch ($privacy) {
845
            case MicrolearningTopic::PRIVACY_PUBLIC:
846
                return 'LABEL_PUBLIC';
847
            case MicrolearningTopic::PRIVACY_PRIVATE:
848
                return 'LABEL_PRIVATE';
849
            default:
850
                return '';
1 www 851
        }
852
    }
17178 stevensc 853
 
854
    /**
855
     * Get topic type label
856
     * @param int $type
857
     * @return string
858
     */
859
    private function getTopicType($type)
860
    {
861
        switch ($type) {
862
            case MicrolearningTopic::TYPE_FREE:
863
                return 'LABEL_FREE';
864
            case MicrolearningTopic::TYPE_PRIVATE:
865
                return 'LABEL_PRIVATE';
866
            case MicrolearningTopic::TYPE_SELLING:
867
                return 'LABEL_SELLING';
868
            default:
869
                return '';
870
        }
871
    }
872
 
873
     /**
874
     * Prepare topic actions
875
     * @param \LeadersLinked\Model\MicrolearningTopic $record
876
     * @param array $permissions
877
     * @param int $totalUsers
878
     * @param int $totalUsersActive
879
     * @return array
880
     */
881
    private function prepareTopicActions($record, $permissions, $totalUsers, $totalUsersActive)
882
    {
17188 stevensc 883
        $editDeleteParams = ['id' => $record->uuid];
17178 stevensc 884
 
885
        return [
17188 stevensc 886
            'link_edit' => $permissions['allowEdit'] ? $this->url()->fromRoute('microlearning/content/topics/edit', $editDeleteParams) : '',
887
            'link_delete' => $permissions['allowDelete'] ? $this->url()->fromRoute('microlearning/content/topics/delete', $editDeleteParams) : '',
17178 stevensc 888
            'link_total_users' => $permissions['allowUsers'] && $totalUsers ?
889
                $this->url()->fromRoute('microlearning/content/topics/users', [
890
                    'topic_uuid' => $record->uuid,
891
                    'type' => 'all'
892
                ]) : '',
893
            'link_total_users_actives' => $permissions['allowUsers'] && $totalUsersActive ?
894
                $this->url()->fromRoute('microlearning/content/topics/users', [
895
                    'topic_uuid' => $record->uuid,
896
                    'type' => 'active'
897
                ]) : ''
898
        ];
899
    }
17214 stevensc 900
 
901
    /**
902
     * Update topic capsule relations
903
     * @param \LeadersLinked\Model\MicrolearningTopic $topic
904
     * @param array $capsuleUuids
905
     * @param int $companyId
17224 stevensc 906
     * @param \LeadersLinked\Model\User $currentUser
17214 stevensc 907
     * @return array
908
     */
17224 stevensc 909
    private function updateTopicCapsuleRelations($topic, $capsuleUuids, $companyId, $currentUser)
17214 stevensc 910
    {
911
        try {
17224 stevensc 912
            // Ensure capsuleUuids is an array
913
            if (!is_array($capsuleUuids)) {
914
                $capsuleUuids = [];
915
            }
916
 
17214 stevensc 917
            $topicCapsuleMapper = MicrolearningTopicCapsuleMapper::getInstance($this->adapter);
918
            $topicCapsuleMapper->deleteByTopicId($topic->id);
919
 
920
            $capsuleMapper = MicrolearningCapsuleMapper::getInstance($this->adapter);
921
            foreach ($capsuleUuids as $capsuleUuid) {
922
                $capsule = $capsuleMapper->fetchOneByUuid($capsuleUuid);
923
 
924
                if ($capsule) {
925
                    $topicCapsule = new MicrolearningTopicCapsule();
926
                    $topicCapsule->topic_id = $topic->id;
927
                    $topicCapsule->capsule_id = $capsule->id;
928
                    $topicCapsule->company_id = $companyId;
929
                    $topicCapsuleMapper->insert($topicCapsule);
930
                }
931
            }
17224 stevensc 932
 
933
            $this->logger->info('Se actualizo la relacion de cápsulas del tópico ' . $topic->name, ['user_id' => $currentUser->id, 'ip' => Functions::getUserIP()]);
17214 stevensc 934
            return ['success' => true];
935
        } catch (\Exception $e) {
17224 stevensc 936
            $this->logger->err('Error in updateTopicCapsuleRelations: ' . $e->getMessage());
17214 stevensc 937
            return ['success' => false, 'error' => $e->getMessage()];
938
        }
939
    }
940
 
941
    /**
942
     * Process topic images
943
     * @param \Laminas\Http\Request $request
944
     * @param \LeadersLinked\Model\MicrolearningTopic $topic
945
     * @return array
946
     */
947
    private function processTopicImages($request, $topic)
948
    {
949
        try {
950
            $storage = Storage::getInstance($this->config, $this->adapter);
951
            $target_path = $storage->getPathMicrolearningTopic();
952
            $storage->setFiles($request->getFiles()->toArray());
953
 
954
            $result = [
955
                'success' => true,
956
                'image_filename' => '',
957
                'marketplace_filename' => ''
958
            ];
959
 
960
            // Process main image if uploaded
17219 stevensc 961
            if ($storage->setCurrentFilename('image')) {
17214 stevensc 962
                $target_size = $this->config['leaderslinked.image_sizes.microlearning_image_size'];
963
                list($target_width, $target_height) = explode('x', $target_size);
964
 
965
                $image_source_filename = $storage->getTmpFilename();
966
                $image_filename = 'topic-' . uniqid() . '.png';
967
                $image_target_filename = $storage->composePathToFilename(
968
                    Storage::TYPE_MICROLEARNING_TOPIC,
969
                    $topic->uuid,
970
                    $image_filename
971
                );
972
 
973
                if (!$storage->uploadImageCrop($image_source_filename, $image_target_filename, $target_width, $target_height)) {
974
                    return ['success' => false, 'error' => 'ERROR_UPLOAD_IMAGE'];
975
                }
976
 
977
                // Delete old image if exists
978
                if ($topic->image) {
979
                    $storage->deleteFile($target_path, $topic->uuid, $topic->image);
980
                }
981
 
982
                $result['image_filename'] = $image_filename;
983
            }
984
 
985
            // Process marketplace image if uploaded
986
            if ($storage->setCurrentFilename('marketplace')) {
987
                $target_size = $this->config['leaderslinked.image_sizes.microlearning_image_size'];
988
                list($target_width, $target_height) = explode('x', $target_size);
989
 
990
                $marketplace_source_filename = $storage->getTmpFilename();
991
                $marketplace_filename = 'marketplace-' . uniqid() . '.png';
992
                $marketplace_target_filename = $storage->composePathToFilename(
993
                    Storage::TYPE_MICROLEARNING_TOPIC,
994
                    $topic->uuid,
995
                    $marketplace_filename
996
                );
997
 
998
                if (!$storage->uploadImageCrop($marketplace_source_filename, $marketplace_target_filename, $target_width, $target_height)) {
999
                    return ['success' => false, 'error' => 'ERROR_UPLOAD_IMAGE'];
1000
                }
1001
 
1002
                // Delete old marketplace image if exists
1003
                if ($topic->marketplace) {
1004
                    $storage->deleteFile($target_path, $topic->uuid, $topic->marketplace);
1005
                }
1006
 
1007
                $result['marketplace_filename'] = $marketplace_filename;
1008
            }
1009
 
1010
            return $result;
1011
        } catch (\Exception $e) {
1012
            return ['success' => false, 'error' => $e->getMessage()];
1013
        }
1014
    }
1 www 1015
}