Proyectos de Subversion LeadersLinked - Services

Rev

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

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
2
 
3
declare(strict_types=1);
4
 
5
namespace LeadersLinked\Controller;
6
 
7
use Laminas\Db\Adapter\AdapterInterface;
8
 
9
use Laminas\Mvc\Controller\AbstractActionController;
10
use Laminas\Log\LoggerInterface;
11
use Laminas\View\Model\ViewModel;
12
 
13
use LeadersLinked\Library\Functions;
14
use LeadersLinked\Mapper\UserMapper;
15
 
16
use LeadersLinked\Model\User;
17
 
18
use LeadersLinked\Mapper\UserBlockedMapper;
19
 
20
use LeadersLinked\Mapper\CompanyMapper;
21
use LeadersLinked\Mapper\CompanyUserMapper;
307 www 22
use LeadersLinked\Mapper\ConversationMapper;
23
use LeadersLinked\Mapper\MessageMapper;
24
use LeadersLinked\Model\Conversation;
1 efrain 25
use LeadersLinked\Library\Image;
26
use Laminas\View\Model\JsonModel;
307 www 27
use LeadersLinked\Form\InMail\SendForm;
28
use LeadersLinked\Model\Message;
29
use LeadersLinked\Model\VideoConvert;
30
use LeadersLinked\Mapper\VideoConvertMapper;
1 efrain 31
use Laminas\Mvc\I18n\Translator;
199 efrain 32
use LeadersLinked\Mapper\AbuseReportMapper;
33
use LeadersLinked\Model\AbuseReport;
345 www 34
use LeadersLinked\Library\Storage;
1 efrain 35
 
