Proyectos de Subversion LeadersLinked - Backend

Rev

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