Proyectos de Subversion LeadersLinked - Services

Rev

Rev 596 | 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
/**
4
 *
5
 * Controlador: Mis Perfiles
6
 *
7
 */
8
 
9
declare(strict_types=1);
10
 
11
namespace LeadersLinked\Controller;
12
 
13
use Laminas\Db\Adapter\AdapterInterface;
14
 
15
use Laminas\Mvc\Controller\AbstractActionController;
16
use Laminas\Log\LoggerInterface;
17
use Laminas\View\Model\ViewModel;
18
use Laminas\View\Model\JsonModel;
19
 
20
use LeadersLinked\Form\UserProfile\SkillForm;
21
use LeadersLinked\Form\UserProfile\LanguageForm;
22
 
23
use LeadersLinked\Library\Functions;
24
use LeadersLinked\Mapper\UserProfileMapper;
25
use LeadersLinked\Hydrator\ObjectPropertyHydrator;
26
use LeadersLinked\Model\UserProfile;
27
use LeadersLinked\Mapper\CompanyFollowerMapper;
28
use LeadersLinked\Mapper\LocationMapper;
29
use LeadersLinked\Model\UserLanguage;
30
use LeadersLinked\Mapper\UserLanguageMapper;
31
use LeadersLinked\Mapper\UserSkillMapper;
32
 
33
use LeadersLinked\Model\UserSkill;
34
use LeadersLinked\Mapper\UserMapper;
35
use LeadersLinked\Form\UserProfile\ExtendedForm;
36
use LeadersLinked\Form\UserProfile\LocationForm;
37
use LeadersLinked\Model\Location;
38
use LeadersLinked\Form\UserProfile\SocialNetworkForm;
39
use LeadersLinked\Form\UserProfile\EducationForm;
40
use LeadersLinked\Model\UserEducation;
41
use LeadersLinked\Mapper\UserEducationMapper;
42
use LeadersLinked\Mapper\DegreeMapper;
43
use LeadersLinked\Form\UserProfile\ExperienceForm;
44
use LeadersLinked\Mapper\AptitudeMapper;
45
use LeadersLinked\Mapper\LanguageMapper;
46
use LeadersLinked\Mapper\UserAptitudeMapper;
47
use LeadersLinked\Mapper\UserExperienceMapper;
48
use LeadersLinked\Mapper\IndustryMapper;
49
use LeadersLinked\Mapper\CompanySizeMapper;
50
use LeadersLinked\Model\UserExperience;
51
use LeadersLinked\Mapper\ConnectionMapper;
52
use LeadersLinked\Form\UserProfile\ImageForm;
53
use LeadersLinked\Form\UserProfile\CoverForm;
54
use LeadersLinked\Mapper\SkillMapper;
55
use LeadersLinked\Form\MyProfiles\CreateForm;
56
use LeadersLinked\Form\UserProfile\AptitudeForm;
57
use LeadersLinked\Model\UserAptitude;
58
use LeadersLinked\Form\UserProfile\HobbyAndInterestForm;
59
use LeadersLinked\Mapper\HobbyAndInterestMapper;
60
use LeadersLinked\Mapper\UserHobbyAndInterestMapper;
61
use LeadersLinked\Model\UserHobbyAndInterest;
283 www 62
use LeadersLinked\Library\Storage;
1 efrain 63
 
64
 