36
class InMailController extends AbstractActionController
37
{
38
    /**
39
     *
40
     * @var \Laminas\Db\Adapter\AdapterInterface
41
     */
42
    private $adapter;
582 ariadna 43
 
1 efrain 44
    /**
45
     *
46
     * @var \LeadersLinked\Cache\CacheInterface
47
     */
48
    private $cache;
582 ariadna 49
 
50
 
1 efrain 51
    /**
52
     *
53
     * @var \Laminas\Log\LoggerInterface
54
     */
55
    private $logger;
582 ariadna 56
 
1 efrain 57
    /**
58
     *
59
     * @var array
60
     */
61
    private $config;
582 ariadna 62
 
63
 
1 efrain 64
    /**
65
     *
66
     * @var \Laminas\Mvc\I18n\Translator
67
     */
68
    private $translator;
582 ariadna 69
 
70
 
1 efrain 71
    /**
72
     *
73
     * @param \Laminas\Db\Adapter\AdapterInterface $adapter
74
     * @param \LeadersLinked\Cache\CacheInterface $cache
75
     * @param \Laminas\Log\LoggerInterface LoggerInterface $logger
76
     * @param array $config
77
     * @param \Laminas\Mvc\I18n\Translator $translator
78
     */
79
    public function __construct($adapter, $cache, $logger, $config, $translator)
80
    {
81
        $this->adapter      = $adapter;
82
        $this->cache        = $cache;
83
        $this->logger       = $logger;
84
        $this->config       = $config;
85
        $this->translator   = $translator;
86
    }
87
 
88
    /**
667 stevensc 89
     * Genera el listado de conversaciones del usuario actual
1 efrain 90
     *
667 stevensc 91
     * Endpoint: GET /inmail
1 efrain 92
     *
667 stevensc 93
     * Parámetros de ruta:
94
     * - id: UUID del usuario o empresa para seleccionar automáticamente (opcional)
95
     *
96
     * Respuesta exitosa:
1 efrain 97
     * [
667 stevensc 98
     *   success: true,
99
     *   data: [
100
     *     [
101
     *       uuid: UUID del usuario/empresa con quien se tiene la conversación,
102
     *       name: nombre del usuario/empresa,
103
     *       image: URL de la imagen del usuario/empresa,
104
     *       profile: URL del perfil del usuario/empresa,
105
     *       last_message: tiempo transcurrido del último mensaje,
307 www 106
     *       count_unread: cantidad de mensajes sin leer,
667 stevensc 107
     *       messages_link: URL para recuperar los mensajes,
108
     *       send_link: URL para enviar mensaje,
109
     *       selected: 0 = no seleccionado, 1 = seleccionado,
110
     *       delete_link: URL para eliminar la conversación
307 www 111
     *     ]
667 stevensc 112
     *   ]
113
     * ]
1 efrain 114
     *
667 stevensc 115
     * Respuesta de error:
116
     * [
117
     *   success: false,
118
     *   data: mensaje de error
119
     * ]
1 efrain 120
     *
121
     * @return \Laminas\View\Model\JsonModel
122
     */
123
    public function indexAction()
124
    {
125
        $request = $this->getRequest();
667 stevensc 126
 
127
        // Verificar que la petición sea GET
128
        if (!$request->isGet()) {
129
            return new JsonModel([
130
                'success' => false,
131
                'data' => 'ERROR_METHOD_NOT_ALLOWED'
132
            ]);
133
        }
307 www 134
 
667 stevensc 135
        // ========================================
136
        // INICIALIZACIÓN Y OBTENCIÓN DE DATOS BÁSICOS
137
        // ========================================
138
 
139
        // Obtener el usuario actual autenticado
140
        $currentUserPlugin = $this->plugin('currentUserPlugin');
141
        $currentUser = $currentUserPlugin->getUser();
307 www 142
 
667 stevensc 143
        // Obtener la fecha actual de la base de datos para cálculos de tiempo
144
        $userMapper = UserMapper::getInstance($this->adapter);
145
        $now = $userMapper->getDatebaseNow();
1 efrain 146
 
667 stevensc 147
        // ========================================
148
        // OBTENCIÓN DE USUARIOS BLOQUEADOS
149
        // ========================================
150
 
151
        // Obtener IDs de usuarios que el usuario actual ha bloqueado
152
        $userBlockedMapper = UserBlockedMapper::getInstance($this->adapter);
153
        $user_blocked_ids = $userBlockedMapper->fetchAllBlockedReturnIds($currentUser->id);
199 efrain 154
 
667 stevensc 155
        // Obtener IDs de usuarios que han bloqueado al usuario actual
156
        $user_blocked_me_ids = $userBlockedMapper->fetchAllUserBlockMeReturnIds($currentUser->id);
1 efrain 157
 
667 stevensc 158
        // ========================================
159
        // INICIALIZACIÓN DE MAPPER Y VARIABLES
160
        // ========================================
161
 
162
        $conversationMapper = ConversationMapper::getInstance($this->adapter);
163
        $messageMapper = MessageMapper::getInstance($this->adapter);
164
        $conversations = [];
165
        $selected_user_id = 0;
307 www 166
 
667 stevensc 167
        // ========================================
168
        // PROCESAMIENTO DE USUARIO/EMPRESA SELECCIONADO
169
        // ========================================
170
 
171
        $id = $this->params()->fromRoute('id');
172
        if ($id) {
173
            // ========================================
174
            // BÚSQUEDA COMO EMPRESA PRIMERO
175
            // ========================================
176
 
177
            $companyMapper = CompanyMapper::getInstance($this->adapter);
178
            $company = $companyMapper->fetchOneByUuid($id);
179
 
180
            if ($company) {
181
                // Buscar el propietario de la empresa
182
                $companyUserMapper = CompanyUserMapper::getInstance($this->adapter);
183
                $companyUser = $companyUserMapper->fetchOwnerByCompanyId($company->id);
307 www 184
 
667 stevensc 185
                // Verificar que no haya bloqueos entre usuarios
186
                if (!in_array($companyUser->user_id, $user_blocked_ids) &&
187
                    !in_array($companyUser->id, $user_blocked_me_ids)) {
188
 
189
                    $user = $userMapper->fetchOne($companyUser->user_id);
190
                    $selected_user_id = $user->id;
191
 
192
                    // Buscar conversación existente
193
                    $conversation = $conversationMapper->fetchOneByUserId1AndUserId2($currentUser->id, $user->id);
307 www 194
 
667 stevensc 195
                    // Calcular tiempo del último mensaje y mensajes no leídos
196
                    $timeElapsedString = '';
197
                    if ($conversation) {
198
                        $unread = $messageMapper->fetchCountUnreadMessagesByConversationIdAndReceiverId(
199
                            $conversation->id,
200
                            $currentUser->id
201
                        );
202
                        $lastMessage = $messageMapper->fetchLastUnreadMessagesByConversationIdAndReceiverId(
203
                            $conversation->id,
204
                            $currentUser->id
205
                        );
582 ariadna 206
 
667 stevensc 207
                        if ($lastMessage) {
208
                            $timeElapsedString = $this->timeAgo($lastMessage, $now);
209
                        }
210
                    } else {
211
                        $unread = 0;
212
                    }
582 ariadna 213
 
667 stevensc 214
                    // Agregar conversación de empresa a la lista
215
                    array_push($conversations, [
216
                        'uuid' => $company->uuid,
217
                        'name' => $company->name,
218
                        'image' => $this->url()->fromRoute('storage', [
219
                            'type' => 'company',
220
                            'code' => $company->uuid,
221
                            'filename' => $company->image
222
                        ], ['force_canonical' => true]),
223
                        'profile' => $this->url()->fromRoute('company/view', ['id' => $company->uuid]),
224
                        'last_message' => $timeElapsedString,
225
                        'count_unread' => $unread,
226
                        'messages_link' => $this->url()->fromRoute('inmail/message/list', ['id' => $user->uuid]),
227
                        'send_link' => $this->url()->fromRoute('inmail/message/send', ['id' => $user->uuid]),
228
                        'selected' => 1, // Marcar como seleccionado
229
                        'delete_link' => $this->url()->fromRoute('inmail/message/delete', ['id' => $user->uuid]),
230
                    ]);
231
                }
232
            }
233
            // ========================================
234
            // BÚSQUEDA COMO USUARIO INDIVIDUAL
235
            // ========================================
236
            else {
237
                $user = $userMapper->fetchOneByUuid($id);
238
                if ($user) {
239
                    // Verificar que no haya bloqueos entre usuarios
240
                    if (!in_array($user->id, $user_blocked_ids) &&
241
                        !in_array($user->id, $user_blocked_me_ids)) {
582 ariadna 242
 
667 stevensc 243
                        $timeElapsedString = '';
582 ariadna 244
                        $selected_user_id = $user->id;
667 stevensc 245
 
246
                        // Buscar conversación existente
582 ariadna 247
                        $conversation = $conversationMapper->fetchOneByUserId1AndUserId2($currentUser->id, $user->id);
667 stevensc 248
 
582 ariadna 249
                        if ($conversation) {
667 stevensc 250
                            $unread = $messageMapper->fetchCountUnreadMessagesByConversationIdAndReceiverId(
251
                                $conversation->id,
252
                                $currentUser->id
253
                            );
254
                            $lastMessage = $messageMapper->fetchLastUnreadMessagesByConversationIdAndReceiverId(
255
                                $conversation->id,
256
                                $currentUser->id
257
                            );
258
 
582 ariadna 259
                            if ($lastMessage) {
667 stevensc 260
                                $timeElapsedString = $this->timeAgo($lastMessage, $now);
582 ariadna 261
                            }
262
                        } else {
263
                            $unread = 0;
264
                        }
265
 
667 stevensc 266
                        // Agregar conversación de usuario a la lista
582 ariadna 267
                        array_push($conversations, [
667 stevensc 268
                            'uuid' => $user->uuid,
269
                            'name' => trim($user->first_name . ' ' . $user->last_name),
270
                            'image' => $this->url()->fromRoute('storage', [
271
                                'type' => 'user',
272
                                'code' => $user->uuid,
273
                                'filename' => $user->image
274
                            ], ['force_canonical' => true]),
275
                            'profile' => $this->url()->fromRoute('profile/view', ['id' => $user->uuid]),
582 ariadna 276
                            'last_message' => $timeElapsedString,
277
                            'count_unread' => $unread,
667 stevensc 278
                            'messages_link' => $this->url()->fromRoute('inmail/message/list', ['id' => $user->uuid]),
582 ariadna 279
                            'send_link' => $this->url()->fromRoute('inmail/message/send', ['id' => $user->uuid]),
667 stevensc 280
                            'selected' => 1, // Marcar como seleccionado
281
                            'delete_link' => $this->url()->fromRoute('inmail/message/delete', ['id' => $user->uuid]),
582 ariadna 282
                        ]);
283
                    }
284
                }
285
            }
667 stevensc 286
        }
307 www 287
 
667 stevensc 288
        // ========================================
289
        // OBTENCIÓN DE TODAS LAS CONVERSACIONES EXISTENTES
290
        // ========================================
291
 
292
        $records = $conversationMapper->fetchAllByUserId($currentUser->id);
293
 
294
        foreach ($records as $record) {
295
            // ========================================
296
            // FILTRADO DE CONVERSACIONES YA PROCESADAS
297
            // ========================================
298
 
299
            // Omitir conversaciones que ya fueron procesadas como seleccionadas
300
            if ($selected_user_id) {
301
                if ($record->sender_id == $currentUser->id && $record->receiver_id == $selected_user_id) {
302
                    continue;
1 efrain 303
                }
667 stevensc 304
                if ($record->receiver_id == $currentUser->id && $record->sender_id == $selected_user_id) {
305
                    continue;
582 ariadna 306
                }
667 stevensc 307
            }
1 efrain 308
 
667 stevensc 309
            // ========================================
310
            // DETERMINACIÓN DEL OTRO USUARIO EN LA CONVERSACIÓN
311
            // ========================================
312
 
313
            if ($record->sender_id == $currentUser->id) {
314
                $user = $userMapper->fetchOne($record->receiver_id);
315
            }
316
            if ($record->receiver_id == $currentUser->id) {
317
                $user = $userMapper->fetchOne($record->sender_id);
318
 
319
                // Omitir usuarios bloqueados
320
                if (in_array($user->id, $user_blocked_ids) || in_array($user->id, $user_blocked_me_ids)) {
321
                    continue;
582 ariadna 322
                }
667 stevensc 323
            }
1 efrain 324
 
667 stevensc 325
            // ========================================
326
            // CÁLCULO DE TIEMPO Y MENSAJES NO LEÍDOS
327
            // ========================================
328
 
329
            $timeElapsedString = '';
330
            $unread = $messageMapper->fetchCountUnreadMessagesByConversationIdAndReceiverId(
331
                $record->id,
332
                $currentUser->id
333
            );
334
            $lastMessage = $messageMapper->fetchLastMessagesByConversationIdAndReceiverId(
335
                $record->id,
336
                $currentUser->id
337
            );
1 efrain 338
 
667 stevensc 339
            if ($lastMessage) {
340
                $timeElapsedString = $this->timeAgo($lastMessage, $now);
582 ariadna 341
            }
1 efrain 342
 
667 stevensc 343
            // ========================================
344
            // AGREGAR CONVERSACIÓN A LA LISTA
345
            // ========================================
346
 
347
            array_push($conversations, [
348
                'uuid' => $user->uuid,
349
                'name' => trim($user->first_name . ' ' . $user->last_name),
350
                'image' => $this->url()->fromRoute('storage', [
351
                    'type' => 'user',
352
                    'code' => $user->uuid,
353
                    'filename' => $user->image
354
                ], ['force_canonical' => true]),
355
                'profile' => $this->url()->fromRoute('profile/view', ['id' => $user->uuid]),
356
                'last_message' => $timeElapsedString,
357
                'count_unread' => $unread,
358
                'messages_link' => $this->url()->fromRoute('inmail/message/list', ['id' => $user->uuid]),
359
                'send_link' => $this->url()->fromRoute('inmail/message/send', ['id' => $user->uuid]),
360
                'selected' => 0, // No seleccionado
361
                'delete_link' => $this->url()->fromRoute('inmail/message/delete', ['id' => $user->uuid]),
362
            ]);
363
        }
1 efrain 364
 
667 stevensc 365
        // ========================================
366
        // ORDENAMIENTO DE CONVERSACIONES
367
        // ========================================
368
 
369
        // Ordenar por: seleccionados primero, luego por fecha del último mensaje
370
        usort($conversations, function ($a, $b) {
371
            if ($a['selected'] == $b['selected']) {
372
                if ($a['last_message'] == $b['last_message']) {
373
                    return 0;
582 ariadna 374
                } else {
667 stevensc 375
                    return $a['last_message'] < $b['last_message'] ? -1 : 1;
582 ariadna 376
                }
667 stevensc 377
            } else {
378
                return $a['selected'] < $b['selected'] ? -1 : 1;
379
            }
380
        });
1 efrain 381
 
667 stevensc 382
        // ========================================
383
        // RESPUESTA FINAL
384
        // ========================================
385
 
386
        return new JsonModel([
387
            'success' => true,
388
            'data' => $conversations
389
        ]);
1 efrain 390
    }
307 www 391
 
392
    /**
666 stevensc 393
     * Recupera los mensajes de una conversación específica entre usuarios
394
     *
395
     * Endpoint: GET /inmail/message/:id
396
     *
397
     * Parámetros de consulta:
398
     * - page: número de página para paginación (opcional, por defecto 0)
399
     *
400
     * Respuesta exitosa:
307 www 401
     * [
402
     *   success: true,
666 stevensc 403
     *   data: [
404
     *     [
405
     *       uuid: UUID del mensaje,
406
     *       sender_name: nombre del remitente,
407
     *       sender_image: URL de la imagen del remitente,
408
     *       sender_profile: URL del perfil del remitente,
409
     *       receiver_name: nombre del destinatario,
410
     *       receiver_image: URL de la imagen del destinatario,
411
     *       receiver_profile: URL del perfil del destinatario,
412
     *       side: 'left' (mensaje propio) | 'right' (mensaje recibido),
413
     *       message: contenido del mensaje,
414
     *       type: 'text' | 'image' | 'video' | 'document',
415
     *       filename: URL del archivo adjunto (si existe),
416
     *       date: tiempo transcurrido desde el envío,
417
     *       url_abuse_report: URL para reportar abuso (solo mensajes recibidos)
418
     *     ]
419
     *   ],
420
     *   pagination: información de paginación
421
     * ]
422
     *
423
     * Respuesta de error:
307 www 424
     * [
666 stevensc 425
     *   success: false,
426
     *   data: mensaje de error
307 www 427
     * ]
666 stevensc 428
     *
307 www 429
     * @return \Laminas\View\Model\JsonModel
430
     */
431
    public function messageAction()
1 efrain 432
    {
433
        $request = $this->getRequest();
666 stevensc 434
 
435
        // Verificar que la petición sea GET
436
        if (!$request->isGet()) {
437
            return new JsonModel([
438
                'success' => false,
439
                'data' => 'ERROR_METHOD_NOT_ALLOWED'
440
            ]);
441
        }
307 www 442
 
666 stevensc 443
        // ========================================
444
        // INICIALIZACIÓN Y VALIDACIÓN DE PARÁMETROS
445
        // ========================================
446
 
447
        // Obtener parámetros de la petición
448
        $page = intval($this->params()->fromQuery('page', 0), 10);
449
        $id = $this->params()->fromRoute('id');
450
 
451
        // Validar que se proporcione el ID del usuario
452
        if (!$id) {
453
            return new JsonModel([
454
                'success' => false,
455
                'data' => 'ERROR_PARAMETERS_ARE_INVALID'
456
            ]);
457
        }
307 www 458
 
666 stevensc 459
        // Obtener el usuario actual autenticado
460
        $currentUserPlugin = $this->plugin('currentUserPlugin');
461
        $currentUser = $currentUserPlugin->getUser();
582 ariadna 462
 
666 stevensc 463
        // Obtener la fecha actual de la base de datos para cálculos de tiempo
464
        $userMapper = UserMapper::getInstance($this->adapter);
465
        $now = $userMapper->getDatebaseNow();
307 www 466
 
666 stevensc 467
        // ========================================
468
        // VALIDACIÓN DEL USUARIO DESTINATARIO
469
        // ========================================
470
 
471
        // Buscar el usuario destinatario por UUID
472
        $user = $userMapper->fetchOneByUuid($id);
473
        if (!$user) {
474
            return new JsonModel([
475
                'success' => false,
476
                'data' => 'ERROR_REQUEST_IS_INVALID'
477
            ]);
478
        }
307 www 479
 
666 stevensc 480
        // ========================================
481
        // OBTENCIÓN DE REPORTES DE ABUSO
482
        // ========================================
483
 
484
        // Obtener IDs de mensajes reportados por el usuario actual
485
        $abuseReportMapper = AbuseReportMapper::getInstance($this->adapter);
486
        $abuse_report_message_ids = $abuseReportMapper->fetchAllDataByUserReportingIdAndTypeReturnIds(
487
            $currentUser->id,
488
            AbuseReport::TYPE_INMAIL_MESSAGE
489
        );
307 www 490
 
666 stevensc 491
        // ========================================
492
        // BÚSQUEDA DE LA CONVERSACIÓN
493
        // ========================================
494
 
495
        $conversationMapper = ConversationMapper::getInstance($this->adapter);
496
        $messageMapper = MessageMapper::getInstance($this->adapter);
497
 
498
        // Buscar la conversación entre los dos usuarios
499
        $conversation = $conversationMapper->fetchOneByUserId1AndUserId2($currentUser->id, $user->id);
500
 
501
        $messages = [];
502
 
503
        // ========================================
504
        // PROCESAMIENTO DE MENSAJES
505
        // ========================================
506
 
507
        if ($conversation) {
508
            // Obtener mensajes paginados de la conversación
509
            $records = $messageMapper->getAllMessagesPaginatorByConversationId($conversation->id, $page);
582 ariadna 510
 
666 stevensc 511
            foreach ($records as $record) {
512
                // Calcular tiempo transcurrido desde el envío del mensaje
513
                $timeElapsedString = $this->timeAgo($record->added_on, $now);
307 www 514
 
666 stevensc 515
                // ========================================
516
                // MENSAJES ENVIADOS POR EL USUARIO ACTUAL
517
                // ========================================
518
 
519
                if ($record->sender_id == $currentUser->id) {
520
                    array_push($messages, [
521
                        'uuid' => $record->uuid,
522
                        'sender_name' => trim($currentUser->first_name . ' ' . $currentUser->last_name),
523
                        'sender_image' => $this->url()->fromRoute('storage', [
524
                            'type' => 'user',
525
                            'filename' => $currentUser->image,
526
                            'code' => $currentUser->uuid
527
                        ], ['force_canonical' => true]),
528
                        'sender_profile' => $this->url()->fromRoute('profile/view', ['id' => $currentUser->uuid]),
529
                        'receiver_name' => trim($user->first_name . ' ' . $user->last_name),
530
                        'receiver_image' => $this->url()->fromRoute('storage', [
531
                            'type' => 'user',
532
                            'filename' => $user->image,
533
                            'code' => $user->uuid
534
                        ], ['force_canonical' => true]),
535
                        'receiver_profile' => $this->url()->fromRoute('profile/view', ['id' => $user->uuid]),
536
                        'side' => 'left', // Mensaje propio (lado izquierdo)
537
                        'message' => $record->message,
538
                        'type' => $record->type,
539
                        'filename' => $record->filename ? $this->url()->fromRoute('storage', [
540
                            'type' => 'message',
541
                            'filename' => $record->filename,
542
                            'code' => $record->uuid
543
                        ], ['force_canonical' => true]) : '',
544
                        'date' => $timeElapsedString,
545
                        'url_abuse_report' => '', // No se puede reportar mensajes propios
546
                    ]);
547
                }
548
                // ========================================
549
                // MENSAJES RECIBIDOS DEL OTRO USUARIO
550
                // ========================================
551
                else {
552
                    // Verificar si el mensaje ha sido reportado por abuso
553
                    if (in_array($record->id, $abuse_report_message_ids)) {
554
                        // Mensaje reportado - mostrar mensaje de contenido reportado
555
                        array_push($messages, [
556
                            'uuid' => $record->uuid,
557
                            'sender_name' => trim($user->first_name . ' ' . $user->last_name),
558
                            'sender_image' => $this->url()->fromRoute('storage', [
559
                                'type' => 'user',
560
                                'filename' => $user->image,
561
                                'code' => $user->uuid
562
                            ], ['force_canonical' => true]),
563
                            'sender_profile' => $this->url()->fromRoute('profile/view', ['id' => $user->uuid]),
564
                            'receiver_name' => trim($currentUser->first_name . ' ' . $currentUser->last_name),
565
                            'receiver_image' => $this->url()->fromRoute('storage', [
566
                                'type' => 'user',
567
                                'filename' => $currentUser->image,
568
                                'code' => $user->uuid
569
                            ], ['force_canonical' => true]),
570
                            'receiver_profile' => $this->url()->fromRoute('profile/view', ['id' => $currentUser->uuid]),
571
                            'side' => 'right', // Mensaje recibido (lado derecho)
572
                            'message' => 'LABEL_ABUSE_CONTENT_REPORTED',
573
                            'type' => Message::TYPE_TEXT,
574
                            'filename' => '',
575
                            'date' => $timeElapsedString,
576
                            'url_abuse_report' => '', // Ya no se puede reportar
577
                        ]);
578
                    } else {
579
                        // Mensaje normal - generar URL para reportar abuso
580
                        $url_abuse_report = $this->url()->fromRoute('helpers/abuse-report', [
581
                            'type' => 'message',
582
                            'id' => $record->uuid
583
                        ], ['force_canonical' => true]);
582 ariadna 584
 
307 www 585
                        array_push($messages, [
586
                            'uuid' => $record->uuid,
666 stevensc 587
                            'sender_name' => trim($user->first_name . ' ' . $user->last_name),
588
                            'sender_image' => $this->url()->fromRoute('storage', [
589
                                'type' => 'user',
590
                                'filename' => $user->image,
591
                                'code' => $user->uuid
592
                            ], ['force_canonical' => true]),
593
                            'sender_profile' => $this->url()->fromRoute('profile/view', ['id' => $user->uuid]),
594
                            'receiver_name' => trim($currentUser->first_name . ' ' . $currentUser->last_name),
595
                            'receiver_image' => $this->url()->fromRoute('storage', [
596
                                'type' => 'user',
597
                                'filename' => $currentUser->image,
598
                                'code' => $user->uuid
599
                            ], ['force_canonical' => true]),
600
                            'receiver_profile' => $this->url()->fromRoute('profile/view', ['id' => $currentUser->uuid]),
601
                            'side' => 'right', // Mensaje recibido (lado derecho)
307 www 602
                            'message' => $record->message,
603
                            'type' => $record->type,
666 stevensc 604
                            'filename' => $record->filename ? $this->url()->fromRoute('storage', [
605
                                'type' => 'message',
606
                                'filename' => $record->filename,
607
                                'code' => $record->uuid
608
                            ], ['force_canonical' => true]) : '',
307 www 609
                            'date' => $timeElapsedString,
666 stevensc 610
                            'url_abuse_report' => $url_abuse_report,
307 www 611
                        ]);
582 ariadna 612
 
666 stevensc 613
                        // Marcar el mensaje como leído
307 www 614
                        $messageMapper->markAsRead($record->id);
261 efrain 615
                    }
307 www 616
                }
1 efrain 617
            }
307 www 618
 
666 stevensc 619
            // ========================================
620
            // RESPUESTA CON MENSAJES Y PAGINACIÓN
621
            // ========================================
622
 
307 www 623
            return new JsonModel([
624
                'success' => true,
625
                'data' => $messages,
666 stevensc 626
                'pagination' => $records->getPages()
307 www 627
            ]);
1 efrain 628
        }
666 stevensc 629
 
630
        // ========================================
631
        // RESPUESTA CUANDO NO EXISTE CONVERSACIÓN
632
        // ========================================
633
 
634
        return new JsonModel([
635
            'success' => true,
636
            'data' => $messages,
637
            'pagination' => 1
638
        ]);
1 efrain 639
    }
307 www 640
 
641
    /**
589 ariadna 642
     * Envía un mensaje InMail a un usuario específico
307 www 643
     *
589 ariadna 644
     * Endpoint: POST /inmail/message/send/:id
645
     *
646
     * Parámetros requeridos:
647
     * - message: texto plano del mensaje
648
     *
649
     * Parámetros opcionales:
650
     * - file: archivo adjunto (jpg, jpeg, png, mp4, webm, mpeg, pdf)
651
     *
652
     * @return JsonModel
307 www 653
     */
654
    public function sendMessageAction()
1 efrain 655
    {
589 ariadna 656
        // Verificar que la petición sea POST
1 efrain 657
        $request = $this->getRequest();
589 ariadna 658
        if (!$request->isPost()) {
659
            return new JsonModel([
660
                'success' => false,
661
                'data' => 'ERROR_METHOD_NOT_ALLOWED'
662
            ]);
663
        }
307 www 664
 
589 ariadna 665
        // Obtener el usuario actual
666
        $currentUserPlugin = $this->plugin('currentUserPlugin');
667
        $currentUser = $currentUserPlugin->getUser();
307 www 668
 
589 ariadna 669
        // Obtener la fecha actual de la base de datos
670
        $userMapper = UserMapper::getInstance($this->adapter);
671
        $now = $userMapper->getDatebaseNow();
582 ariadna 672
 
589 ariadna 673
        // Validar el ID del destinatario
674
        $id = $this->params()->fromRoute('id');
675
        if (!$id) {
676
            return new JsonModel([
677
                'success' => false,
678
                'data' => 'ERROR_PARAMETERS_ARE_INVALID'
679
            ]);
680
        }
307 www 681
 
589 ariadna 682
        // Buscar el usuario destinatario
683
        $user = $userMapper->fetchOneByUuidAndNetworkId($id, $currentUser->network_id);
684
        if (!$user) {
685
            return new JsonModel([
686
                'success' => false,
687
                'data' => 'ERROR_REQUEST_IS_INVALID'
688
            ]);
689
        }
307 www 690
 
589 ariadna 691
        // Combinar datos POST y archivos
692
        $data = array_merge($request->getPost()->toArray(), $request->getFiles()->toArray());
307 www 693
 
589 ariadna 694
        // Si se envía un archivo sin error, usar su nombre como mensaje
695
        if (!empty($data['file']) && empty($data['file']['error'])) {
696
            $data['message'] = $data['file']['name'];
697
        }
307 www 698
 
589 ariadna 699
        // Validar los datos del formulario
700
        $form = new SendForm();
701
        $form->setData($data);
582 ariadna 702
 
589 ariadna 703
        if (!$form->isValid()) {
704
            // Si el formulario no es válido, devolver los errores
705
            $messages = [];
706
            $form_messages = (array) $form->getMessages();
707
            foreach ($form_messages as $fieldname => $field_messages) {
708
                $messages[$fieldname] = array_values($field_messages);
307 www 709
            }
589 ariadna 710
            return new JsonModel([
711
                'success' => false,
712
                'data' => $messages
713
            ]);
714
        }
582 ariadna 715
 
589 ariadna 716
        // Obtener los datos validados
717
        $dataPost = (array) $form->getData();
307 www 718
 
589 ariadna 719
        // Buscar o crear la conversación
720
        $conversationMapper = ConversationMapper::getInstance($this->adapter);
721
        $conversation = $conversationMapper->fetchOneByUserId1AndUserId2($currentUser->id, $user->id);
307 www 722
 
589 ariadna 723
        if ($conversation) {
724
            // Actualizar estado de la conversación existente
725
            $conversation->receiver_status = Conversation::STATUS_NORMAL;
726
            $conversation->sender_status = Conversation::STATUS_NORMAL;
307 www 727
 
589 ariadna 728
            if (!$conversationMapper->update($conversation)) {
729
                return new JsonModel([
730
                    'success' => false,
731
                    'data' => $conversationMapper->getError()
732
                ]);
733
            }
734
        } else {
735
            // Crear nueva conversación
736
            $conversation = new Conversation();
737
            $conversation->sender_id = $currentUser->id;
738
            $conversation->sender_status = Conversation::STATUS_NORMAL;
739
            $conversation->receiver_id = $user->id;
740
            $conversation->receiver_status = Conversation::STATUS_NORMAL;
582 ariadna 741
 
589 ariadna 742
            if (!$conversationMapper->insert($conversation)) {
743
                return new JsonModel([
744
                    'success' => false,
745
                    'data' => $conversationMapper->getError()
746
                ]);
747
            }
748
        }
307 www 749
 
589 ariadna 750
        // Procesar archivo adjunto si existe
751
        $files = $this->getRequest()->getFiles()->toArray();
752
        $type = Message::TYPE_TEXT;
753
        $message_tmp_filename = '';
754
        $message_filename = '';
307 www 755
 
589 ariadna 756
        if (isset($files['file']) && empty($files['file']['error'])) {
757
            $message_tmp_filename = $files['file']['tmp_name'];
758
            $message_filename = \LeadersLinked\Library\Functions::normalizeStringFilename($files['file']['name']);
307 www 759
 
589 ariadna 760
            // Determinar el tipo de archivo
761
            $mime_type = mime_content_type($message_tmp_filename);
762
            if ($mime_type == 'image/jpg' || $mime_type == 'image/jpeg' || $mime_type == 'image/png') {
763
                $type = Storage::FILE_TYPE_IMAGE;
764
            } else if ($mime_type == 'video/webm' || $mime_type == 'video/mpeg' || $mime_type == 'video/mpg' || $mime_type == 'video/mp4') {
765
                $type = Storage::FILE_TYPE_VIDEO;
766
            } else if ($mime_type == 'application/pdf') {
767
                $type = Storage::FILE_TYPE_DOCUMENT;
768
            }
769
        }
307 www 770
 
589 ariadna 771
        // Crear y guardar el mensaje
772
        $message = new Message();
773
        $message->conversation_id = $conversation->id;
774
        $message->read = Message::NO;
775
        $message->message = $type == Message::TYPE_TEXT ? $dataPost['message'] : '';
776
        $message->receiver_id = $user->id;
777
        $message->receiver_status = Message::STATUS_NORMAL;
778
        $message->sender_id = $currentUser->id;
779
        $message->sender_status = Message::STATUS_NORMAL;
780
        $message->type = $type;
307 www 781
 
589 ariadna 782
        $messageMapper = MessageMapper::getInstance($this->adapter);
783
        if (!$messageMapper->insert($message)) {
784
            return new JsonModel([
785
                'success' => false,
786
                'data' => $messageMapper->getError()
787
            ]);
788
        }
307 www 789
 
589 ariadna 790
        // Procesar archivo adjunto si existe
791
        if ($message_filename) {
792
            $storage = new Storage();
793
            $storage->setAdapter($this->adapter);
794
            $storage->setLogger($this->logger);
795
            $storage->setTranslator($this->translator);
307 www 796
 
589 ariadna 797
            if (!$storage->uploadMessageFile($message_tmp_filename, $message_filename, $message->uuid)) {
798
                return new JsonModel([
799
                    'success' => false,
800
                    'data' => $storage->getError()
801
                ]);
802
            }
307 www 803
 
589 ariadna 804
            $message->filename = $message_filename;
805
            if (!$messageMapper->update($message)) {
1 efrain 806
                return new JsonModel([
589 ariadna 807
                    'success' => false,
808
                    'data' => $messageMapper->getError()
1 efrain 809
                ]);
810
            }
811
        }
589 ariadna 812
 
813
        // Preparar respuesta exitosa
814
        $filename = '';
815
        if ($message->filename) {
816
            $filename = $this->url()->fromRoute('storage', [
817
                'type' => 'message',
818
                'filename' => $message->filename,
819
                'code' => $message->uuid
820
            ], ['force_canonical' => true]);
821
        }
822
 
823
        // Actualizar última actividad del usuario
824
        $userMapper->updateLastActivity($currentUser->id);
825
 
826
        // Devolver respuesta exitosa con datos del mensaje
827
        return new JsonModel([
828
            'success' => true,
829
            'data' => [
830
                'sender_name' => trim($currentUser->first_name . ' ' . $currentUser->last_name),
831
                'sender_image' => $this->url()->fromRoute('storage', [
832
                    'type' => 'user',
833
                    'filename' => $currentUser->image,
834
                    'code' => $currentUser->uuid
835
                ], ['force_canonical' => true]),
836
                'sender_profile' => $this->url()->fromRoute('profile/view', ['id' => $currentUser->uuid]),
837
                'receiver_name' => trim($user->first_name . ' ' . $user->last_name),
838
                'receiver_image' => $this->url()->fromRoute('storage', [
839
                    'type' => 'user',
840
                    'filename' => $user->image,
841
                    'code' => $user->uuid
842
                ], ['force_canonical' => true]),
843
                'receiver_profile' => $this->url()->fromRoute('profile/view', ['id' => $user->uuid]),
844
                'side' => 'left',
845
                'message' => $message->message,
846
                'type' => $message->type,
847
                'filename' => $filename,
848
                'date' => $this->timeAgo($now, $now),
849
            ]
850
        ]);
1 efrain 851
    }
307 www 852
 
853
 
854
 
855
    /**
856
     *
857
     * @param string $timestamp
858
     * @param string $now
859
     * @return string
860
     */
861
    private function timeAgo($timestamp, $now = '')
862
    {
582 ariadna 863
 
307 www 864
        if ($now) {
865
            $datetime1 = \DateTime::createFromFormat('Y-m-d H:i:s', $now);
1 efrain 866
        } else {
307 www 867
            $now = date('Y-m-d H:i:s');
868
            $datetime1 = date_create($now);
1 efrain 869
        }
307 www 870
        $datetime2 = date_create($timestamp);
582 ariadna 871
 
307 www 872
        $diff = date_diff($datetime1, $datetime2);
873
        $timemsg = '';
874
        if ($diff->y > 0) {
582 ariadna 875
            $timemsg = $diff->y . ' ' . ($diff->y > 1 ? $this->translator->translate('LABEL_YEARS_SMALL')  : $this->translator->translate('LABEL_YEAR_SMALL'));
307 www 876
        } else if ($diff->m > 0) {
582 ariadna 877
            $timemsg = $diff->m  . ' ' . ($diff->m > 1 ? $this->translator->translate('LABEL_MONTHS_SMALL')  : $this->translator->translate('LABEL_MONTH_SMALL'));
307 www 878
        } else if ($diff->d > 0) {
582 ariadna 879
            $timemsg = $diff->d . ' ' . ($diff->d > 1 ? $this->translator->translate('LABEL_DAYS_SMALL')  : $this->translator->translate('LABEL_DAY_SMALL'));
307 www 880
        } else if ($diff->h > 0) {
582 ariadna 881
            $timemsg = $diff->h  . ' ' . ($diff->h > 1 ? $this->translator->translate('LABEL_HOURS_SMALL')  : $this->translator->translate('LABEL_HOUR_SMALL'));
307 www 882
        } else if ($diff->i > 0) {
582 ariadna 883
            $timemsg = $diff->i  . ' ' . ($diff->i > 1 ? $this->translator->translate('LABEL_MINUTES_SMALL')  : $this->translator->translate('LABEL_MINUTE_SMALL'));
307 www 884
        } else if ($diff->s > 0) {
582 ariadna 885
            $timemsg = $diff->s  . ' ' . ($diff->s > 1 ? $this->translator->translate('LABEL_SECONDS_SMALL')  : $this->translator->translate('LABEL_SECOND_SMALL'));
307 www 886
        }
887
        if (!$timemsg) {
582 ariadna 888
            $timemsg = $this->translator->translate('LABEL_NOW');
307 www 889
        } else {
582 ariadna 890
            $timemsg = $this->translator->translate('LABEL_AGO_SMALL') . ' ' . $timemsg . '';
307 www 891
        }
892
        return $timemsg;
1 efrain 893
    }
307 www 894
 
895
 
896
    public function deleteAction()
1 efrain 897
    {
898
        $request = $this->getRequest();
899
        if ($request->isPost()) {
900
            $currentUserPlugin = $this->plugin('currentUserPlugin');
901
            $currentUser = $currentUserPlugin->getUser();
582 ariadna 902
 
1 efrain 903
            $id = $this->params()->fromRoute('id');
904
            if (!$id) {
905
                return new JsonModel([
906
                    'success' => false,
907
                    'data' => 'ERROR_PARAMETERS_ARE_INVALID'
908
                ]);
909
            }
582 ariadna 910
 
307 www 911
            $userMapper = UserMapper::getInstance($this->adapter);
912
            $user = $userMapper->fetchOneByUuid($id);
1 efrain 913
            if (!$user) {
914
                return new JsonModel([
915
                    'success' => false,
916
                    'data' => 'ERROR_REQUEST_IS_INVALID'
917
                ]);
918
            }
582 ariadna 919
 
307 www 920
            $conversationMapper = ConversationMapper::getInstance($this->adapter);
921
            $conversation = $conversationMapper->fetchOneByUserId1AndUserId2($currentUser->id, $user->id);
582 ariadna 922
 
923
 
307 www 924
            if ($conversation) {
582 ariadna 925
 
307 www 926
                if ($conversation->sender_id == $currentUser->id && $conversation->receiver_id == $user->id) {
927
                    $conversation->sender_status = Conversation::STATUS_DELETED;
928
                    if ($conversationMapper->update($conversation)) {
929
                        $response = [
930
                            'success' => true,
931
                            'data' => 'LABEL_CONVERSATION_WAS_DELETED'
932
                        ];
933
                    } else {
582 ariadna 934
 
935
 
307 www 936
                        $response = [
937
                            'success' => false,
938
                            'data' => $conversationMapper->getError()
939
                        ];
291 www 940
                    }
307 www 941
                }
582 ariadna 942
 
307 www 943
                if ($conversation->receiver_id == $currentUser->id && $conversation->sender_id == $user->id) {
944
                    $conversation->receiver_status = Conversation::STATUS_DELETED;
945
                    if ($conversationMapper->update($conversation)) {
946
                        $response = [
947
                            'success' => true,
948
                            'data' => 'LABEL_CONVERSATION_WAS_DELETED'
949
                        ];
291 www 950
                    } else {
582 ariadna 951
 
952
 
307 www 953
                        $response = [
954
                            'success' => false,
955
                            'data' => $conversationMapper->getError()
956
                        ];
1 efrain 957
                    }
958
                }
582 ariadna 959
 
307 www 960
                return new JsonModel($response);
1 efrain 961
            } else {
307 www 962
                $response = [
963
                    'success' => false,
964
                    'data' => 'ERROR_CONVERSATION_NOT_FOUND'
965
                ];
1 efrain 966
            }
582 ariadna 967
 
307 www 968
            return new JsonModel($response);
1 efrain 969
        } else {
307 www 970
            $response = [
1 efrain 971
                'success' => false,
972
                'data' => 'ERROR_METHOD_NOT_ALLOWED'
307 www 973
            ];
1 efrain 974
        }
582 ariadna 975
 
307 www 976
        return new JsonModel($response);
1 efrain 977
    }
978
}