Proyectos de Subversion LeadersLinked - Backend

Rev

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