65
class MyProfilesController extends AbstractActionController
66
{
67
    /**
68
     *
69
     * @var \Laminas\Db\Adapter\AdapterInterface
70
     */
71
    private $adapter;
596 ariadna 72
 
1 efrain 73
    /**
74
     *
75
     * @var \LeadersLinked\Cache\CacheInterface
76
     */
77
    private $cache;
596 ariadna 78
 
79
 
1 efrain 80
    /**
81
     *
82
     * @var \Laminas\Log\LoggerInterface
83
     */
84
    private $logger;
596 ariadna 85
 
1 efrain 86
    /**
87
     *
88
     * @var array
89
     */
90
    private $config;
596 ariadna 91
 
92
 
1 efrain 93
    /**
94
     *
95
     * @var \Laminas\Mvc\I18n\Translator
96
     */
97
    private $translator;
596 ariadna 98
 
99
 
1 efrain 100
    /**
101
     *
102
     * @param \Laminas\Db\Adapter\AdapterInterface $adapter
103
     * @param \LeadersLinked\Cache\CacheInterface $cache
104
     * @param \Laminas\Log\LoggerInterface LoggerInterface $logger
105
     * @param array $config
106
     * @param \Laminas\Mvc\I18n\Translator $translator
107
     */
108
    public function __construct($adapter, $cache, $logger, $config, $translator)
109
    {
110
        $this->adapter      = $adapter;
111
        $this->cache        = $cache;
112
        $this->logger       = $logger;
113
        $this->config       = $config;
114
        $this->translator   = $translator;
115
    }
116
 
117
    /**
118
     *
119
     * Generación del listado de perfiles
120
     * {@inheritDoc}
121
     * @see \Laminas\Mvc\Controller\AbstractActionController::indexAction()
122
     */
123
    public function indexAction()
124
    {
596 ariadna 125
        // Obtener el usuario actual del sistema
1 efrain 126
        $currentUserPlugin = $this->plugin('currentUserPlugin');
127
        $currentUser = $currentUserPlugin->getUser();
128
 
596 ariadna 129
        // Obtener la petición HTTP
1 efrain 130
        $request = $this->getRequest();
131
        if ($request->isGet()) {
596 ariadna 132
            // Sanitizar el parámetro de búsqueda si existe
133
            $search = Functions::sanitizeFilterString($this->params()->fromQuery('search'));
1 efrain 134
 
596 ariadna 135
            // Obtener el control de acceso (ACL) para verificar permisos
136
            $acl = $this->getEvent()->getViewModel()->getVariable('acl');
137
            // Verificar permisos para diferentes acciones
138
            $allowView = $acl->isAllowed($currentUser->usertype_id, 'profile/view');
139
            $allowEdit = $acl->isAllowed($currentUser->usertype_id, 'profile/my-profiles/edit');
140
            $allowDelete = $acl->isAllowed($currentUser->usertype_id, 'profile/my-profiles/delete');
1 efrain 141
 
596 ariadna 142
            // Inicializar el sistema de almacenamiento para manejar imágenes
143
            $storage = Storage::getInstance($this->config, $this->adapter);
1 efrain 144
 
596 ariadna 145
            // Obtener el mapper de perfiles de usuario
146
            $userProfileMapper = UserProfileMapper::getInstance($this->adapter);
147
            // Obtener todos los perfiles del usuario actual, opcionalmente filtrados por búsqueda
148
            $records  = $userProfileMapper->fetchAllByUserIdAndSearch($currentUser->id, $search);
1 efrain 149
 
596 ariadna 150
            // Preparar el array de items para la respuesta
151
            $items = [];
152
            foreach ($records as $record) {
153
                // Construir cada item con la información del perfil
154
                $item = [
155
                    'id' => $record->id,
156
                    'name' => $record->name,
157
                    'image' => $storage->getUserProfileImage($currentUser, $record),
158
                    'link_view' => $allowView ? $this->url()->fromRoute('profile/view', ['id' => $record->uuid])  : '',
159
                    'link_edit' => $allowEdit ? $this->url()->fromRoute('profile/my-profiles/edit', ['id' => $record->uuid])  : '',
160
                    'link_delete' => $allowDelete && $record->public == UserProfile::PUBLIC_NO ? $this->url()->fromRoute('profile/my-profiles/delete', ['id' => $record->uuid]) : '',
161
                ];
1 efrain 162
 
596 ariadna 163
                array_push($items, $item);
164
            }
1 efrain 165
 
596 ariadna 166
            // Preparar la respuesta exitosa con los items
167
            $response = [
168
                'success' => true,
169
                'data' => $items
170
            ];
1 efrain 171
 
596 ariadna 172
            return new JsonModel($response);
1 efrain 173
        } else {
596 ariadna 174
            // Si no es una petición GET, devolver error
1 efrain 175
            return new JsonModel([
176
                'success' => false,
177
                'data' => 'ERROR_METHOD_NOT_ALLOWED'
178
            ]);
179
        }
180
    }
181
 
182
 
183
 
184
    /**
185
     *
186
     * Agregar un nuevo perfil
187
     * @return \Laminas\View\Model\JsonModel
188
     */
189
    public function addAction()
190
    {
191
        $request = $this->getRequest();
192
 
193
 
194
        if ($request->isPost()) {
195
            $form = new  CreateForm();
196
            $dataPost = $request->getPost()->toArray();
197
 
198
            $form->setData($dataPost);
199
 
200
            if ($form->isValid()) {
201
                $dataPost = (array) $form->getData();
202
 
203
                $hydrator = new ObjectPropertyHydrator();
204
                $userProfile = new UserProfile();
205
                $hydrator->hydrate($dataPost, $userProfile);
206
 
207
                $currentUserPlugin = $this->plugin('currentUserPlugin');
208
                $currentUser = $currentUserPlugin->getUser();
209
 
210
                $userProfile->uuid = Functions::genUUID();
211
                $userProfile->user_id = $currentUser->id;
212
                $userProfile->public = \LeadersLinked\Model\UserProfile::PUBLIC_NO;
213
 
214
                $userProfileMapper = UserProfileMapper::getInstance($this->adapter);
215
                $result = $userProfileMapper->insert($userProfile);
216
 
217
                if ($result) {
218
                    $this->logger->info('Se agrego el perfil ' . ($userProfile->public == UserProfile::PUBLIC_YES ? 'público' : $userProfile->name), ['user_id' => $userProfile->user_id, 'ip' => Functions::getUserIP()]);
219
 
220
                    $data = [
221
                        'success'   => true,
222
                        'data'   => 'LABEL_RECORD_ADDED'
223
                    ];
224
                } else {
225
                    $data = [
226
                        'success'   => false,
227
                        'data'      => $userProfile->getError()
228
                    ];
229
                }
230
 
231
                return new JsonModel($data);
232
            } else {
233
                $messages = [];
234
                $form_messages = (array) $form->getMessages();
235
                foreach ($form_messages  as $fieldname => $field_messages) {
236
 
237
                    $messages[$fieldname] = array_values($field_messages);
238
                }
239
 
240
                return new JsonModel([
241
                    'success'   => false,
242
                    'data'   => $messages
243
                ]);
244
            }
245
        } else {
246
            $data = [
247
                'success' => false,
248
                'data' => 'ERROR_METHOD_NOT_ALLOWED'
249
            ];
250
 
251
            return new JsonModel($data);
252
        }
253
 
254
        return new JsonModel($data);
255
    }
256
 
257
    /**
258
     *
259
     * Borrar un perfil excepto el público
260
     * @return \Laminas\View\Model\JsonModel
261
     */
262
    public function deleteAction()
263
    {
264
        $currentUserPlugin = $this->plugin('currentUserPlugin');
265
        $currentUser = $currentUserPlugin->getUser();
266
 
267
        $request = $this->getRequest();
268
        $id = $this->params()->fromRoute('id');
269
 
270
        if (!$id) {
553 stevensc 271
            // Use helper for consistency
272
            return $this->_createSimpleErrorResponse('ERROR_INVALID_PARAMETER');
1 efrain 273
        }
274
 
275
        $userProfileMapper = UserProfileMapper::getInstance($this->adapter);
276
        $userProfile = $userProfileMapper->fetchOneByUuid($id);
277
        if (!$userProfile) {
596 ariadna 278
            // Use helper for consistency
553 stevensc 279
            return $this->_createSimpleErrorResponse('ERROR_RECORD_NOT_FOUND');
1 efrain 280
        }
281
 
553 stevensc 282
        // Authorize: Check if current user owns the profile
1 efrain 283
        if ($currentUser->id != $userProfile->user_id) {
596 ariadna 284
            // Use helper for consistency
553 stevensc 285
            return $this->_createSimpleErrorResponse('ERROR_UNAUTHORIZED');
286
        }
1 efrain 287
 
553 stevensc 288
        // Prevent deletion of the public profile
289
        if ($userProfile->public == UserProfile::PUBLIC_YES) {
290
            // Use helper for consistency
291
            return $this->_createSimpleErrorResponse('ERROR_PUBLIC_PROFILE');
1 efrain 292
        }
293
 
553 stevensc 294
        if ($request->isPost()) {
295
            $storage = Storage::getInstance($this->config, $this->adapter);
296
            $target_path = $storage->getPathUser();
297
            $user_uuid = $currentUser->uuid; // Assuming user UUID matches profile owner's UUID for path
1 efrain 298
 
553 stevensc 299
            // Attempt to delete associated files first
300
            $image_deleted = true;
301
            if ($userProfile->image) {
302
                $image_deleted = $storage->deleteFile($target_path, $user_uuid, $userProfile->image);
303
                if (!$image_deleted) {
304
                    $this->logger->err("Failed to delete profile image file: {$target_path}/{$user_uuid}/{$userProfile->image}", ['user_id' => $userProfile->user_id]);
305
                    // Decide if this is a critical error. Proceeding with DB deletion for now.
306
                }
307
            }
308
            $cover_deleted = true;
309
            if ($userProfile->cover) {
310
                $cover_deleted = $storage->deleteFile($target_path, $user_uuid, $userProfile->cover);
596 ariadna 311
                if (!$cover_deleted) {
553 stevensc 312
                    $this->logger->err("Failed to delete profile cover file: {$target_path}/{$user_uuid}/{$userProfile->cover}", ['user_id' => $userProfile->user_id]);
313
                    // Decide if this is a critical error. Proceeding with DB deletion for now.
314
                }
315
            }
1 efrain 316
 
553 stevensc 317
            // Delete the database record
1 efrain 318
            $result = $userProfileMapper->delete($userProfile);
319
            if ($result) {
320
                $this->logger->info('Se borro el perfil ' . ($userProfile->public == UserProfile::PUBLIC_YES ? 'público' : $userProfile->name), ['user_id' => $userProfile->user_id, 'ip' => Functions::getUserIP()]);
321
 
553 stevensc 322
                // Success response
1 efrain 323
                $data = [
324
                    'success' => true,
325
                    'data' => 'LABEL_RECORD_DELETED'
326
                ];
327
            } else {
553 stevensc 328
                // Use helper for DB error
329
                $data = $this->_createSimpleErrorResponse($userProfileMapper->getError() ?: 'ERROR_THERE_WAS_AN_ERROR');
1 efrain 330
            }
331
        } else {
553 stevensc 332
            // Use helper for method error
333
            $data = $this->_createSimpleErrorResponse('ERROR_METHOD_NOT_ALLOWED');
1 efrain 334
        }
335
 
553 stevensc 336
        // Return JsonModel for all paths
337
        return $data instanceof JsonModel ? $data : new JsonModel($data);
1 efrain 338
    }
339
 
340
    /**
596 ariadna 341
     * Presenta el perfil con las opciones de edición de cada sección.
342
     * Este método:
343
     * - Obtiene y valida el perfil del usuario
344
     * - Recopila toda la información relacionada (educación, experiencia, habilidades, etc.)
345
     * - Prepara los datos para la vista de edición
346
     * - Genera las URLs necesarias para las diferentes acciones de edición
347
     *
1 efrain 348
     * @return \Laminas\Http\Response|\Laminas\View\Model\ViewModel|\Laminas\View\Model\JsonModel
349
     */
350
    public function editAction()
351
    {
596 ariadna 352
        // Obtener el usuario actual del sistema
1 efrain 353
        $currentUserPlugin = $this->plugin('currentUserPlugin');
354
        $currentUser = $currentUserPlugin->getUser();
355
 
596 ariadna 356
        // Obtener el plugin para mensajes flash
1 efrain 357
        $flashMessenger = $this->plugin('FlashMessenger');
358
 
596 ariadna 359
        // Obtener parámetros de la petición
1 efrain 360
        $request = $this->getRequest();
361
        $id = $this->params()->fromRoute('id');
362
 
596 ariadna 363
        // Validar que se proporcionó un ID
1 efrain 364
        if (!$id) {
365
            $flashMessenger->addErrorMessage('ERROR_INVALID_PARAMETER');
366
            return $this->redirect()->toRoute('dashboard');
367
        }
368
 
596 ariadna 369
        // Obtener el perfil de usuario correspondiente
1 efrain 370
        $userProfileMapper = UserProfileMapper::getInstance($this->adapter);
371
        $userProfile = $userProfileMapper->fetchOneByUuid($id);
372
 
596 ariadna 373
        // Validar que el perfil existe
1 efrain 374
        if (!$userProfile) {
375
            $flashMessenger->addErrorMessage('ERROR_RECORD_NOT_FOUND');
376
            return $this->redirect()->toRoute('dashboard');
377
        }
378
 
596 ariadna 379
        // Verificar que el usuario actual es el propietario del perfil
1 efrain 380
        if ($currentUser->id != $userProfile->user_id) {
381
            $flashMessenger->addErrorMessage('ERROR_UNAUTHORIZED');
382
            return $this->redirect()->toRoute('dashboard');
383
        }
384
 
596 ariadna 385
        // Determinar la clave de API de Google Maps según el entorno
1 efrain 386
        $sandbox = $this->config['leaderslinked.runmode.sandbox'];
387
        if ($sandbox) {
388
            $google_map_key  = $this->config['leaderslinked.google_map.sandbox_api_key'];
389
        } else {
390
            $google_map_key  = $this->config['leaderslinked.google_map.production_api_key'];
391
        }
392
 
596 ariadna 393
        // Procesar solo peticiones GET
1 efrain 394
        if ($request->isGet()) {
596 ariadna 395
            // Obtener información de ubicación si existe
1 efrain 396
            if ($userProfile->location_id) {
397
                $locationMapper = LocationMapper::getInstance($this->adapter);
398
                $location = $locationMapper->fetchOne($userProfile->location_id);
399
 
400
                $formattedAddress = $location->formatted_address;
401
                $country = $location->country;
402
            } else {
403
                $formattedAddress = '';
404
                $country = '';
405
            }
406
 
596 ariadna 407
            // Obtener información del usuario
1 efrain 408
            $userMapper = UserMapper::getInstance($this->adapter);
409
            $user = $userMapper->fetchOne($userProfile->user_id);
410
 
596 ariadna 411
            // Obtener idiomas del usuario
1 efrain 412
            $userLanguages = [];
413
            $languageMapper = LanguageMapper::getInstance($this->adapter);
414
            $userLanguageMapper = UserLanguageMapper::getInstance($this->adapter);
415
            $records = $userLanguageMapper->fetchAllByUserProfileId($userProfile->id);
416
            foreach ($records as $record) {
417
                $language = $languageMapper->fetchOne($record->language_id);
418
                $userLanguages[$language->id] = $language->name;
419
            }
420
 
596 ariadna 421
            // Obtener educación del usuario
1 efrain 422
            $locationMapper = LocationMapper::getInstance($this->adapter);
423
            $degreeMapper = DegreeMapper::getInstance($this->adapter);
424
            $userEducationMapper = UserEducationMapper::getInstance($this->adapter);
425
            $userEducations = $userEducationMapper->fetchAllByUserProfileId($userProfile->id);
426
 
596 ariadna 427
            // Formatear información de educación
1 efrain 428
            foreach ($userEducations  as &$userEducation) {
429
                $location = $locationMapper->fetchOne($userEducation->location_id);
430
                $degree = $degreeMapper->fetchOne($userEducation->degree_id);
431
 
432
                $userEducation = [
433
                    'university' => $userEducation->university,
434
                    'degree' => $degree->name,
435
                    'field_of_study' => $userEducation->field_of_study,
436
                    'grade_or_percentage' => $userEducation->grade_or_percentage,
437
                    'formatted_address' => $location->formatted_address,
438
                    'from_year' => $userEducation->from_year,
439
                    'to_year' => $userEducation->to_year,
440
                    'description' => $userEducation->description,
350 www 441
                    'link_edit' => $this->url()->fromRoute('profile/my-profiles/education', ['id' => $userProfile->uuid, 'operation' => 'edit', 'user_education_id' => $userEducation->uuid]),
442
                    'link_delete' => $this->url()->fromRoute('profile/my-profiles/education', ['id' => $userProfile->uuid, 'operation' => 'delete', 'user_education_id' => $userEducation->uuid]),
1 efrain 443
                ];
444
            }
445
 
596 ariadna 446
            // Obtener experiencia laboral del usuario
1 efrain 447
            $industryMapper = IndustryMapper::getInstance($this->adapter);
448
            $companySizeMapper = CompanySizeMapper::getInstance($this->adapter);
449
            $userExperienceMapper = UserExperienceMapper::getInstance($this->adapter);
450
            $userExperiences = $userExperienceMapper->fetchAllByUserProfileId($userProfile->id);
451
 
596 ariadna 452
            // Formatear información de experiencia laboral
1 efrain 453
            foreach ($userExperiences  as &$userExperience) {
454
                $location = $locationMapper->fetchOne($userExperience->location_id);
455
                $companySize = $companySizeMapper->fetchOne($userExperience->company_size_id);
456
                $industry = $industryMapper->fetchOne($userExperience->industry_id);
457
 
458
                $userExperience = [
459
                    'company' => $userExperience->company,
460
                    'industry' => $industry->name,
461
                    'size' => $companySize->name . ' (' . $companySize->minimum_no_of_employee . '-' . $companySize->maximum_no_of_employee . ')',
462
                    'title' => $userExperience->title,
463
                    'formatted_address' => $location->formatted_address,
464
                    'from_year' => $userExperience->from_year,
465
                    'from_month' => $userExperience->from_month,
466
                    'to_year' => $userExperience->to_year,
467
                    'to_month' => $userExperience->to_month,
468
                    'description' => $userExperience->description,
469
                    'is_current' => $userExperience->is_current,
350 www 470
                    'link_edit' => $this->url()->fromRoute('profile/my-profiles/experience', ['id' => $userProfile->uuid, 'operation' => 'edit', 'user_experience_id' => $userExperience->uuid]),
471
                    'link_delete' => $this->url()->fromRoute('profile/my-profiles/experience', ['id' => $userProfile->uuid, 'operation' => 'delete', 'user_experience_id' => $userExperience->uuid])
1 efrain 472
                ];
473
            }
474
 
596 ariadna 475
            // Obtener aptitudes del usuario
1 efrain 476
            $userAptitudes = [];
477
            $aptitudeMapper = AptitudeMapper::getInstance($this->adapter);
478
            $userAptitudeMapper = UserAptitudeMapper::getInstance($this->adapter);
479
            $records  = $userAptitudeMapper->fetchAllByUserProfileId($userProfile->id);
480
            foreach ($records as $record) {
481
                $aptitude = $aptitudeMapper->fetchOne($record->aptitude_id);
482
                if ($aptitude) {
483
                    $userAptitudes[$aptitude->uuid] = $aptitude->name;
484
                }
485
            }
486
 
596 ariadna 487
            // Obtener hobbies e intereses del usuario
1 efrain 488
            $userHobbiesAndInterests = [];
489
            $hobbyAndInterestMapper = HobbyAndInterestMapper::getInstance($this->adapter);
490
            $userHobbyAndInterestMapper = UserHobbyAndInterestMapper::getInstance($this->adapter);
491
            $records  = $userHobbyAndInterestMapper->fetchAllByUserProfileId($userProfile->id);
492
            foreach ($records as $record) {
493
                $hobbyAndInterest = $hobbyAndInterestMapper->fetchOne($record->hobby_and_interest_id);
494
                if ($hobbyAndInterest) {
495
                    $userHobbiesAndInterests[$hobbyAndInterest->uuid] = $hobbyAndInterest->name;
496
                }
497
            }
498
 
596 ariadna 499
            // Obtener habilidades del usuario
1 efrain 500
            $userSkills = [];
501
            $userSkillMapper = UserSkillMapper::getInstance($this->adapter);
502
            $skillMapper = SkillMapper::getInstance($this->adapter);
503
            $records  = $userSkillMapper->fetchAllByUserProfileId($userProfile->id);
504
            foreach ($records as $record) {
505
                $skill = $skillMapper->fetchOne($record->skill_id);
506
                $userSkills[$skill->uuid] = $skill->name;
507
            }
508
 
596 ariadna 509
            // Obtener estadísticas de conexiones
1 efrain 510
            $companyFollowerMapper = CompanyFollowerMapper::getInstance($this->adapter);
511
            $following = $companyFollowerMapper->getCountFollowing($user->id);
512
 
513
            $connectionMapper = ConnectionMapper::getInstance($this->adapter);
514
            $follower = $connectionMapper->fetchTotalConnectionByUser($user->id);
515
 
596 ariadna 516
            // Obtener configuraciones de tamaño de imágenes
1 efrain 517
            $image_size_cover = $this->config['leaderslinked.image_sizes.user_cover_upload'];
518
            $image_size_profile = $this->config['leaderslinked.image_sizes.user_upload'];
519
 
596 ariadna 520
            // Inicializar el sistema de almacenamiento
333 www 521
            $storage = Storage::getInstance($this->config, $this->adapter);
1 efrain 522
 
596 ariadna 523
            // Preparar datos para la respuesta
524
            $data = [
525
                'following'         => $following,
526
                'follower'          => $follower,
527
                'user_id'           => $user->id,
528
                'user_uuid'         => $user->uuid,
529
                'full_name'         => trim($user->first_name . ' ' . $user->last_name),
530
                'user_profile_id'   => $userProfile->id,
531
                'user_profile_uuid' => $userProfile->uuid,
532
                'image'             => $storage->getUserProfileImage($currentUser, $userProfile),
533
                'cover'             => $storage->getUserProfileCover($currentUser, $userProfile),
534
                'overview'          => $userProfile->description,
535
                'facebook'          => $userProfile->facebook,
536
                'instagram'         => $userProfile->instagram,
537
                'twitter'           => $userProfile->twitter,
538
                'formatted_address' => $formattedAddress,
539
                'country'           => $country,
540
                'user_skills'       => $userSkills,
541
                'user_languages'    => $userLanguages,
542
                'user_educations'   => $userEducations,
543
                'user_experiences'  => $userExperiences,
544
                'user_aptitudes'                => $userAptitudes,
545
                'user_hobbies_and_interests'    => $userHobbiesAndInterests,
546
                'image_size_cover' =>  $image_size_cover,
547
                'image_size_profile' => $image_size_profile,
348 www 548
 
596 ariadna 549
                // Generar URLs para las diferentes acciones de edición
550
                'link_extended' => $this->url()->fromRoute('profile/my-profiles/extended', ['id' => $userProfile->uuid]),
551
                'link_image_upload' => $this->url()->fromRoute('profile/my-profiles/image', ['id' => $userProfile->uuid, 'operation' => 'upload']),
552
                'link_image_delete' => $this->url()->fromRoute('profile/my-profiles/image', ['id' => $userProfile->uuid, 'operation' => 'delete']),
553
                'link_cover_upload' => $this->url()->fromRoute('profile/my-profiles/cover', ['id' => $userProfile->uuid, 'operation' => 'upload']),
554
                'link_cover_delete' => $this->url()->fromRoute('profile/my-profiles/cover', ['id' => $userProfile->uuid, 'operation' => 'delete']),
555
                'link_experience_add' => $this->url()->fromRoute('profile/my-profiles/experience', ['id' => $userProfile->uuid, 'operation' => 'add']),
556
                'link_education_add' => $this->url()->fromRoute('profile/my-profiles/education', ['id' => $userProfile->uuid, 'operation' => 'add']),
557
                'link_language' => $this->url()->fromRoute('profile/my-profiles/language', ['id' => $userProfile->uuid]),
558
                'link_location' => $this->url()->fromRoute('profile/my-profiles/location', ['id' => $userProfile->uuid]),
559
                'link_skill' => $this->url()->fromRoute('profile/my-profiles/skill', ['id' => $userProfile->uuid]),
560
                'link_social_network' => $this->url()->fromRoute('profile/my-profiles/social-network', ['id' => $userProfile->uuid]),
561
                'link_aptitude' => $this->url()->fromRoute('profile/my-profiles/aptitude', ['id' => $userProfile->uuid]),
562
                'link_hobby_and_interest' => $this->url()->fromRoute('profile/my-profiles/hobby-and-interest', ['id' => $userProfile->uuid]),
563
            ];
1 efrain 564
 
596 ariadna 565
            return new JsonModel($data);
1 efrain 566
        } else {
596 ariadna 567
            // Si no es una petición GET, devolver error
1 efrain 568
            $data = [
569
                'success' => false,
570
                'data' => 'ERROR_METHOD_NOT_ALLOWED'
571
            ];
572
 
573
            return new JsonModel($data);
574
        }
575
 
576
        return new JsonModel($data);
577
    }
578
 
579
    /**
580
     * Actualización de las habilidades
581
     * @return \Laminas\View\Model\JsonModel
582
     */
583
    public function skillAction()
584
    {
585
        $currentUserPlugin = $this->plugin('currentUserPlugin');
586
        $currentUser = $currentUserPlugin->getUser();
587
 
588
        $user_profile_id = $this->params()->fromRoute('id');
589
        $userProfileMapper = UserProfileMapper::getInstance($this->adapter);
590
 
591
        $userProfile = $userProfileMapper->fetchOneByUuid($user_profile_id);
592
        if (!$userProfile) {
593
            $response = [
594
                'success' => false,
595
                'data' => 'ERROR_INVALID_PARAMETER'
596
            ];
597
 
598
            return new JsonModel($response);
599
        }
600
 
601
        if ($currentUser->id != $userProfile->user_id) {
602
            $response = [
603
                'success' => false,
604
                'data' => 'ERROR_UNAUTHORIZED'
605
            ];
606
 
607
            return new JsonModel($response);
608
        }
609
 
610
 
611
 
612
        $request = $this->getRequest();
613
        if ($request->isGet()) {
614
            $skillMapper = SkillMapper::getInstance($this->adapter);
615
 
616
 
617
            $userSkillMapper = UserSkillMapper::getInstance($this->adapter);
618
            $userSkills  = $userSkillMapper->fetchAllByUserProfileId($userProfile->id);
619
 
620
            $items = [];
621
            foreach ($userSkills as $userSkill) {
622
                $skill = $skillMapper->fetchOne($userSkill->skill_id);
623
                array_push($items, $skill->uuid);
624
            }
625
 
626
            $data = [
627
                'success' => true,
628
                'data' => $items
629
            ];
630
 
631
            return new JsonModel($data);
632
        } else if ($request->isPost()) {
633
 
634
            $form = new SkillForm($this->adapter);
635
            $dataPost = $request->getPost()->toArray();
636
 
637
            $form->setData($dataPost);
638
 
639
            if ($form->isValid()) {
640
                $this->logger->info('Se actualizaron las habilidades del perfil ' . ($userProfile->public == UserProfile::PUBLIC_YES ? 'público' : $userProfile->name), ['user_id' => $userProfile->user_id, 'ip' => Functions::getUserIP()]);
641
 
642
                $skillMapper = SkillMapper::getInstance($this->adapter);
643
 
644
 
645
                $userSkillMapper = UserSkillMapper::getInstance($this->adapter);
646
                $userSkillMapper->deleteByUserProfileId($userProfile->id);
647
 
648
                $dataPost = (array) $form->getData();
649
                $skills = $dataPost['skills'];
650
                foreach ($skills as $skill_uuid) {
651
 
652
                    $skill = $skillMapper->fetchOneByUuid($skill_uuid);
653
 
654
 
655
 
656
                    $userSkill = new UserSkill();
657
                    $userSkill->user_id = $userProfile->user_id;
658
                    $userSkill->user_profile_id = $userProfile->id;
659
                    $userSkill->skill_id =  $skill->id;
660
 
661
                    $userSkillMapper->insert($userSkill);
662
                }
663
 
664
                $items = [];
665
 
666
                $records = $userSkillMapper->fetchAllByUserProfileId($userProfile->id);
667
                foreach ($records as $record) {
668
                    $skill = $skillMapper->fetchOne($record->skill_id);
669
                    array_push($items,  ['value' => $skill->uuid, 'label' => $skill->name]);
670
                }
671
 
672
                return new JsonModel([
673
                    'success'   => true,
674
                    'data'   => $items
675
                ]);
676
            } else {
677
                $messages = [];
678
                $form_messages = (array) $form->getMessages();
679
                foreach ($form_messages  as $fieldname => $field_messages) {
680
                    $messages[$fieldname] = array_values($field_messages);
681
                }
682
 
683
                return new JsonModel([
684
                    'success'   => false,
685
                    'data'   => $messages
686
                ]);
687
            }
688
        }
689
 
690
 
691
        $data = [
692
            'success' => false,
693
            'data' => 'ERROR_METHOD_NOT_ALLOWED'
694
        ];
695
 
696
 
697
        return new JsonModel($data);
698
    }
699
 
700
    /**
701
     * Actualización de los idiomas
622 ariadna 702
     *
703
     * Esta acción maneja la lógica para obtener y actualizar los idiomas asociados
704
     * a un perfil de usuario específico.
705
     * - En una petición GET, devuelve la lista actual de IDs de idiomas del perfil.
706
     * - En una petición POST, valida los datos del formulario, actualiza los idiomas
707
     *   (borrando los antiguos y añadiendo los nuevos) y devuelve la nueva lista
708
     *   de idiomas con su ID y nombre.
709
     *
710
     * @return \Laminas\View\Model\JsonModel Retorna un modelo JSON con el resultado de la operación.
711
     *         - success (bool): Indica si la operación fue exitosa.
712
     *         - data (array|string):
713
     *           - En GET exitoso: Array de IDs de idiomas.
714
     *           - En POST exitoso: Array de objetos idioma (con 'value' => id, 'label' => nombre).
715
     *           - En error: Mensaje de error o array de mensajes de validación del formulario.
1 efrain 716
     */
717
    public function languageAction()
718
    {
622 ariadna 719
        // Obtener el usuario actualmente autenticado
1 efrain 720
        $currentUserPlugin = $this->plugin('currentUserPlugin');
721
        $currentUser = $currentUserPlugin->getUser();
722
 
622 ariadna 723
        // Obtener el ID del perfil de usuario desde los parámetros de la ruta
1 efrain 724
        $user_profile_id = $this->params()->fromRoute('id');
725
        $userProfileMapper = UserProfileMapper::getInstance($this->adapter);
726
 
622 ariadna 727
        // Buscar el perfil de usuario por su UUID
1 efrain 728
        $userProfile = $userProfileMapper->fetchOneByUuid($user_profile_id);
622 ariadna 729
        // Si el perfil no se encuentra, devolver error
1 efrain 730
        if (!$userProfile) {
731
            $response = [
732
                'success' => false,
733
                'data' => 'ERROR_INVALID_PARAMETER'
734
            ];
735
 
736
            return new JsonModel($response);
737
        }
738
 
622 ariadna 739
        // Verificar que el usuario actual es el propietario del perfil
1 efrain 740
        if ($currentUser->id != $userProfile->user_id) {
741
            $response = [
742
                'success' => false,
743
                'data' => 'ERROR_UNAUTHORIZED'
744
            ];
745
 
746
            return new JsonModel($response);
747
        }
748
 
749
 
622 ariadna 750
        // Obtener la petición HTTP actual
1 efrain 751
        $request = $this->getRequest();
622 ariadna 752
        // Procesar si la petición es GET
1 efrain 753
        if ($request->isGet()) {
622 ariadna 754
            // Registrar la acción (aunque es un GET, se registra como actualización, revisar si es intencional)
1 efrain 755
            $this->logger->info('Se actualizaron los idiomas del perfil ' . ($userProfile->public == UserProfile::PUBLIC_YES ? 'público' : $userProfile->name), ['user_id' => $userProfile->user_id, 'ip' => Functions::getUserIP()]);
756
 
622 ariadna 757
            // Obtener los idiomas asociados al perfil
1 efrain 758
            $userLanguageMapper = UserLanguageMapper::getInstance($this->adapter);
759
            $languages  = $userLanguageMapper->fetchAllByUserProfileId($userProfile->id);
760
 
622 ariadna 761
            // Preparar un array con los IDs de los idiomas
1 efrain 762
            $items = [];
763
            foreach ($languages as $language) {
764
                array_push($items, $language->language_id);
765
            }
766
 
767
            $data = [
768
                'success' => true,
769
                'data' => $items
770
            ];
771
 
772
            return new JsonModel($data);
622 ariadna 773
            // Procesar si la petición es POST
1 efrain 774
        } else if ($request->isPost()) {
622 ariadna 775
            // Instanciar el formulario de idiomas
1 efrain 776
            $form = new LanguageForm($this->adapter);
777
            $dataPost = $request->getPost()->toArray();
778
 
622 ariadna 779
            // Establecer los datos del POST en el formulario
1 efrain 780
            $form->setData($dataPost);
781
 
622 ariadna 782
            // Validar el formulario
1 efrain 783
            if ($form->isValid()) {
622 ariadna 784
                // Mappers para idiomas y la relación usuario-idioma
1 efrain 785
                $languageMapper = LanguageMapper::getInstance($this->adapter);
786
                $userLanguageMapper = UserLanguageMapper::getInstance($this->adapter);
622 ariadna 787
                // Ya no se eliminan todos los idiomas existentes, se añaden solo los nuevos.
1 efrain 788
 
622 ariadna 789
                // 1. Obtener los IDs de los idiomas actualmente asociados al perfil en la base de datos.
790
                $existingUserLanguages = $userLanguageMapper->fetchAllByUserProfileId($userProfile->id);
791
                $existingLanguageIdsInDB = [];
792
                foreach ($existingUserLanguages as $exUserLang) {
793
                    $existingLanguageIdsInDB[] = $exUserLang->language_id;
794
                }
795
 
796
                // Obtener los datos validados del formulario
1 efrain 797
                $dataPost = (array) $form->getData();
622 ariadna 798
                // Asegurarse de que $submittedLanguageIds es un array, incluso si está vacío.
799
                $submittedLanguageIds = isset($dataPost['languages']) && is_array($dataPost['languages']) ? $dataPost['languages'] : [];
1 efrain 800
 
622 ariadna 801
                // Iterar sobre los IDs de idiomas enviados desde el formulario
802
                foreach ($submittedLanguageIds as $submitted_language_id) {
803
                    // Verificar si este idioma ya está asociado al perfil del usuario
804
                    if (!in_array($submitted_language_id, $existingLanguageIdsInDB)) {
805
                        // El idioma no está asociado, proceder a añadirlo.
806
                        $language = $languageMapper->fetchOne($submitted_language_id); // Obtener el objeto idioma completo
1 efrain 807
 
622 ariadna 808
                        if ($language) { // Asegurarse de que el idioma existe en la tabla principal de idiomas
809
                            // Crear y configurar la nueva entidad de relación usuario-idioma
810
                            $userLanguage = new UserLanguage();
811
                            $userLanguage->user_id = $userProfile->user_id;
812
                            $userLanguage->user_profile_id = $userProfile->id;
813
                            $userLanguage->language_id = $language->id;
814
 
815
                            // Insertar el nuevo registro de idioma para el perfil
816
                            $userLanguageMapper->insert($userLanguage);
817
                        }
818
                    }
1 efrain 819
                }
820
 
622 ariadna 821
                // Preparar la respuesta con la lista actualizada de idiomas (ID y nombre)
822
                // Esta parte ahora reflejará los idiomas existentes más los nuevos añadidos.
1 efrain 823
                $items = [];
824
                $records = $userLanguageMapper->fetchAllByUserProfileId($userProfile->id);
825
                foreach ($records as $record) {
826
                    $language = $languageMapper->fetchOne($record->language_id);
827
                    array_push($items,  ['value' => $language->id, 'label' => $language->name]);
828
                }
829
 
830
                return new JsonModel([
831
                    'success'   => true,
832
                    'data'   => $items
833
                ]);
834
            } else {
622 ariadna 835
                // Si el formulario no es válido, obtener y devolver los mensajes de error
1 efrain 836
                $messages = [];
837
                $form_messages = (array) $form->getMessages();
838
                foreach ($form_messages  as $fieldname => $field_messages) {
839
                    $messages[$fieldname] = array_values($field_messages);
840
                }
841
 
842
                return new JsonModel([
843
                    'success'   => false,
844
                    'data'   => $messages
845
                ]);
846
            }
847
        }
848
 
849
 
850
        $data = [
851
            'success' => false,
852
            'data' => 'ERROR_METHOD_NOT_ALLOWED'
853
        ];
854
 
855
 
856
        return new JsonModel($data);
857
    }
858
 
859
    /**
860
     * Actualización de la descripción y cualquier otro campo extendido del perfil a futuro
861
     * @return \Laminas\View\Model\JsonModel
862
     */
863
    public function extendedAction()
864
    {
865
        $currentUserPlugin = $this->plugin('currentUserPlugin');
866
        $currentUser = $currentUserPlugin->getUser();
867
 
868
 
869
        $user_profile_id = $this->params()->fromRoute('id');
870
        $userProfileMapper = UserProfileMapper::getInstance($this->adapter);
871
 
872
        $userProfile = $userProfileMapper->fetchOneByUuid($user_profile_id);
873
        if (!$userProfile) {
874
            $response = [
875
                'success' => false,
876
                'data' => 'ERROR_INVALID_PARAMETER'
877
            ];
878
 
879
            return new JsonModel($response);
880
        }
881
 
882
        if ($currentUser->id != $userProfile->user_id) {
883
            $response = [
884
                'success' => false,
885
                'data' => 'ERROR_UNAUTHORIZED'
886
            ];
887
 
888
            return new JsonModel($response);
889
        }
890
 
891
 
892
 
893
        $request = $this->getRequest();
894
        if ($request->isGet()) {
895
            $data = [
896
                'success' => true,
897
                'data' => [
898
                    'description' => $userProfile->description,
899
                ]
900
            ];
901
 
902
            return new JsonModel($data);
903
        } else if ($request->isPost()) {
904
 
905
 
906
            $form = new ExtendedForm();
907
            $dataPost = $request->getPost()->toArray();
908
 
909
            $form->setData($dataPost);
910
 
911
            if ($form->isValid()) {
912
                $dataPost = (array) $form->getData();
913
 
914
                $hydrator = new ObjectPropertyHydrator();
915
                $hydrator->hydrate($dataPost, $userProfile);
916
 
917
                $userProfileMapper->updateExtended($userProfile);
918
 
919
                $this->logger->info('Se actualizo las descripción del perfil ' . ($userProfile->public == UserProfile::PUBLIC_YES ? 'público' : $userProfile->name), ['user_id' => $userProfile->user_id, 'ip' => Functions::getUserIP()]);
920
 
921
                return new JsonModel([
922
                    'success'   => true,
923
                    'data' => [
924
                        'description' => $userProfile->description,
925
                    ]
926
                ]);
927
            } else {
928
                $messages = [];
929
                $form_messages = (array) $form->getMessages();
930
                foreach ($form_messages  as $fieldname => $field_messages) {
931
                    $messages[$fieldname] = array_values($field_messages);
932
                }
933
 
934
                return new JsonModel([
935
                    'success'   => false,
936
                    'data'   => $messages
937
                ]);
938
            }
939
        }
940
 
941
 
942
        $data = [
943
            'success' => false,
944
            'data' => 'ERROR_METHOD_NOT_ALLOWED'
945
        ];
946
 
947
 
948
        return new JsonModel($data);
949
    }
950
 
951
    /**
952
     * Actualización de la ubucación
953
     * @return \Laminas\View\Model\JsonModel
954
     */
955
    public function locationAction()
956
    {
957
        $currentUserPlugin = $this->plugin('currentUserPlugin');
958
        $currentUser = $currentUserPlugin->getUser();
959
 
960
        $user_profile_id = $this->params()->fromRoute('id');
961
        $userProfileMapper = UserProfileMapper::getInstance($this->adapter);
962
 
963
        $userProfile = $userProfileMapper->fetchOneByUuid($user_profile_id);
964
        if (!$userProfile) {
965
            $response = [
966
                'success' => false,
967
                'data' => 'ERROR_INVALID_PARAMETER'
968
            ];
969
 
970
            return new JsonModel($response);
971
        }
972
 
973
 
974
        if ($currentUser->id != $userProfile->user_id) {
975
            $response = [
976
                'success' => false,
977
                'data' => 'ERROR_UNAUTHORIZED'
978
            ];
979
 
980
            return new JsonModel($response);
981
        }
982
 
983
 
984
 
985
        $request = $this->getRequest();
986
        if ($request->isPost()) {
987
 
988
            $form = new LocationForm();
989
            $dataPost = $request->getPost()->toArray();
990
 
991
            $form->setData($dataPost);
992
 
993
            if ($form->isValid()) {
994
                $this->logger->info('Se actualizaron la ubicación del perfil ' . ($userProfile->public == UserProfile::PUBLIC_YES ? 'público' : $userProfile->name), ['user_id' => $userProfile->user_id, 'ip' => Functions::getUserIP()]);
995
 
996
                $dataPost = (array) $form->getData();
997
 
998
                $location = new Location();
999
                $hydrator = new ObjectPropertyHydrator();
1000
                $hydrator->hydrate($dataPost, $location);
1001
 
1002
                $location->id = $userProfile->location_id ? $userProfile->location_id : null;
1003
 
1004
 
1005
 
1006
                $locationMapper = LocationMapper::getInstance($this->adapter);
1007
                if ($userProfile->location_id) {
1008
                    $result = $locationMapper->update($location);
1009
                } else {
1010
                    $result = $locationMapper->insert($location);
1011
 
1012
                    if ($result) {
1013
                        $userProfile->location_id = $location->id;
1014
                        $userProfileMapper->updateLocation($userProfile);
1015
                    }
1016
                }
1017
 
1018
                if ($result) {
1019
                    if ($userProfile->public == UserProfile::PUBLIC_YES) {
1020
                        $currentUser->location_id = $location->id;
1021
 
1022
                        $userMapper = UserMapper::getInstance($this->adapter);
1023
                        $userMapper->updateLocation($currentUser);
1024
                    }
1025
 
1026
 
1027
                    $response = [
1028
                        'success'   => true,
1029
                        'data' => [
1030
                            'formatted_address' => $location->formatted_address,
1031
                            'country' => $location->country,
1032
                        ]
1033
                    ];
1034
                } else {
1035
                    $response = [
1036
                        'success'   => false,
1037
                        'data' => 'ERROR_THERE_WAS_AN_ERROR'
1038
                    ];
1039
                }
1040
 
1041
 
1042
 
1043
                return new JsonModel($response);
1044
            } else {
1045
                return new JsonModel([
1046
                    'success'   => false,
1047
                    'data'   =>   'ERROR_PLACED_AUTOCOMPLETE_DOES_NOT_CONTAIN_GEOMETRY'
1048
                ]);
1049
            }
1050
        }
1051
 
1052
 
1053
        $data = [
1054
            'success' => false,
1055
            'data' => 'ERROR_METHOD_NOT_ALLOWED'
1056
        ];
1057
 
1058
 
1059
        return new JsonModel($data);
1060
    }
1061
 
1062
    /**
1063
     * Actualización de las redes sociales
1064
     * @return \Laminas\View\Model\JsonModel
1065
     */
1066
    public function socialNetworkAction()
1067
    {
1068
        $currentUserPlugin = $this->plugin('currentUserPlugin');
1069
        $currentUser = $currentUserPlugin->getUser();
1070
 
1071
        $user_profile_id = $this->params()->fromRoute('id');
1072
        $userProfileMapper = UserProfileMapper::getInstance($this->adapter);
1073
 
1074
        $userProfile = $userProfileMapper->fetchOneByUuid($user_profile_id);
1075
        if (!$userProfile) {
1076
            $response = [
1077
                'success' => false,
1078
                'data' => 'ERROR_INVALID_PARAMETER'
1079
            ];
1080
 
1081
            return new JsonModel($response);
1082
        }
1083
 
1084
 
1085
        if ($currentUser->id != $userProfile->user_id) {
1086
            $response = [
1087
                'success' => false,
1088
                'data' => 'ERROR_UNAUTHORIZED'
1089
            ];
1090
 
1091
            return new JsonModel($response);
1092
        }
1093
 
1094
 
1095
 
1096
        $request = $this->getRequest();
1097
        if ($request->isGet()) {
1098
            $data = [
1099
                'success' => true,
1100
                'data' => [
1101
                    'facebook' => $userProfile->facebook,
1102
                    'instagram' => $userProfile->instagram,
1103
                    'twitter' => $userProfile->twitter
1104
                ]
1105
            ];
1106
 
1107
            return new JsonModel($data);
1108
        } else if ($request->isPost()) {
1109
 
1110
            $form = new SocialNetworkForm();
1111
            $dataPost = $request->getPost()->toArray();
1112
 
1113
            $form->setData($dataPost);
1114
 
1115
            if ($form->isValid()) {
1116
                $this->logger->info('Se actualizaron las redes sociales del perfil ' . ($userProfile->public == UserProfile::PUBLIC_YES ? 'público' : $userProfile->name), ['user_id' => $userProfile->user_id, 'ip' => Functions::getUserIP()]);
1117
 
1118
                $dataPost = (array) $form->getData();
1119
 
1120
                $hydrator = new ObjectPropertyHydrator();
1121
                $hydrator->hydrate($dataPost, $userProfile);
1122
 
1123
                $userProfileMapper->updateSocialNetwork($userProfile);
1124
                return new JsonModel([
1125
                    'success'   => true,
1126
                    'data' => [
1127
                        'facebook' => $userProfile->facebook,
1128
                        'instagram' => $userProfile->instagram,
1129
                        'twitter' => $userProfile->twitter
1130
                    ]
1131
                ]);
1132
            } else {
1133
                $messages = [];
1134
                $form_messages = (array) $form->getMessages();
1135
                foreach ($form_messages  as $fieldname => $field_messages) {
1136
                    $messages[$fieldname] = array_values($field_messages);
1137
                }
1138
 
1139
                return new JsonModel([
1140
                    'success'   => false,
1141
                    'data'   => $messages
1142
                ]);
1143
            }
1144
        }
1145
 
1146
 
1147
        $data = [
1148
            'success' => false,
1149
            'data' => 'ERROR_METHOD_NOT_ALLOWED'
1150
        ];
1151
 
1152
 
1153
        return new JsonModel($data);
1154
    }
1155
 
383 www 1156
 
1157
 
596 ariadna 1158
 
1 efrain 1159
    /**
1160
     * Actualización de los registros de estudios realizados
1161
     * @return \Laminas\View\Model\JsonModel
1162
     */
1163
    public function  educationAction()
1164
    {
1165
 
1166
        $currentUserPlugin = $this->plugin('currentUserPlugin');
1167
        $currentUser = $currentUserPlugin->getUser();
1168
 
1169
        $user_profile_id    = $this->params()->fromRoute('id');
1170
        $user_education_id  = $this->params()->fromRoute('user_education_id');
1171
        $operation          = $this->params()->fromRoute('operation');
1172
 
1173
        $userProfileMapper = UserProfileMapper::getInstance($this->adapter);
1174
 
1175
        $userProfile = $userProfileMapper->fetchOneByUuid($user_profile_id);
1176
        if (!$userProfile) {
1177
            $response = [
1178
                'success' => false,
1179
                'data' => 'ERROR_INVALID_PARAMETER'
1180
            ];
1181
 
1182
            return new JsonModel($response);
1183
        }
1184
 
1185
 
1186
        if ($currentUser->id != $userProfile->user_id) {
1187
            $response = [
1188
                'success' => false,
1189
                'data' => 'ERROR_UNAUTHORIZED'
1190
            ];
1191
 
1192
            return new JsonModel($response);
1193
        }
1194
 
1195
 
1196
 
1197
        $request = $this->getRequest();
1198
        if ($request->isPost()) {
1199
            $userEducationMapper = UserEducationMapper::getInstance($this->adapter);
1200
 
1201
            if ($operation == 'delete' || $operation == 'edit') {
1202
                $userEducation = $userEducationMapper->fetchOneByUuid($user_education_id);
1203
 
1204
 
1205
                if (!$userEducation) {
1206
 
1207
                    $response = [
1208
                        'success' => false,
1209
                        'data' => 'ERROR_RECORD_NOT_FOUND'
1210
                    ];
1211
 
1212
                    return new JsonModel($response);
1213
                } else if ($userProfile->id != $userEducation->user_profile_id) {
1214
                    $response = [
1215
                        'success' => false,
1216
                        'data' => 'ERROR_UNAUTHORIZED'
1217
                    ];
1218
 
1219
                    return new JsonModel($response);
1220
                }
1221
            } else {
1222
                $userEducation = null;
1223
            }
1224
 
1225
            $locationMapper = LocationMapper::getInstance($this->adapter);
1226
            if ($operation == 'delete') {
1227
                $this->logger->info('Se borro un registro de educación del perfil ' . ($userProfile->public == UserProfile::PUBLIC_YES ? 'público' : $userProfile->name), ['user_id' => $userProfile->user_id, 'ip' => Functions::getUserIP()]);
1228
 
1229
                $result = $userEducationMapper->delete($userEducation);
1230
                if ($result) {
1231
                    $locationMapper->delete($userEducation->location_id);
1232
                }
1233
            } else {
1234
 
1235
 
1236
                $form = new EducationForm($this->adapter);
1237
                $dataPost = $request->getPost()->toArray();
1238
 
1239
                $form->setData($dataPost);
1240
 
1241
                if ($form->isValid()) {
1242
 
1243
                    if (!$userEducation) {
1244
                        $userEducation = new UserEducation();
1245
                        $userEducation->user_id = $userProfile->user_id;
1246
                        $userEducation->user_profile_id = $userProfile->id;
1247
                    }
1248
 
1249
                    $dataPost = (array) $form->getData();
1250
 
1251
                    $hydrator = new ObjectPropertyHydrator();
1252
                    $hydrator->hydrate($dataPost, $userEducation);
1253
 
1254
                    $degreeMapper = DegreeMapper::getInstance($this->adapter);
1255
                    $degree = $degreeMapper->fetchOneByUuid($dataPost['degree_id']);
1256
                    $userEducation->degree_id = $degree->id;
1257
 
1258
 
1259
 
1260
 
1261
                    if ($userEducation->location_id) {
1262
                        $location = $locationMapper->fetchOne($userEducation->location_id);
1263
                    } else {
1264
                        $location = new Location();
1265
                    }
1266
 
1267
                    $hydrator->hydrate($dataPost, $location);
1268
                    if ($userEducation->location_id) {
1269
                        $this->logger->info('Se actualizo un registro de educación del perfil ' . ($userProfile->public == UserProfile::PUBLIC_YES ? 'público' : $userProfile->name), ['user_id' => $userProfile->user_id, 'ip' => Functions::getUserIP()]);
1270
 
1271
                        $result = $locationMapper->update($location);
1272
                    } else {
1273
                        $this->logger->info('Se agrego un registro de educación del perfil ' . ($userProfile->public == UserProfile::PUBLIC_YES ? 'público' : $userProfile->name), ['user_id' => $userProfile->user_id, 'ip' => Functions::getUserIP()]);
1274
 
1275
                        $result = $locationMapper->insert($location);
1276
 
1277
                        if ($result) {
1278
                            $userEducation->location_id = $location->id;
1279
                        }
1280
                    }
1281
                    if ($result) {
1282
                        if ($userEducation->id) {
1283
                            $result = $userEducationMapper->update($userEducation);
1284
                        } else {
1285
                            $result =  $userEducationMapper->insert($userEducation);
1286
                        }
1287
                    }
1288
                } else {
1289
                    $messages = [];
1290
                    $form_messages = (array) $form->getMessages();
1291
                    foreach ($form_messages  as $fieldname => $field_messages) {
1292
                        $messages[$fieldname] = array_values($field_messages);
1293
                    }
1294
 
1295
                    return new JsonModel([
1296
                        'success'   => false,
1297
                        'data'   => $messages
1298
                    ]);
1299
                }
1300
            }
1301
 
1302
            if ($result) {
1303
                $degreeMapper = DegreeMapper::getInstance($this->adapter);
1304
                $userEducations = $userEducationMapper->fetchAllByUserProfileId($userProfile->id);
1305
 
1306
                foreach ($userEducations  as &$userEducation) {
1307
                    $location = $locationMapper->fetchOne($userEducation->location_id);
1308
                    $degree = $degreeMapper->fetchOne($userEducation->degree_id);
1309
 
1310
                    $userEducation = [
1311
                        'university' => $userEducation->university,
1312
                        'degree' => $degree->name,
1313
                        'field_of_study' => $userEducation->field_of_study,
1314
                        'grade_or_percentage' => $userEducation->grade_or_percentage,
1315
                        'formatted_address' => $location->formatted_address,
1316
                        'from_year' => $userEducation->from_year,
1317
                        'to_year' => $userEducation->to_year,
1318
                        'description' => $userEducation->description,
350 www 1319
                        'link_edit' => $this->url()->fromRoute('profile/my-profiles/education', ['id' => $userProfile->uuid, 'operation' => 'edit', 'user_education_id' => $userEducation->uuid]),
1320
                        'link_delete' => $this->url()->fromRoute('profile/my-profiles/education', ['id' => $userProfile->uuid, 'operation' => 'delete', 'user_education_id' => $userEducation->uuid]),
1 efrain 1321
                    ];
1322
                }
1323
 
1324
                $response = [
1325
                    'success'   => true,
1326
                    'data' => $userEducations
1327
                ];
1328
            } else {
1329
                $response = [
1330
                    'success'   => false,
1331
                    'data' => 'ERROR_THERE_WAS_AN_ERROR'
1332
                ];
1333
            }
1334
 
1335
 
1336
 
1337
            return new JsonModel($response);
1338
        } else if ($request->isGet() && $operation == 'edit') {
1339
            $userEducationMapper = UserEducationMapper::getInstance($this->adapter);
1340
            $userEducation = $userEducationMapper->fetchOneByUuid($user_education_id);
1341
 
1342
            if (!$userEducation) {
1343
 
1344
                $response = [
1345
                    'success' => false,
1346
                    'data' => 'ERROR_RECORD_NOT_FOUND'
1347
                ];
1348
            } else if ($userProfile->id != $userEducation->user_profile_id) {
1349
                $response = [
1350
                    'success' => false,
1351
                    'data' => 'ERROR_UNAUTHORIZED'
1352
                ];
1353
            } else {
1354
                $locationMapper = LocationMapper::getInstance($this->adapter);
1355
                $location = $locationMapper->fetchOne($userEducation->location_id);
1356
 
1357
                $hydrator = new ObjectPropertyHydrator();
1358
                $education = $hydrator->extract($userEducation);
1359
 
1360
                $degree = $degreeMapper = DegreeMapper::getInstance($this->adapter);
1361
                $degree = $degreeMapper->fetchOne($education['degree_id']);
1362
                $education['degree_id'] = $degree->uuid;
1363
 
1364
                $location = [
1365
                    'address1' => $location->address1,
1366
                    'address2' => $location->address2,
1367
                    'city1' => $location->city1,
1368
                    'city2' => $location->city2,
1369
                    'country' => $location->country,
1370
                    'formatted_address' => $location->formatted_address,
1371
                    'latitude' => $location->latitude,
1372
                    'longitude' => $location->longitude,
1373
                    'postal_code' => $location->postal_code,
1374
                    'state' => $location->state,
1375
                ];
1376
 
1377
                $response = [
1378
                    'success' => true,
1379
                    'data' => [
1380
                        'location' => $location,
1381
                        'education' => $education,
1382
                    ]
1383
                ];
1384
            }
1385
 
1386
            return new JsonModel($response);
1387
        }
1388
 
1389
 
1390
 
1391
 
1392
        $data = [
1393
            'success' => false,
1394
            'data' => 'ERROR_METHOD_NOT_ALLOWED'
1395
        ];
1396
 
1397
 
1398
        return new JsonModel($data);
1399
    }
1400
 
1401
    /**
1402
     * Actualización de los registros de la experiencia laboral
1403
     * @return \Laminas\View\Model\JsonModel
1404
     */
1405
    public function  experienceAction()
1406
    {
1407
        $currentUserPlugin = $this->plugin('currentUserPlugin');
1408
        $currentUser = $currentUserPlugin->getUser();
1409
 
1410
        $user_profile_id    = $this->params()->fromRoute('id');
1411
        $user_experience_id = $this->params()->fromRoute('user_experience_id');
1412
        $operation          = $this->params()->fromRoute('operation');
1413
 
1414
        $userProfileMapper = UserProfileMapper::getInstance($this->adapter);
1415
 
1416
        $userProfile = $userProfileMapper->fetchOneByUuid($user_profile_id);
1417
        if (!$userProfile) {
1418
            $response = [
1419
                'success' => false,
1420
                'data' => 'ERROR_INVALID_PARAMETER'
1421
            ];
1422
 
1423
            return new JsonModel($response);
1424
        }
1425
 
1426
        if ($currentUser->id != $userProfile->user_id) {
1427
            $response = [
1428
                'success' => false,
1429
                'data' => 'ERROR_UNAUTHORIZED'
1430
            ];
1431
 
1432
            return new JsonModel($response);
1433
        }
1434
 
1435
 
1436
 
1437
        $request = $this->getRequest();
1438
        if ($request->isPost()) {
1439
            $userExperienceMapper = UserExperienceMapper::getInstance($this->adapter);
1440
 
1441
            if ($operation == 'delete' || $operation == 'edit') {
1442
                $userExperience = $userExperienceMapper->fetchOneByUuid($user_experience_id);
1443
 
1444
                if (!$userExperience) {
1445
 
1446
                    $response = [
1447
                        'success' => false,
1448
                        'data' => 'ERROR_RECORD_NOT_FOUND'
1449
                    ];
1450
 
1451
                    return new JsonModel($response);
1452
                } else if ($userProfile->id != $userExperience->user_profile_id) {
1453
                    $response = [
1454
                        'success' => false,
1455
                        'data' => 'ERROR_UNAUTHORIZED'
1456
                    ];
1457
 
1458
                    return new JsonModel($response);
1459
                }
1460
            } else {
1461
                $userExperience = null;
1462
            }
1463
 
1464
            $locationMapper = LocationMapper::getInstance($this->adapter);
1465
            if ($operation == 'delete') {
1466
                $this->logger->info('Se borro un registro de experiencia del perfil ' . ($userProfile->public == UserProfile::PUBLIC_YES ? 'público' : $userProfile->name), ['user_id' => $userProfile->user_id, 'ip' => Functions::getUserIP()]);
1467
 
1468
                $result = $userExperienceMapper->delete($userExperience);
1469
                if ($result) {
1470
                    $locationMapper->delete($userExperience->location_id);
1471
                }
1472
            } else {
1473
 
1474
 
1475
                $form = new ExperienceForm($this->adapter);
1476
                $dataPost = $request->getPost()->toArray();
1477
 
1478
 
1479
                $dataPost['is_current'] = isset($dataPost['is_current']) ? $dataPost['is_current'] : UserExperience::IS_CURRENT_NO;
1480
                if ($dataPost['is_current']  == UserExperience::IS_CURRENT_YES) {
1481
                    $dataPost['to_month'] = 12;
1482
                    $dataPost['to_year'] = date('Y');
1483
                }
1484
 
1485
 
1486
                $form->setData($dataPost);
1487
 
1488
                if ($form->isValid()) {
1489
 
1490
 
1491
 
1492
 
1493
                    if (!$userExperience) {
1494
                        $userExperience = new UserExperience();
1495
                        $userExperience->user_id = $userProfile->user_id;
1496
                        $userExperience->user_profile_id = $userProfile->id;
1497
                    }
1498
 
1499
                    $dataPost = (array) $form->getData();
1500
                    $companySizeMapper = CompanySizeMapper::getInstance($this->adapter);
1501
                    $companySize = $companySizeMapper->fetchOneByUuid($dataPost['company_size_id']);
1502
 
1503
                    $industryMapper = IndustryMapper::getInstance($this->adapter);
1504
                    $industry = $industryMapper->fetchOneByUuid($dataPost['industry_id']);
1505
 
1506
                    $hydrator = new ObjectPropertyHydrator();
1507
                    $hydrator->hydrate($dataPost, $userExperience);
1508
 
1509
                    $userExperience->company_size_id = $companySize->id;
1510
                    $userExperience->industry_id = $industry->id;
1511
 
1512
                    if ($userExperience->is_current == UserExperience::IS_CURRENT_YES) {
1513
                        $userExperience->to_month = null;
1514
                        $userExperience->to_year = null;
1515
                    }
1516
 
1517
                    if ($userExperience->location_id) {
1518
                        $location = $locationMapper->fetchOne($userExperience->location_id);
1519
                    } else {
1520
                        $location = new Location();
1521
                    }
1522
                    $hydrator->hydrate($dataPost, $location);
1523
 
1524
                    if ($userExperience->location_id) {
1525
                        $this->logger->info('Se actualizo un registro de experiencia del perfil ' . ($userProfile->public == UserProfile::PUBLIC_YES ? 'público' : $userProfile->name), ['user_id' => $userProfile->user_id, 'ip' => Functions::getUserIP()]);
1526
 
1527
                        $result = $locationMapper->update($location);
1528
                    } else {
1529
                        $this->logger->info('Se agrego un registro de experiencia del perfil ' . ($userProfile->public == UserProfile::PUBLIC_YES ? 'público' : $userProfile->name), ['user_id' => $userProfile->user_id, 'ip' => Functions::getUserIP()]);
1530
 
1531
                        $result = $locationMapper->insert($location);
1532
 
1533
                        if ($result) {
1534
                            $userExperience->location_id = $location->id;
1535
                        }
1536
                    }
1537
                    if ($result) {
1538
                        if ($userExperience->id) {
1539
                            $result = $userExperienceMapper->update($userExperience);
1540
                        } else {
1541
                            $result =  $userExperienceMapper->insert($userExperience);
1542
                        }
1543
                    }
1544
                } else {
1545
                    $messages = [];
1546
                    $form_messages = (array) $form->getMessages();
1547
                    foreach ($form_messages  as $fieldname => $field_messages) {
1548
                        $messages[$fieldname] = array_values($field_messages);
1549
                    }
1550
 
1551
                    return new JsonModel([
1552
                        'success'   => false,
1553
                        'data'   => $messages,
1554
                    ]);
1555
                }
1556
            }
1557
 
1558
            if ($result) {
1559
                $industryMapper = IndustryMapper::getInstance($this->adapter);
1560
                $companySizeMapper = CompanySizeMapper::getInstance($this->adapter);
1561
                $userExperiences = $userExperienceMapper->fetchAllByUserProfileId($userProfile->id);
1562
 
1563
                foreach ($userExperiences  as &$userExperience) {
1564
                    $location = $locationMapper->fetchOne($userExperience->location_id);
1565
                    $companySize = $companySizeMapper->fetchOne($userExperience->company_size_id);
1566
                    $industry = $industryMapper->fetchOne($userExperience->industry_id);
1567
 
1568
                    $userExperience = [
1569
                        'company' => $userExperience->company,
1570
                        'industry' => $industry,
1571
                        'size' => $companySize->name . ' (' . $companySize->minimum_no_of_employee . '-' . $companySize->maximum_no_of_employee . ') ',
1572
                        'title' => $userExperience->title,
1573
                        'formatted_address' => $location->formatted_address,
1574
                        'from_year' => $userExperience->from_year,
1575
                        'from_month' => $userExperience->from_month,
1576
                        'to_year' => $userExperience->to_year,
1577
                        'to_month' => $userExperience->to_month,
1578
                        'description' => $userExperience->description,
1579
                        'is_current' => $userExperience->is_current,
350 www 1580
                        'link_edit' => $this->url()->fromRoute('profile/my-profiles/experience', ['id' => $userProfile->uuid, 'operation' => 'edit', 'user_experience_id' => $userExperience->uuid]),
1581
                        'link_delete' => $this->url()->fromRoute('profile/my-profiles/experience', ['id' => $userProfile->uuid, 'operation' => 'delete', 'user_experience_id' => $userExperience->uuid]),
1 efrain 1582
                    ];
1583
                }
1584
 
1585
                $response = [
1586
                    'success'   => true,
1587
                    'data' => $userExperiences
1588
                ];
1589
            } else {
1590
                $response = [
1591
                    'success'   => false,
1592
                    'data' => 'ERROR_THERE_WAS_AN_ERROR'
1593
                ];
1594
            }
1595
 
1596
            return new JsonModel($response);
1597
        } else if ($request->isGet() && $operation == 'edit') {
1598
            $userExperienceMapper = UserExperienceMapper::getInstance($this->adapter);
1599
            $userExperience = $userExperienceMapper->fetchOneByUuid($user_experience_id);
1600
 
1601
            if (!$userExperience) {
1602
                $response = [
1603
                    'success' => false,
1604
                    'data' => 'ERROR_RECORD_NOT_FOUND'
1605
                ];
1606
            } else if ($userProfile->id != $userExperience->user_profile_id) {
1607
                $response = [
1608
                    'success' => false,
1609
                    'data' => 'ERROR_UNAUTHORIZED'
1610
                ];
1611
            } else {
1612
                $hydrator = new ObjectPropertyHydrator();
1613
                $experience = $hydrator->extract($userExperience);
1614
 
1615
 
1616
                $industryMapper = IndustryMapper::getInstance($this->adapter);
1617
                $industry = $industryMapper->fetchOne($userExperience->industry_id);
1618
 
1619
                $companySizeMapper = CompanySizeMapper::getInstance($this->adapter);
1620
                $companySize = $companySizeMapper->fetchOne($userExperience->company_size_id);
1621
 
1622
                $experience['industry_id'] = $industry->uuid;
1623
                $experience['company_size_id'] = $companySize->uuid;
1624
 
1625
                $locationMapper = LocationMapper::getInstance($this->adapter);
1626
                $location = $locationMapper->fetchOne($userExperience->location_id);
1627
 
1628
                $response = [
1629
                    'success' => true,
1630
                    'data' => [
1631
                        'location' => $hydrator->extract($location),
1632
                        'experience' => $experience
1633
                    ]
1634
                ];
1635
            }
1636
            return new JsonModel($response);
1637
        }
1638
 
1639
        $data = [
1640
            'success' => false,
1641
            'data' => 'ERROR_METHOD_NOT_ALLOWED'
1642
        ];
1643
 
1644
 
1645
        return new JsonModel($data);
1646
    }
1647
 
1648
    /**
596 ariadna 1649
     * Maneja la subida y eliminación de la imagen del perfil de usuario.
1650
     * Este método permite:
1651
     * - Subir una nueva imagen de perfil
1652
     * - Eliminar la imagen existente
1653
     * - Actualizar la imagen principal del usuario si el perfil es público
1654
     *
1 efrain 1655
     * @return \Laminas\View\Model\JsonModel
1656
     */
1657
    public function imageAction()
1658
    {
596 ariadna 1659
        // Obtener el usuario actual del sistema
1 efrain 1660
        $currentUserPlugin = $this->plugin('currentUserPlugin');
1661
        $currentUser = $currentUserPlugin->getUser();
1662
 
596 ariadna 1663
        // Obtener parámetros de la ruta: ID del perfil y operación (upload/delete)
1 efrain 1664
        $user_profile_id    = $this->params()->fromRoute('id');
1665
        $operation          = $this->params()->fromRoute('operation');
1666
 
596 ariadna 1667
        // Obtener el perfil de usuario correspondiente
1 efrain 1668
        $userProfileMapper = UserProfileMapper::getInstance($this->adapter);
596 ariadna 1669
        $userProfile = $userProfileMapper->fetchOneByUuid($user_profile_id);
1 efrain 1670
 
596 ariadna 1671
        // Validar que el perfil existe
1 efrain 1672
        if (!$userProfile) {
553 stevensc 1673
            return $this->_createSimpleErrorResponse('ERROR_INVALID_PARAMETER');
1 efrain 1674
        }
1675
 
596 ariadna 1676
        // Verificar que el usuario actual es el propietario del perfil
1 efrain 1677
        if ($currentUser->id != $userProfile->user_id) {
553 stevensc 1678
            return $this->_createSimpleErrorResponse('ERROR_UNAUTHORIZED');
1 efrain 1679
        }
1680
 
596 ariadna 1681
        // Procesar solo peticiones POST
1 efrain 1682
        $request = $this->getRequest();
1683
        if ($request->isPost()) {
596 ariadna 1684
            // Inicializar el sistema de almacenamiento
346 www 1685
            $storage = Storage::getInstance($this->config, $this->adapter);
1686
            $target_path = $storage->getPathUser();
596 ariadna 1687
            $user_uuid = $currentUser->uuid;
1688
 
1689
            // Manejar la eliminación de la imagen
1 efrain 1690
            if ($operation == 'delete') {
596 ariadna 1691
                // Registrar la acción en el log
1 efrain 1692
                $this->logger->info('Se borro el image del perfil ' . ($userProfile->public == UserProfile::PUBLIC_YES ? 'público' : $userProfile->name), ['user_id' => $userProfile->user_id, 'ip' => Functions::getUserIP()]);
1693
 
596 ariadna 1694
                // Si existe una imagen, intentar eliminarla
1 efrain 1695
                if ($userProfile->image) {
553 stevensc 1696
                    if (!$storage->deleteFile($target_path, $user_uuid, $userProfile->image)) {
1697
                        return $this->_createSimpleErrorResponse('ERROR_THERE_WAS_AN_ERROR');
1 efrain 1698
                    }
1699
                }
1700
 
596 ariadna 1701
                // Limpiar el campo de imagen y actualizar la base de datos
1 efrain 1702
                $userProfile->image = '';
1703
                if (!$userProfileMapper->updateImage($userProfile)) {
553 stevensc 1704
                    return $this->_createSimpleErrorResponse('ERROR_THERE_WAS_AN_ERROR');
1 efrain 1705
                }
596 ariadna 1706
            } else {
1707
                // Manejar la subida de una nueva imagen
1 efrain 1708
                $form = new ImageForm($this->config);
553 stevensc 1709
                $data = array_merge($request->getPost()->toArray(), $request->getFiles()->toArray());
1 efrain 1710
 
1711
                $form->setData($data);
1712
 
1713
                if ($form->isValid()) {
596 ariadna 1714
                    // Configurar el archivo para procesamiento
346 www 1715
                    $storage->setFiles($request->getFiles()->toArray());
596 ariadna 1716
                    if (!$storage->setCurrentFilename('image')) {
553 stevensc 1717
                        return $this->_createSimpleErrorResponse('ERROR_UPLOAD_FILE');
1 efrain 1718
                    }
1719
 
596 ariadna 1720
                    // Obtener dimensiones objetivo para el redimensionamiento
553 stevensc 1721
                    list($target_width_str, $target_height_str) = explode('x', $this->config['leaderslinked.image_sizes.user_size']);
1722
                    $target_width = (int)$target_width_str;
1723
                    $target_height = (int)$target_height_str;
596 ariadna 1724
 
1725
                    // Generar nombres de archivo únicos
346 www 1726
                    $source_filename    = $storage->getTmpFilename();
1727
                    $filename           = 'user-profile-' . uniqid() . '.png';
596 ariadna 1728
                    $target_filename    = $storage->composePathToFilename(Storage::TYPE_USER, $user_uuid, $filename);
1729
 
1730
                    // Subir y redimensionar la imagen
555 stevensc 1731
                    if (!$storage->uploadImageResize($source_filename, $target_filename, $target_width, $target_height)) {
553 stevensc 1732
                        return $this->_createSimpleErrorResponse('ERROR_THERE_WAS_AN_ERROR');
1 efrain 1733
                    }
596 ariadna 1734
 
1735
                    // Eliminar la imagen anterior si existe
346 www 1736
                    if ($userProfile->image) {
553 stevensc 1737
                        if (!$storage->deleteFile($target_path, $user_uuid, $userProfile->image)) {
1738
                            return $this->_createSimpleErrorResponse('ERROR_THERE_WAS_AN_ERROR');
346 www 1739
                        }
1740
                    }
1 efrain 1741
 
596 ariadna 1742
                    // Actualizar el perfil con la nueva imagen
346 www 1743
                    $userProfile->image = $filename;
1 efrain 1744
                    if (!$userProfileMapper->updateImage($userProfile)) {
553 stevensc 1745
                        return $this->_createSimpleErrorResponse('ERROR_THERE_WAS_AN_ERROR');
1 efrain 1746
                    }
1747
 
596 ariadna 1748
                    // Si es un perfil público, actualizar también la imagen principal del usuario
1 efrain 1749
                    if ($userProfile->public == UserProfile::PUBLIC_YES) {
596 ariadna 1750
                        $main_user_filename = 'user-' . uniqid() . '.png';
1751
                        $target_filename_main_user = $storage->composePathToFilename(Storage::TYPE_USER, $user_uuid, $main_user_filename);
1752
 
1753
                        // Copiar la imagen del perfil para la imagen principal
1754
                        if (!$storage->copyFile($target_filename, $target_filename_main_user)) {
1755
                            return $this->_createSimpleErrorResponse('ERROR_THERE_WAS_AN_ERROR');
283 www 1756
                        }
596 ariadna 1757
 
1758
                        // Eliminar la imagen principal anterior si existe
346 www 1759
                        if ($currentUser->image) {
553 stevensc 1760
                            if (!$storage->deleteFile($target_path, $user_uuid, $currentUser->image)) {
1761
                                return $this->_createSimpleErrorResponse('ERROR_THERE_WAS_AN_ERROR');
346 www 1762
                            }
1763
                        }
1 efrain 1764
 
596 ariadna 1765
                        // Actualizar la imagen principal del usuario
553 stevensc 1766
                        $currentUser->image = $main_user_filename;
1 efrain 1767
                        $userMapper = UserMapper::getInstance($this->adapter);
553 stevensc 1768
                        if (!$userMapper->updateImage($currentUser)) {
596 ariadna 1769
                            return $this->_createSimpleErrorResponse('ERROR_THERE_WAS_AN_ERROR');
553 stevensc 1770
                        }
1 efrain 1771
                    }
1772
 
596 ariadna 1773
                    // Registrar la actualización en el log
1 efrain 1774
                    $this->logger->info('Se actualizo el image del perfil ' . ($userProfile->public == UserProfile::PUBLIC_YES ? 'público' : $userProfile->name), ['user_id' => $userProfile->user_id, 'ip' => Functions::getUserIP()]);
1775
                } else {
596 ariadna 1776
                    // Devolver errores de validación del formulario
553 stevensc 1777
                    return $this->_createFormErrorResponse($form);
1 efrain 1778
                }
596 ariadna 1779
            }
1780
 
1781
            // Devolver respuesta exitosa con las URLs actualizadas
333 www 1782
            $storage = Storage::getInstance($this->config, $this->adapter);
1 efrain 1783
            return new JsonModel([
1784
                'success'   => true,
1785
                'data' => [
283 www 1786
                    'user' => $storage->getUserImage($currentUser),
1787
                    'profile' => $storage->getUserProfileImage($currentUser, $userProfile),
1 efrain 1788
                    'update_navbar' =>  $userProfile->public == UserProfile::PUBLIC_YES ? 1 : 0,
1789
                ]
1790
            ]);
596 ariadna 1791
        }
1 efrain 1792
 
596 ariadna 1793
        // Si no es una petición POST, devolver error
553 stevensc 1794
        return $this->_createSimpleErrorResponse('ERROR_METHOD_NOT_ALLOWED');
1 efrain 1795
    }
1796
 
1797
    /**
550 stevensc 1798
     * Handles changing the user profile's cover image.
1799
     * Supports uploading a new cover or deleting the existing one.
1800
     * @return \\Laminas\\View\\Model\\JsonModel
1 efrain 1801
     */
1802
    public function coverAction()
1803
    {
550 stevensc 1804
        // Get current user
1 efrain 1805
        $currentUserPlugin = $this->plugin('currentUserPlugin');
1806
        $currentUser = $currentUserPlugin->getUser();
1807
 
550 stevensc 1808
        // Get parameters from route
1 efrain 1809
        $user_profile_id    = $this->params()->fromRoute('id');
550 stevensc 1810
        $operation          = $this->params()->fromRoute('operation'); // Expected: 'upload' or 'delete'
1 efrain 1811
 
550 stevensc 1812
        // Fetch user profile
1 efrain 1813
        $userProfileMapper = UserProfileMapper::getInstance($this->adapter);
550 stevensc 1814
        $userProfile = $userProfileMapper->fetchOneByUuid($user_profile_id);
1 efrain 1815
 
550 stevensc 1816
        // Validate profile existence
1 efrain 1817
        if (!$userProfile) {
550 stevensc 1818
            return $this->_createSimpleErrorResponse('ERROR_INVALID_PARAMETER');
1 efrain 1819
        }
1820
 
550 stevensc 1821
        // Authorize current user against the profile: only the profile owner can modify it
1 efrain 1822
        if ($currentUser->id != $userProfile->user_id) {
550 stevensc 1823
            return $this->_createSimpleErrorResponse('ERROR_UNAUTHORIZED');
1 efrain 1824
        }
1825
 
1826
        $request = $this->getRequest();
1827
        if ($request->isPost()) {
346 www 1828
            $storage = Storage::getInstance($this->config, $this->adapter);
550 stevensc 1829
            $target_path = $storage->getPathUser(); // Base path for user-specific files
556 stevensc 1830
            $user_uuid = $currentUser->uuid;
596 ariadna 1831
 
550 stevensc 1832
            // Handle cover deletion operation
1 efrain 1833
            if ($operation == 'delete') {
1834
                if ($userProfile->cover) {
550 stevensc 1835
                    // Attempt to delete the existing cover file from storage
556 stevensc 1836
                    if (!$storage->deleteFile($target_path, $user_uuid, $userProfile->cover)) {
550 stevensc 1837
                        return $this->_createSimpleErrorResponse('ERROR_THERE_WAS_AN_ERROR');
1 efrain 1838
                    }
1839
                }
550 stevensc 1840
                // Log the deletion action
1 efrain 1841
                $this->logger->info('Se borro el cover del perfil ' . ($userProfile->public == UserProfile::PUBLIC_YES ? 'público' : $userProfile->name), ['user_id' => $userProfile->user_id, 'ip' => Functions::getUserIP()]);
550 stevensc 1842
                $userProfile->cover = ''; // Clear the cover field in the profile model
596 ariadna 1843
 
550 stevensc 1844
                // Persist the cleared cover information to the database
1845
                if (!$userProfileMapper->updateCover($userProfile)) {
1846
                    // Handle error if database update fails for deletion
1847
                    return $this->_createSimpleErrorResponse('ERROR_THERE_WAS_AN_ERROR');
1848
                }
1849
            } else { // Handle cover upload operation
1 efrain 1850
                $form = new CoverForm($this->config);
550 stevensc 1851
                // Merge POST data and FILES data for the form
1852
                $data = array_merge($request->getPost()->toArray(), $request->getFiles()->toArray());
1 efrain 1853
                $form->setData($data);
1854
 
556 stevensc 1855
 
1 efrain 1856
                if ($form->isValid()) {
550 stevensc 1857
                    // Set files in storage and select the 'cover' file by its input name
346 www 1858
                    $storage->setFiles($request->getFiles()->toArray());
550 stevensc 1859
                    if (!$storage->setCurrentFilename('cover')) { // Ensure 'cover' is the correct file input name from CoverForm
1860
                        return $this->_createSimpleErrorResponse('ERROR_UPLOAD_FILE');
1 efrain 1861
                    }
553 stevensc 1862
 
550 stevensc 1863
                    // Prepare for image resize and save: Get target dimensions from config
1864
                    // Example config value: '1200x400'
1865
                    list($target_width_str, $target_height_str) = explode('x', $this->config['leaderslinked.image_sizes.user_cover_size']);
1866
                    $target_width = (int)$target_width_str;
1867
                    $target_height = (int)$target_height_str;
1 efrain 1868
 
550 stevensc 1869
                    $filename           = 'user-cover-' . uniqid() . '.png'; // Generate unique filename for the new cover
1870
                    $source_filename    = $storage->getTmpFilename(); // Temporary path of the uploaded file
556 stevensc 1871
                    $target_filename    = $storage->composePathToFilename(Storage::TYPE_USER, $user_uuid, $filename);
1 efrain 1872
 
550 stevensc 1873
                    // Upload, resize, and save the image
346 www 1874
                    if (!$storage->uploadImageResize($source_filename, $target_filename, $target_width, $target_height)) {
550 stevensc 1875
                        return $this->_createSimpleErrorResponse('ERROR_THERE_WAS_AN_ERROR');
1 efrain 1876
                    }
596 ariadna 1877
 
550 stevensc 1878
                    // If an old cover exists, delete it from storage
346 www 1879
                    if ($userProfile->cover) {
556 stevensc 1880
                        if (!$storage->deleteFile($target_path, $user_uuid, $userProfile->cover)) {
550 stevensc 1881
                            // Decide if this is a critical error. Original code returns error.
1882
                            // Consider logging this and proceeding if deletion of old file is non-critical.
1883
                            return $this->_createSimpleErrorResponse('ERROR_THERE_WAS_AN_ERROR');
346 www 1884
                        }
1885
                    }
1 efrain 1886
 
550 stevensc 1887
                    // Update profile model with new cover filename
346 www 1888
                    $userProfile->cover = $filename;
550 stevensc 1889
                    // Persist the new cover information to the database
1 efrain 1890
                    if (!$userProfileMapper->updateCover($userProfile)) {
550 stevensc 1891
                        return $this->_createSimpleErrorResponse('ERROR_THERE_WAS_AN_ERROR');
1 efrain 1892
                    }
1893
 
550 stevensc 1894
                    // Log successful update
1 efrain 1895
                    $this->logger->info('Se actualizo el cover del perfil ' . ($userProfile->public == UserProfile::PUBLIC_YES ? 'público' : $userProfile->name), ['user_id' => $userProfile->user_id, 'ip' => Functions::getUserIP()]);
1896
                } else {
550 stevensc 1897
                    // Form is invalid, return validation messages
1898
                    return $this->_createFormErrorResponse($form);
1 efrain 1899
                }
550 stevensc 1900
            } // End of upload/delete specific logic
596 ariadna 1901
 
550 stevensc 1902
            // Successful operation (upload or delete has been handled and persisted)
1903
            // Return success response with the current cover URL (new, or default after delete)
1904
            // The $storage instance from the beginning of the POST block is still valid.
1 efrain 1905
            return new JsonModel([
1906
                'success'   => true,
283 www 1907
                'data' => $storage->getUserProfileCover($currentUser, $userProfile)
1 efrain 1908
            ]);
550 stevensc 1909
        } // End of isPost()
1 efrain 1910
 
550 stevensc 1911
        // If not a POST request, return method not allowed error
1912
        return $this->_createSimpleErrorResponse('ERROR_METHOD_NOT_ALLOWED');
1 efrain 1913
    }
1914
 
1915
    /**
1916
     * Actualización de las habilidades
1917
     * @return \Laminas\View\Model\JsonModel
1918
     */
1919
    public function aptitudeAction()
1920
    {
1921
        $currentUserPlugin = $this->plugin('currentUserPlugin');
1922
        $currentUser = $currentUserPlugin->getUser();
1923
 
1924
        $user_profile_id = $this->params()->fromRoute('id');
1925
        $userProfileMapper = UserProfileMapper::getInstance($this->adapter);
1926
 
1927
        $userProfile = $userProfileMapper->fetchOneByUuid($user_profile_id);
1928
        if (!$userProfile) {
1929
            $response = [
1930
                'success' => false,
1931
                'data' => 'ERROR_INVALID_PARAMETER'
1932
            ];
1933
 
1934
            return new JsonModel($response);
1935
        }
1936
 
1937
        if ($currentUser->id != $userProfile->user_id) {
1938
            $response = [
1939
                'success' => false,
1940
                'data' => 'ERROR_UNAUTHORIZED'
1941
            ];
1942
 
1943
            return new JsonModel($response);
1944
        }
1945
 
1946
 
1947
 
1948
        $request = $this->getRequest();
1949
        if ($request->isGet()) {
1950
            $aptitudeMapper = AptitudeMapper::getInstance($this->adapter);
1951
 
1952
 
1953
            $userAptitudeMapper = UserAptitudeMapper::getInstance($this->adapter);
1954
            $userAptitudes  = $userAptitudeMapper->fetchAllByUserProfileId($userProfile->id);
1955
 
1956
            $items = [];
1957
            foreach ($userAptitudes as $userAptitude) {
1958
                $aptitude = $aptitudeMapper->fetchOne($userAptitude->aptitude_id);
1959
                array_push($items, $aptitude->uuid);
1960
            }
1961
 
1962
            $data = [
1963
                'success' => true,
1964
                'data' => $items
1965
            ];
1966
 
1967
            return new JsonModel($data);
1968
        } else if ($request->isPost()) {
1969
 
1970
            $form = new AptitudeForm($this->adapter);
1971
            $dataPost = $request->getPost()->toArray();
1972
 
1973
            $form->setData($dataPost);
1974
 
1975
            if ($form->isValid()) {
1976
                $this->logger->info('Se actualizaron las habilidades del perfil ' . ($userProfile->public == UserProfile::PUBLIC_YES ? 'público' : $userProfile->name), ['user_id' => $userProfile->user_id, 'ip' => Functions::getUserIP()]);
1977
 
1978
                $aptitudeMapper = AptitudeMapper::getInstance($this->adapter);
1979
 
1980
 
1981
                $userAptitudeMapper = UserAptitudeMapper::getInstance($this->adapter);
1982
                $userAptitudeMapper->deleteByUserProfileId($userProfile->id);
1983
 
1984
                $dataPost = (array) $form->getData();
1985
                $aptitudes = $dataPost['aptitudes'];
1986
                foreach ($aptitudes as $aptitude_uuid) {
1987
 
1988
                    $aptitude = $aptitudeMapper->fetchOneByUuid($aptitude_uuid);
1989
 
1990
 
1991
                    $userAptitude = new UserAptitude();
1992
                    $userAptitude->user_id = $userProfile->user_id;
1993
                    $userAptitude->user_profile_id = $userProfile->id;
1994
                    $userAptitude->aptitude_id =  $aptitude->id;
1995
 
1996
                    $userAptitudeMapper->insert($userAptitude);
1997
                }
1998
 
1999
                $items = [];
2000
 
2001
                $records = $userAptitudeMapper->fetchAllByUserProfileId($userProfile->id);
2002
                foreach ($records as $record) {
2003
                    $aptitude = $aptitudeMapper->fetchOne($record->aptitude_id);
2004
                    array_push($items,  ['value' => $aptitude->uuid, 'label' => $aptitude->name]);
2005
                }
2006
 
2007
                return new JsonModel([
2008
                    'success'   => true,
2009
                    'data'   => $items
2010
                ]);
2011
            } else {
2012
                $messages = [];
2013
                $form_messages = (array) $form->getMessages();
2014
                foreach ($form_messages  as $fieldname => $field_messages) {
2015
                    $messages[$fieldname] = array_values($field_messages);
2016
                }
2017
 
2018
                return new JsonModel([
2019
                    'success'   => false,
2020
                    'data'   => $messages
2021
                ]);
2022
            }
2023
 
2024
            $userAptitudeMapper = UserAptitudeMapper::getInstance($this->adapter);
2025
        }
2026
 
2027
 
2028
        $data = [
2029
            'success' => false,
2030
            'data' => 'ERROR_METHOD_NOT_ALLOWED'
2031
        ];
2032
 
2033
 
2034
        return new JsonModel($data);
2035
    }
2036
 
2037
    /**
2038
     * Actualización de las habilidades
2039
     * @return \Laminas\View\Model\JsonModel
2040
     */
2041
    public function hobbyAndInterestAction()
2042
    {
2043
        $currentUserPlugin = $this->plugin('currentUserPlugin');
2044
        $currentUser = $currentUserPlugin->getUser();
2045
 
2046
        $user_profile_id = $this->params()->fromRoute('id');
2047
        $userProfileMapper = UserProfileMapper::getInstance($this->adapter);
2048
 
2049
        $userProfile = $userProfileMapper->fetchOneByUuid($user_profile_id);
2050
        if (!$userProfile) {
2051
            $response = [
2052
                'success' => false,
2053
                'data' => 'ERROR_INVALID_PARAMETER'
2054
            ];
2055
 
2056
            return new JsonModel($response);
2057
        }
2058
 
2059
        if ($currentUser->id != $userProfile->user_id) {
2060
            $response = [
2061
                'success' => false,
2062
                'data' => 'ERROR_UNAUTHORIZED'
2063
            ];
2064
 
2065
            return new JsonModel($response);
2066
        }
2067
 
2068
 
2069
 
2070
        $request = $this->getRequest();
2071
        if ($request->isGet()) {
2072
            $hobbyAndInterestMapper = HobbyAndInterestMapper::getInstance($this->adapter);
2073
 
2074
 
2075
            $userHobbyAndInterestMapper = UserHobbyAndInterestMapper::getInstance($this->adapter);
2076
            $userHobbyAndInterests  = $userHobbyAndInterestMapper->fetchAllByUserProfileId($userProfile->id);
2077
 
2078
            $items = [];
2079
            foreach ($userHobbyAndInterests as $userHobbyAndInterest) {
2080
                $hobbyAndInterest = $hobbyAndInterestMapper->fetchOne($userHobbyAndInterest->hobbyAndInterest_id);
2081
                array_push($items, $hobbyAndInterest->uuid);
2082
            }
2083
 
2084
            $data = [
2085
                'success' => true,
2086
                'data' => $items
2087
            ];
2088
 
2089
            return new JsonModel($data);
2090
        } else if ($request->isPost()) {
2091
 
2092
            $form = new HobbyAndInterestForm($this->adapter);
2093
            $dataPost = $request->getPost()->toArray();
2094
 
2095
 
2096
            $form->setData($dataPost);
2097
 
2098
            if ($form->isValid()) {
2099
                $this->logger->info('Se actualizaron las habilidades del perfil ' . ($userProfile->public == UserProfile::PUBLIC_YES ? 'público' : $userProfile->name), ['user_id' => $userProfile->user_id, 'ip' => Functions::getUserIP()]);
2100
 
2101
                $hobbyAndInterestMapper = HobbyAndInterestMapper::getInstance($this->adapter);
2102
 
2103
 
2104
                $userHobbyAndInterestMapper = UserHobbyAndInterestMapper::getInstance($this->adapter);
2105
                $userHobbyAndInterestMapper->deleteByUserProfileId($userProfile->id);
2106
 
2107
                $dataPost = (array) $form->getData();
2108
                $hobbyAndInterests = $dataPost['hobbies_and_interests'];
2109
                foreach ($hobbyAndInterests as $hobbyAndInterest_uuid) {
2110
 
2111
                    $hobbyAndInterest = $hobbyAndInterestMapper->fetchOneByUuid($hobbyAndInterest_uuid);
2112
 
2113
 
2114
                    $userHobbyAndInterest = new UserHobbyAndInterest();
2115
                    $userHobbyAndInterest->user_id = $userProfile->user_id;
2116
                    $userHobbyAndInterest->user_profile_id = $userProfile->id;
2117
                    $userHobbyAndInterest->hobby_and_interest_id =  $hobbyAndInterest->id;
2118
 
2119
                    $userHobbyAndInterestMapper->insert($userHobbyAndInterest);
2120
                }
2121
 
2122
                $items = [];
2123
 
2124
                $records = $userHobbyAndInterestMapper->fetchAllByUserProfileId($userProfile->id);
2125
                foreach ($records as $record) {
2126
                    $hobbyAndInterest = $hobbyAndInterestMapper->fetchOne($record->hobby_and_interest_id);
2127
                    array_push($items,  ['value' => $hobbyAndInterest->uuid, 'label' => $hobbyAndInterest->name]);
2128
                }
2129
 
2130
                return new JsonModel([
2131
                    'success'   => true,
2132
                    'data'   => $items
2133
                ]);
2134
            } else {
2135
                $messages = [];
2136
                $form_messages = (array) $form->getMessages();
2137
                foreach ($form_messages  as $fieldname => $field_messages) {
2138
                    $messages[$fieldname] = array_values($field_messages);
2139
                }
2140
 
2141
                return new JsonModel([
2142
                    'success'   => false,
2143
                    'data'   => $messages
2144
                ]);
2145
            }
2146
 
2147
            $userHobbyAndInterestMapper = UserHobbyAndInterestMapper::getInstance($this->adapter);
2148
        }
2149
 
2150
 
2151
        $data = [
2152
            'success' => false,
2153
            'data' => 'ERROR_METHOD_NOT_ALLOWED'
2154
        ];
2155
 
2156
 
2157
        return new JsonModel($data);
2158
    }
550 stevensc 2159
 
2160
    // Helper methods for creating standardized JSON responses
2161
    // These can be used across various actions in this controller
2162
 
2163
    /**
2164
     * Creates a standardized JSON error response with a simple message.
2165
     * @param string $errorMessageKey Identifier for the error message (e.g., a translation key or constant).
2166
     * @return JsonModel
2167
     */
551 stevensc 2168
    private function _createSimpleErrorResponse($errorMessageKey)
550 stevensc 2169
    {
2170
        return new JsonModel([
2171
            'success' => false,
596 ariadna 2172
            'data'    => $errorMessageKey
550 stevensc 2173
        ]);
2174
    }
2175
 
2176
    /**
2177
     * Creates a JSON response for form validation errors.
2178
     * Extracts messages from the form and structures them for the client.
551 stevensc 2179
     * @param \Laminas\Form\FormInterface $form The form instance containing validation messages.
550 stevensc 2180
     * @return JsonModel
2181
     */
551 stevensc 2182
    private function _createFormErrorResponse($form)
550 stevensc 2183
    {
2184
        $messages = [];
2185
        $form_messages = (array) $form->getMessages(); // Get all error messages from the form
2186
        foreach ($form_messages as $fieldname => $field_messages_for_field) {
2187
            // Ensure messages for each field are in a simple array format for the frontend
2188
            $messages[$fieldname] = array_values((array)$field_messages_for_field);
2189
        }
2190
        return new JsonModel([
2191
            'success' => false,
2192
            'data'    => $messages
2193
        ]);
2194
    }
1 efrain 2195
}