Rev 723 | Autoría | Comparar con el anterior | Ultima modificación | Ver Log |
<?phpdeclare(strict_types=1);namespace LeadersLinked\Controller;use Laminas\Mvc\Controller\AbstractActionController;use Laminas\View\Model\JsonModel;use LeadersLinked\Library\Functions;use LeadersLinked\Mapper\MicrolearningCapsuleMapper;use LeadersLinked\Mapper\QueryMapper;use LeadersLinked\Mapper\UserMapper;use Laminas\Db\Sql\Select;use LeadersLinked\Mapper\MicrolearningCapsuleCommentMapper;use LeadersLinked\Form\Service\CapsuleCommentForm;use LeadersLinked\Model\MicrolearningCapsuleComment;use LeadersLinked\Model\MicrolearningAnswer;use LeadersLinked\Mapper\MicrolearningUserProgressMapper;use LeadersLinked\Mapper\MicrolearningSlideMapper;use LeadersLinked\Mapper\MicrolearningUserLogMapper;use LeadersLinked\Model\MicrolearningUserLog;use LeadersLinked\Mapper\MicrolearningTopicMapper;use LeadersLinked\Mapper\CompanyMapper;use LeadersLinked\Model\MicrolearningUserProgress;use LeadersLinked\Mapper\MicrolearningExtendUserMapper;use LeadersLinked\Mapper\MicrolearningExtendUserCompanyMapper;use LeadersLinked\Mapper\MicrolearningExtendUserFunctionMapper;use LeadersLinked\Mapper\MicrolearningExtendUserGroupMapper;use LeadersLinked\Mapper\MicrolearningExtendUserInstitutionMapper;use LeadersLinked\Mapper\MicrolearningExtendUserPartnerMapper;use LeadersLinked\Mapper\MicrolearningExtendUserProgramMapper;use LeadersLinked\Mapper\MicrolearningExtendUserStudentTypeMapper;use LeadersLinked\Mapper\MicrolearningExtendUserSectorMapper;use LeadersLinked\Mapper\MicrolearningQuizMapper;use LeadersLinked\Mapper\MicrolearningQuestionMapper;use LeadersLinked\Mapper\MicrolearningAnswerMapper;use LeadersLinked\Model\MicrolearningSlide;use LeadersLinked\Library\Storage;use LeadersLinked\Mapper\MicrolearningTopicCapsuleMapper;use LeadersLinked\Mapper\MicrolearningTopicUserMapper;use LeadersLinked\Model\MicrolearningTopicUser;class MicrolearningUserAccessGrantedIds{public $companies;public $topics;public $capsules;public function __construct(){$this->companies = [];$this->topics = [];$this->capsules = [];}}class MicrolearningController extends AbstractActionController{/**** @var \Laminas\Db\Adapter\AdapterInterface*/private $adapter;/**** @var \LeadersLinked\Cache\CacheInterface*/private $cache;/**** @var \Laminas\Log\LoggerInterface*/private $logger;/**** @var array*/private $config;/**** @var \Laminas\Mvc\I18n\Translator*/private $translator;/**** @param \Laminas\Db\Adapter\AdapterInterface $adapter* @param \LeadersLinked\Cache\CacheInterface $cache* @param \Laminas\Log\LoggerInterface LoggerInterface $logger* @param array $config* @param \Laminas\Mvc\I18n\Translator $translator*/public function __construct($adapter, $cache, $logger, $config, $translator){$this->adapter = $adapter;$this->cache = $cache;$this->logger = $logger;$this->config = $config;$this->translator = $translator;}public function indexAction(){$request = $this->getRequest();if($request->isGet()) {return new JsonModel(['success' => true,'data' => ['link_companies' => $this->url()->fromRoute('microlearning/companies',[], ['force_canonical' => true]),'link_timeline' => $this->url()->fromRoute('microlearning/timeline',[], ['force_canonical' => true]),'link_last_capsule_in_progress' => $this->url()->fromRoute('microlearning/last-capsule-in-progress',[], ['force_canonical' => true]),'link_profile' => $this->url()->fromRoute('microlearning/profile',[], ['force_canonical' => true]),'link_topics' => $this->url()->fromRoute('microlearning/topics',[], ['force_canonical' => true]),'link_capsules_pending' => $this->url()->fromRoute('microlearning/capsules-pending',[], ['force_canonical' => true]),'link_capsules_completed' => $this->url()->fromRoute('microlearning/capsules-completed',[], ['force_canonical' => true]),'link_capsules_in_progress' => $this->url()->fromRoute('microlearning/capsules-in-progress',[], ['force_canonical' => true]),]]);}return new JsonModel(['success' => false,'data' => 'ERROR_METHOD_NOT_ALLOWED']);}public function companiesAction(){$request = $this->getRequest();if($request->isGet()) {$currentNetworkPlugin = $this->plugin('currentNetworkPlugin');$currentNetwork = $currentNetworkPlugin->getNetwork();$accessGrantedIds = $this->getAccessGranted();$companyMapper = CompanyMapper::getInstance($this->adapter);$records = $companyMapper->fetchAllByIdsAndNetworkId($accessGrantedIds->companies, $currentNetwork->id);$storage = Storage::getInstance($this->config, $this->adapter);$companies = [];foreach($records as $record){array_push($companies, ['uuid' => $record->uuid,'name' => $record->name,'image' => $storage->getCompanyImage($record),'link_progress' => $this->url()->fromRoute('microlearning/progress',['id' => $record->uuid], ['force_canonical' => true]),]);}return new JsonModel(['success' => true,'data' => $companies]);}return new JsonModel(['success' => false,'data' => 'ERROR_METHOD_NOT_ALLOWED']);}public function capsuleCommentsAction(){$request = $this->getRequest();if($request->isGet()) {$serviceDatetimeFormat = $this->config['leaderslinked.services.datetime'];$currentUserPlugin = $this->plugin('currentUserPlugin');$currentUser = $currentUserPlugin->getUser();$capsule_id = $this->params()->fromRoute('capsule_id');$capsuleMapper = MicrolearningCapsuleMapper::getInstance($this->adapter);$capsule = $capsuleMapper->fetchOneByUuid($capsule_id);if(!$capsule) {return new JsonModel(['success' => false,'data' => 'ERROR_CAPSULE_NOT_FOUND']);}$userMapper = UserMapper::getInstance($this->adapter);$users = [];$storage = Storage::getInstance($this->config, $this->adapter);$capsuleCommentMapper = MicrolearningCapsuleCommentMapper::getInstance($this->adapter);$records = $capsuleCommentMapper->fetchAllByCapsuleId($capsule->id);$comments = [];foreach($records as $record){if(isset($users[$record->user_id])) {$user = $users[$record->user_id];} else {$user = $userMapper->fetchOne($record->user_id);if(!$user) {continue;}$users[$record->user_id] = $user;}$dt = \DateTime::createFromFormat('Y-m-d H:i:s', $record->added_on);array_push($comments, ['date' => $dt->format($serviceDatetimeFormat),'image' => $storage->getUserImage($user),'fullname' => trim(trim($user->first_name) . ' ' . trim($user->last_name)),'rating' => strval($record->rating),'comment' => $record->comment,'link_delete' => $record->user_id == $currentUser->id ? $this->url()->fromRoute('microlearning/capsules-comments/delete', ['capsule_id' => $capsule->uuid, 'comment_id' => $record->uuid], ['force_canonical' => true]) : '',]);}$dataCountAndRatingAverage = $capsuleCommentMapper->fetchCountAndRatingAverage($capsule->company_id, $capsule->id);return new JsonModel(['success' => true,'data' => ['comments' => $comments,'capsule' => ['total_comments' => strval($dataCountAndRatingAverage['total_comments']),'total_rating' => strval($dataCountAndRatingAverage['total_rating'])]]]);}return new JsonModel(['success' => false,'data' => 'ERROR_METHOD_NOT_ALLOWED']);}public function capsuleDeleteMyCommentAction(){$request = $this->getRequest();if($request->isPost()) {$currentUserPlugin = $this->plugin('currentUserPlugin');$currentUser = $currentUserPlugin->getUser();$capsule_id = $this->params()->fromRoute('capsule_id');$comment_id = $this->params()->fromRoute('comment_id');$capsuleMapper = MicrolearningCapsuleMapper::getInstance($this->adapter);$capsule = $capsuleMapper->fetchOneByUuid($capsule_id);if(!$capsule) {return new JsonModel(['success' => false,'data' => 'ERROR_CAPSULE_NOT_FOUND']);}$capsuleCommentMapper = MicrolearningCapsuleCommentMapper::getInstance($this->adapter);$capsuleComment = $capsuleCommentMapper->fetchOneByUuid($comment_id);if(!$capsuleComment) {return new JsonModel(['success' => false,'data' => 'ERROR_CAPSULE_COMMENT_NOT_FOUND',]);}if($capsuleComment->capsule_id != $capsule->id || $capsuleComment->user_id != $currentUser->id) {return new JsonModel(['success' => false,'data' => 'ERROR_YOU_DO_NOT_HAVE_ACCESS_TO_THIS_CAPSULE_COMMENT',]);}$result = $capsuleCommentMapper->delete($capsuleComment->id);if($result) {$dataCountAndRatingAverage = $capsuleCommentMapper->fetchCountAndRatingAverage($capsule->company_id, $capsule->id);return new JsonModel(['success' => true,'data' => ['message' => 'LABEL_CAPSULE_COMMENT_HAVE_BEEN_SUCCESSFULLY_DELETE','capsule' => ['total_comments' => strval($dataCountAndRatingAverage['total_comments']),'total_rating' => strval($dataCountAndRatingAverage['total_rating'])]],]);} else {return new JsonModel(['success' => false,'data' => $capsuleCommentMapper->getError()]);}}return new JsonModel(['success' => false,'data' => 'ERROR_METHOD_NOT_ALLOWED']);}public function capsuleAddMyCommentAction(){$request = $this->getRequest();if($request->isPost()) {$currentUserPlugin = $this->plugin('currentUserPlugin');$currentUser = $currentUserPlugin->getUser();$capsule_id = $this->params()->fromRoute('capsule_id');$capsuleMapper = MicrolearningCapsuleMapper::getInstance($this->adapter);$capsule = $capsuleMapper->fetchOneByUuid($capsule_id);if(!$capsule) {return new JsonModel(['success' => false,'data' => 'ERROR_CAPSULE_NOT_FOUND']);}$form = new CapsuleCommentForm();$dataPost = $request->getPost()->toArray();$dataPost['added_on'] = $capsuleMapper->getDatebaseNow();$form->setData($dataPost);if($form->isValid()) {$dataPost = (array) $form->getData();$capsuleComment = new MicrolearningCapsuleComment();$capsuleComment->company_id = $capsule->company_id;$capsuleComment->capsule_id = $capsule->id;$capsuleComment->user_id = $currentUser->id;$capsuleComment->comment = $dataPost['comment'];$capsuleComment->rating = strval($dataPost['rating']);$capsuleComment->added_on = $dataPost['added_on'];$capsuleCommentMapper = MicrolearningCapsuleCommentMapper::getInstance($this->adapter);$userMapper = UserMapper::getInstance($this->adapter);$storage = Storage::getInstance($this->config, $this->adapter);$result = $capsuleCommentMapper->insert($capsuleComment);if($result) {$capsuleComment = $capsuleCommentMapper->fetchOne($capsuleComment->id);$capsuleCommentUser = $userMapper->fetchOne($capsuleComment->user_id);$dataCountAndRatingAverage = $capsuleCommentMapper->fetchCountAndRatingAverage($capsule->company_id, $capsule->id);return new JsonModel(['success' => true,'data' => ['message' =>'LABEL_CAPSULE_COMMENT_HAVE_BEEN_SUCCESSFULLY_ADDED','comment' => ['uuid' => $capsuleComment->uuid,'date' => $capsuleComment->added_on,'image' => $storage->getUserImage($capsuleCommentUser),'fullname' => trim(trim($capsuleCommentUser->first_name) . ' ' . trim($capsuleCommentUser->last_name)),'rating' => strval($capsuleComment->rating),'comment' => $capsuleComment->comment,'rating' => $capsuleComment->rating,'link_delete' => $this->url()->fromRoute('microlearning/capsules-comments/delete', ['capsule_id' => $capsule->uuid, 'comment_id' => $capsuleComment->uuid], ['force_canonical' => true])],'capsule' => ['total_comments' => strval($dataCountAndRatingAverage['total_comments']),'total_rating' => strval($dataCountAndRatingAverage['total_rating'])]]]);} else {return new JsonModel(['success' => false,'data' => $capsuleCommentMapper->getError()]);}} else {$messages = [];$form_messages = (array) $form->getMessages();foreach($form_messages as $fieldname => $field_messages){$messages[$fieldname] = array_values($field_messages);}return new JsonModel(['success' => false,'data' => $messages]);}}return new JsonModel(['success' => false,'data' => 'ERROR_METHOD_NOT_ALLOWED']);}public function lastCapsuleInProgressAction(){$request = $this->getRequest();if($request->isGet()){$currentUserPlugin = $this->plugin('currentUserPlugin');$currentUser = $currentUserPlugin->getUser();$accessGrantedIds = $this->getAccessGranted();$userProgressMapper = MicrolearningUserProgressMapper::getInstance($this->adapter);$userProgress = $userProgressMapper->fetchOneLastCapsuleInProgressByUserIdAndTopicIds($currentUser->id, $accessGrantedIds->topics);if($userProgress) {$storage = Storage::getInstance($this->config, $this->adapter);$path = $storage->getPathMicrolearningCapsule();$capsuleMapper = MicrolearningCapsuleMapper::getInstance($this->adapter);$capsule = $capsuleMapper->fetchOne($userProgress->capsule_id);$capsuleCommentMapper = MicrolearningCapsuleCommentMapper::getInstance($this->adapter);$dataCountAndRatingAverage = $capsuleCommentMapper->fetchCountAndRatingAverage($capsule->company_id, $capsule->id);$image = $storage->getGenericImage($path, $capsule->uuid, $capsule->image);$response = ['success' => true,'data' => ['uuid' => $capsule->uuid,'name' => $capsule->name ? $capsule->name : '','description' => $capsule->description ? $capsule->description : '','image' => $image,'total_comments' => strval($dataCountAndRatingAverage['total_comments']),'total_rating' => strval($dataCountAndRatingAverage['total_rating']),'completed' => $userProgress->completed,'progress' => $userProgress->progress,'added_on' => $userProgress->added_on,'updated_on' => $userProgress->updated_on]];} else {$response = ['success' => true,'data' => []];}} else {$response = ['success' => false,'data' => 'ERROR_METHOD_NOT_ALLOWED'];}return new JsonModel($response);}public function capsulesPendingAction(){$request = $this->getRequest();if($request->isGet()) {$currentUserPlugin = $this->plugin('currentUserPlugin');$currentUser = $currentUserPlugin->getUser();$name = Functions::sanitizeFilterString($this->params()->fromQuery('name'));$order_field = Functions::sanitizeFilterString($this->params()->fromQuery('order_field'));$order_direction = Functions::sanitizeFilterString($this->params()->fromQuery('order_direction'));if(!in_array($order_field,['name', 'added_on'] )) {$order_field = 'name';}if(!in_array( $order_direction,['asc', 'desc'])) {$order_direction = 'asc';}$userProgressMapper = MicrolearningUserProgressMapper::getInstance($this->adapter);$capsuleMapper = MicrolearningCapsuleMapper::getInstance($this->adapter);$topicCapsuleMapper = MicrolearningTopicCapsuleMapper::getInstance($this->adapter); // Añadido$topicMapper = MicrolearningTopicMapper::getInstance($this->adapter);$capsuleCommentMapper = MicrolearningCapsuleCommentMapper::getInstance($this->adapter); // Reordenado$accessGranted = $this->getAccessGranted();$capsulesData = [];$storage = Storage::getInstance($this->config, $this->adapter);$path = $storage->getPathMicrolearningCapsule();foreach($accessGranted->topics as $topic_id){$topic = $topicMapper->fetchOne($topic_id);if(!$topic) {continue;}$capsules = $topicCapsuleMapper->fetchAllActiveByTopicId($topic_id) ?? [];foreach($capsules as $capsule) {$capsule = $capsuleMapper->fetchOne($capsule->capsule_id);if(!$capsule) {continue;}$userProgress = $userProgressMapper->fetchOneByUseridAndCapsuleId($currentUser->id, $capsule->id);if($userProgress) {continue;}if($name) {if(empty($name) || stripos($capsule->name, $name) === false) {continue;}}$dataCountAndRatingAverage = $capsuleCommentMapper->fetchCountAndRatingAverage($capsule->company_id, $capsule->id);$link_slides = $topic->uuid ? $this->url()->fromRoute('microlearning/slides', ['topic_id' => $topic->uuid, 'capsule_id' => $capsule->uuid], ['force_canonical' => true]) : '';array_push($capsulesData, ['uuid' => $capsule->uuid,'name' => $capsule->name ? $capsule->name : '','description' => $capsule->description ? $capsule->description : '','image' => $capsule->image ? $storage->getGenericImage($path, $capsule->uuid, $capsule->image) : '','link_comments' => $this->url()->fromRoute('microlearning/capsules-comments', ['capsule_id' => $capsule->uuid], ['force_canonical' => true]),'link_comment_add' => $this->url()->fromRoute('microlearning/capsules-comments/add', ['capsule_id' => $capsule->uuid],['force_canonical' => true]),'link_slides' => $link_slides,'total_comments' => strval($dataCountAndRatingAverage['total_comments']),'total_rating' => strval($dataCountAndRatingAverage['total_rating']),'progress' => 0,'added_on' => $capsule->added_on,'updated_on' => $capsule->updated_on,]);}}// 8. Ordenarif($order_field == 'name') {if($order_direction == 'asc') {usort($capsulesData, function($a, $b) {return strcasecmp($a['name'], $b['name']);});} else {usort($capsulesData, function($a, $b) {$result = strcasecmp($a['name'], $b['name']);if($result < 0) { return 1; } else if($result > 0) { return -1; } else { return 0; } // Simplificado});}}if($order_field == 'added_on') {if($order_direction == 'asc') {usort($capsulesData, function($a, $b) {return strcasecmp($a['added_on'], $b['added_on']);});} else {usort($capsulesData, function($a, $b) {$result = strcasecmp($a['added_on'], $b['added_on']);if($result < 0) { return 1; } else if($result > 0) { return -1; } else { return 0; } // Simplificado});}}// Ordenar por fecha de creación de la más reciente a la más antiguausort($capsulesData, function($a, $b) {return strcasecmp($b['added_on'], $a['added_on']);});// 9. Retornarreturn new JsonModel(['success' => true,'data' => $capsulesData]);}return new JsonModel(['success' => false,'data' => 'ERROR_METHOD_NOT_ALLOWED']);}public function capsulesCompletedAction(){$request = $this->getRequest();if($request->isGet()) {$currentUserPlugin = $this->plugin('currentUserPlugin');$currentUser = $currentUserPlugin->getUser();$name = Functions::sanitizeFilterString($this->params()->fromQuery('name'));$order_field = Functions::sanitizeFilterString($this->params()->fromQuery('order_field'));$order_direction = Functions::sanitizeFilterString($this->params()->fromQuery('order_direction'));if(!in_array($order_field,['name', 'added_on','last_access_on'] )) {$order_field = 'name';}if(!in_array( $order_direction,['asc', 'desc'])) {$order_field = 'asc';}$userProgressMapper = MicrolearningUserProgressMapper::getInstance($this->adapter);$capsuleMapper = MicrolearningCapsuleMapper::getInstance($this->adapter);$topicCapsuleMapper = MicrolearningTopicCapsuleMapper::getInstance($this->adapter);$topicMapper = MicrolearningTopicMapper::getInstance($this->adapter);$capsuleCommentMapper = MicrolearningCapsuleCommentMapper::getInstance($this->adapter);$accessGranted = $this->getAccessGranted();$capsulesData = [];$storage = Storage::getInstance($this->config, $this->adapter);$path = $storage->getPathMicrolearningCapsule();foreach($accessGranted->topics as $topic_id){$topic = $topicMapper->fetchOne($topic_id);if(!$topic) {continue;}$capsules = $topicCapsuleMapper->fetchAllActiveByTopicId($topic_id) ?? [];foreach($capsules as $capsule) {$capsule = $capsuleMapper->fetchOne($capsule->capsule_id);if(!$capsule) {continue;}$userProgress = $userProgressMapper->fetchOneByUseridAndCapsuleId($currentUser->id, $capsule->id);if(!$userProgress) {continue;}if($userProgress->completed == 0) {continue;}if($name) {if(empty($name) || stripos($capsule->name, $name) === false) {continue;}}$dataCountAndRatingAverage = $capsuleCommentMapper->fetchCountAndRatingAverage($capsule->company_id, $capsule->id);$link_slides = $topic->uuid ? $this->url()->fromRoute('microlearning/slides', ['topic_id' => $topic->uuid, 'capsule_id' => $capsule->uuid], ['force_canonical' => true]) : '';array_push($capsulesData, ['uuid' => $capsule->uuid,'name' => $capsule->name ? $capsule->name : '','description' => $capsule->description ? $capsule->description : '','image' => $capsule->image ? $storage->getGenericImage($path, $capsule->uuid, $capsule->image) : '','link_comments' => $this->url()->fromRoute('microlearning/capsules-comments', ['capsule_id' => $capsule->uuid], ['force_canonical' => true]),'link_comment_add' => $this->url()->fromRoute('microlearning/capsules-comments/add', ['capsule_id' => $capsule->uuid],['force_canonical' => true]),'link_slides' => $link_slides,'total_comments' => strval($dataCountAndRatingAverage['total_comments']),'total_rating' => strval($dataCountAndRatingAverage['total_rating']),'progress' => $userProgress->progress,'added_on' => $capsule->added_on,'last_access_on' => $userProgress->updated_on,'updated_on' => $capsule->updated_on,]);}}// 8. Ordenarif($order_field == 'name') {if($order_direction == 'asc') {usort($capsulesData, function($a, $b) {return strcasecmp($a['name'], $b['name']);});} else {usort($capsulesData, function($a, $b) {$result = strcasecmp($a['name'], $b['name']);if($result < 0) { return 1; } else if($result > 0) { return -1; } else { return 0; }});}}if($order_field == 'added_on') {if($order_direction == 'asc') {usort($capsulesData, function($a, $b) {return strcasecmp($a['added_on'], $b['added_on']);});} else {usort($capsulesData, function($a, $b) {$result = strcasecmp($a['added_on'], $b['added_on']);if($result < 0) { return 1; } else if($result > 0) { return -1; } else { return 0; }});}}if($order_field == 'last_access_on') {if($order_direction == 'asc') {usort($capsulesData, function($a, $b) {return strcasecmp($a['last_access_on'], $b['last_access_on']);});} else {usort($capsulesData, function($a, $b) {$result = strcasecmp($a['last_access_on'], $b['last_access_on']);if($result < 0) { return 1; } else if($result > 0) { return -1; } else { return 0; }});}}// Ordenar por ultima fecha de acceso de la más reciente a la más antiguausort($capsulesData, function($a, $b) {return strcasecmp($b['last_access_on'], $a['last_access_on']);});return new JsonModel(['success' => true,'data' => $capsulesData]);}return new JsonModel(['success' => false,'data' => 'ERROR_METHOD_NOT_ALLOWED']);}public function capsulesInProgressAction(){$request = $this->getRequest();if($request->isGet()) {$currentUserPlugin = $this->plugin('currentUserPlugin');$currentUser = $currentUserPlugin->getUser();$name = Functions::sanitizeFilterString($this->params()->fromQuery('name'));$order_field = Functions::sanitizeFilterString($this->params()->fromQuery('order_field'));$order_direction = Functions::sanitizeFilterString($this->params()->fromQuery('order_direction'));if(!in_array($order_field,['name', 'added_on', 'last_access_on'] )) {$order_field = 'name';}if(!in_array( $order_direction,['asc', 'desc'])) {$order_direction = 'asc';}$userProgressMapper = MicrolearningUserProgressMapper::getInstance($this->adapter);$capsuleMapper = MicrolearningCapsuleMapper::getInstance($this->adapter);$topicCapsuleMapper = MicrolearningTopicCapsuleMapper::getInstance($this->adapter);$topicMapper = MicrolearningTopicMapper::getInstance($this->adapter);$capsuleCommentMapper = MicrolearningCapsuleCommentMapper::getInstance($this->adapter);$accessGranted = $this->getAccessGranted();$capsulesData = [];$storage = Storage::getInstance($this->config, $this->adapter);$path = $storage->getPathMicrolearningCapsule();foreach($accessGranted->topics as $topic_id){$topic = $topicMapper->fetchOne($topic_id);if(!$topic) {continue;}$capsules = $topicCapsuleMapper->fetchAllActiveByTopicId($topic_id) ?? [];foreach($capsules as $capsule) {$capsule = $capsuleMapper->fetchOne($capsule->capsule_id);if(!$capsule) {continue;}$userProgress = $userProgressMapper->fetchOneByUseridAndCapsuleId($currentUser->id, $capsule->id);if(!$userProgress) {continue;}if($userProgress->completed == 1) {continue;}if($name) {if(empty($name) || stripos($capsule->name, $name) === false) {continue;}}$dataCountAndRatingAverage = $capsuleCommentMapper->fetchCountAndRatingAverage($capsule->company_id, $capsule->id);$link_slides = $topic->uuid ? $this->url()->fromRoute('microlearning/slides', ['topic_id' => $topic->uuid, 'capsule_id' => $capsule->uuid], ['force_canonical' => true]) : '';array_push($capsulesData, ['uuid' => $capsule->uuid,'name' => $capsule->name ? $capsule->name : '','description' => $capsule->description ? $capsule->description : '','image' => $capsule->image ? $storage->getGenericImage($path, $capsule->uuid, $capsule->image) : '','link_comments' => $this->url()->fromRoute('microlearning/capsules-comments', ['capsule_id' => $capsule->uuid], ['force_canonical' => true]),'link_comment_add' => $this->url()->fromRoute('microlearning/capsules-comments/add', ['capsule_id' => $capsule->uuid],['force_canonical' => true]),'link_slides' => $link_slides,'total_comments' => strval($dataCountAndRatingAverage['total_comments']),'total_rating' => strval($dataCountAndRatingAverage['total_rating']),'progress' => $userProgress->progress,'added_on' => $capsule->added_on,'last_access_on' => $userProgress->updated_on,'updated_on' => $capsule->updated_on,]);}}// 8. Ordenarif($order_field == 'name') {if($order_direction == 'asc') {usort($capsulesData, function($a, $b) {return strcasecmp($a['name'], $b['name']);});} else {usort($capsulesData, function($a, $b) {$result = strcasecmp($a['name'], $b['name']);if($result < 0) { return 1; } else if($result > 0) { return -1; } else { return 0; }});}}if($order_field == 'added_on') {if($order_direction == 'asc') {usort($capsulesData, function($a, $b) {return strcasecmp($a['added_on'], $b['added_on']);});} else {usort($capsulesData, function($a, $b) {$result = strcasecmp($a['added_on'], $b['added_on']);if($result < 0) { return 1; } else if($result > 0) { return -1; } else { return 0; }});}}if($order_field == 'last_access_on') {if($order_direction == 'asc') {usort($capsulesData, function($a, $b) {return strcasecmp($a['last_access_on'], $b['last_access_on']);});} else {usort($capsulesData, function($a, $b) {$result = strcasecmp($a['last_access_on'], $b['last_access_on']);if($result < 0) { return 1; } else if($result > 0) { return -1; } else { return 0; }});}}// Ordenar por ultima fecha de acceso de la más reciente a la más antiguausort($capsulesData, function($a, $b) {return strcasecmp($b['last_access_on'], $a['last_access_on']);});return new JsonModel(['success' => true,'data' => $capsulesData]);}return new JsonModel(['success' => false,'data' => 'ERROR_METHOD_NOT_ALLOWED']);}public function timelineAction(){$request = $this->getRequest();if($request->isGet()) {$currentUserPlugin = $this->plugin('currentUserPlugin');$currentUser = $currentUserPlugin->getUser();$page = intval($this->params()->fromQuery('page'), 10);$activities = [MicrolearningUserLog::ACTIVITY_SIGNIN => 'LABEL_MICROLEARNING_ACTIVITY_SIGNIN',MicrolearningUserLog::ACTIVITY_SIGNOUT => 'LABEL_MICROLEARNING_ACTIVITY_SIGNOUT',MicrolearningUserLog::ACTIVITY_START_TOPIC => 'LABEL_MICROLEARNING_ACTIVITY_START_TOPIC',MicrolearningUserLog::ACTIVITY_START_CAPSULE => 'LABEL_MICROLEARNING_ACTIVITY_START_CAPSULE',MicrolearningUserLog::ACTIVITY_VIEW_SLIDE => 'LABEL_MICROLEARNING_ACTIVITY_VIEW_SLIDE',MicrolearningUserLog::ACTIVITY_TAKE_A_TEST => 'LABEL_MICROLEARNING_ACTIVITY_TAKE_A_TEST',MicrolearningUserLog::ACTIVITY_RETAKE_A_TEST => 'LABEL_MICROLEARNING_ACTIVITY_RETAKE_A_TEST',MicrolearningUserLog::ACTIVITY_APPROVED_TEST => 'LABEL_MICROLEARNING_ACTIVITY_APPROVED_TEST',MicrolearningUserLog::ACTIVITY_COMPLETED_CAPSULE => 'LABEL_MICROLEARNING_ACTIVITY_COMPLETED_CAPSULE',MicrolearningUserLog::ACTIVITY_COMPLETED_TOPIC => 'LABEL_MICROLEARNING_ACTIVITY_COMPLETED_TOPIC',];$microlearningUserLogMapper = MicrolearningUserLogMapper::getInstance($this->adapter);$paginator = $microlearningUserLogMapper->getAllMessagesPaginatorByUserId($currentUser->id, $page);$items = [];foreach($paginator as $record){$dt = \DateTime::createFromFormat('Y-m-d H:i:s', $record->added_on);array_push($items, ['activity' => $activities[$record->activity],'added_on' => $dt->format('d/m/Y H:i a')]);}return new JsonModel(['success' => true,'data' => ['total' => ['count' => $paginator->getTotalItemCount(),'pages' => $paginator->getPages()->pageCount,],'current' => ['items' => $items,'page' => $paginator->getCurrentPageNumber(),'count' => $paginator->getCurrentItemCount(),]]]);} else {return new JsonModel(['success' => false,'data' => 'ERROR_METHOD_NOT_ALLOWED']);}}/*** Valores para la generación de los gráficos de progreso* Para las repuesta afirmativa* [* 'success' => true,* 'data' => [* 'topicTotal' => cantidad total de tópicos,* 'topicStarted' => cantidad de tópicos iniciados,* 'topicIncompleted' => cantidad de tópicos incompletos,* 'topicCompleted' => cantidad de tópicos completos,* 'percentCompleted' => % de diapositivas completados ,* 'percentIncompleted' => % de diapositivas incompletos ,* 'percentWithoutReturning' => % de cápsulas sin retorno después de completada,* 'percentWithReturning' => % de cápsulas con retorno después de completada,* ],* ]*** En caso contrario* [* 'success' => false,* 'data' => mensaje de error* ]*** @return \Laminas\View\Model\JsonModel*/public function progressAction(){$request = $this->getRequest();if($request->isGet()) {$currentUserPlugin = $this->plugin('currentUserPlugin');$currentUser = $currentUserPlugin->getUser();$accessGrantedIds = $this->getAccessGranted();$id = $this->params()->fromRoute('id');$companyMapper = CompanyMapper::getInstance($this->adapter);$company = $companyMapper->fetchOneByUuid($id);if(!$company) {$response = ['success' => false,'data' => 'ERROR_COMPANY_NOT_FOUND',];return new JsonModel($response);}if(!in_array($company->id, $accessGrantedIds->companies)) {$response = ['success' => false,'data' => 'ERROR_YOU_DO_NOT_HAVE_ACCESS_TO_THIS_COMPANY',];return new JsonModel($response);}$capsuleTotal = 0;$capsuleCompleted = 0;$capsuleWithReturning = 0;$capsuleWithoutReturning = 0;$capsuleStarted = 0;$capsuleToStart = 0;$percentCompleted = 0;$percentIncompleted = 100;$topicMapper = MicrolearningTopicMapper::getInstance($this->adapter);$topics = $topicMapper->fetchAllActiveByCompanyIdAndIds($company->id, $accessGrantedIds->topics);$progressMapper = MicrolearningUserProgressMapper::getInstance($this->adapter);$topicCapsuleMapper = MicrolearningTopicCapsuleMapper::getInstance($this->adapter);foreach($topics as $topic){$resultCount = $topicCapsuleMapper->fetchCountByCompanyIdAndTopicId($company->id, $topic->id);$capsuleTotal = $capsuleTotal + $resultCount;$resultCount = $progressMapper->fetchCountCapsulesCompletedByIdAndTopicId($currentUser->id, $topic->id);$capsuleCompleted = $capsuleCompleted + $resultCount;$resultCount = $progressMapper->fetchCountCapsulesCompletedWithReturningByIdAndTopicId($currentUser->id, $topic->id);$capsuleWithReturning = $capsuleWithReturning + $resultCount;$resultCount = $progressMapper->fetchCountCapsulesCompletedWithoutReturningByIdAndTopicId($currentUser->id, $topic->id);$capsuleWithoutReturning = $capsuleWithoutReturning + $resultCount;$resultCount = $progressMapper->fetchCountCapsulesCompletedByIdAndTopicId($currentUser->id, $topic->id);$capsuleStarted = $capsuleStarted + $resultCount;}$capsuleToStart = $capsuleTotal - $capsuleStarted;if($capsuleTotal > 0) {$percentCompleted = ($capsuleCompleted * 100) / $capsuleTotal;$percentIncompleted = 100 - $percentCompleted;}return new JsonModel(['success' => true,'data' => ['capsuleTotal' => $capsuleTotal,'capsuleCompleted' => $capsuleCompleted,'capsuleStarted' => $capsuleStarted,'capsuleToStart' => $capsuleToStart,'percentCompleted' => number_format($percentCompleted, 2, '.', ','),'percentIncompleted' => number_format($percentIncompleted, 2, '.', ','),'capsuleWithReturning' => $capsuleWithReturning,'capsuleWithoutReturning' => $capsuleWithoutReturning,],]);} else {return new JsonModel(['success' => false,'data' => 'ERROR_METHOD_NOT_ALLOWED']);}}public function topicsAction(){$request = $this->getRequest();if($request->isGet()) {$currentUserPlugin = $this->plugin('currentUserPlugin');$currentUser = $currentUserPlugin->getUser();$data = [];$accessGrantedIds = $this->getAccessGranted();$userProgressMapper = MicrolearningUserProgressMapper::getInstance($this->adapter);$topicMapper = MicrolearningTopicMapper::getInstance($this->adapter);$storage = Storage::getInstance($this->config, $this->adapter);$path = $storage->getPathMicrolearningTopic();foreach($accessGrantedIds->topics as $id){$topic = $topicMapper->fetchOne($id);if(!$topic) {continue;}$userProgress = $userProgressMapper->fetchOneByUserIdAndTopicId($currentUser->id, $id);if($userProgress) {$progress = $userProgress->progress;$completed = $userProgress->completed;} else {$progress = 0;$completed = 0;}array_push($data, ['uuid' => $topic->uuid,'name' => $topic->name ? $topic->name : '','description' => $topic->description ? $topic->description : '','image' => $topic->image ? $storage->getGenericImage($path, $topic->uuid, $topic->image) : '','progress' => $progress,'completed' => $completed,'order' => $topic->order,'added_on' => $topic->added_on,'updated_on' => $topic->updated_on]);}usort($data, function($a, $b) {$result = $a['order'] <=> $b['order'];if(0 == $result) {$result = strcasecmp($a['added_on'], $b['added_on']);if(0 == $result) {$result = strcasecmp($a['name'], $b['name']);}}if($result < 0) {return 1;} else if($result > 0) {return -1;} else {return 0;}});return new JsonModel(['success' => true,'data' => $data]);} else {return new JsonModel(['success' => false,'data' => 'ERROR_METHOD_NOT_ALLOWED']);}}public function getTopicAction(){// Handle GET request$request = $this->getRequest();if($request->isGet()) {// Get current user$currentUserPlugin = $this->plugin('currentUserPlugin');$currentUser = $currentUserPlugin->getUser();// Get topic ID from route$id = $this->params()->fromRoute('id');$topicMapper = MicrolearningTopicMapper::getInstance($this->adapter);$topic = $topicMapper->fetchOneByUuid($id);// Return error if topic not foundif(!$topic) {return new JsonModel(['success' => false,'data' => 'ERROR_TOPIC_NOT_FOUND']);}// Check if current user has access to the topic$accessGrantedIds = $this->getAccessGranted();if(!in_array($topic->id, $accessGrantedIds->topics)) {return new JsonModel(['success' => false,'data' => 'ERROR_YOU_DO_NOT_HAVE_ACCESS_TO_THIS_TOPIC']);}// Get user progress for this topic$userProgressMapper = MicrolearningUserProgressMapper::getInstance($this->adapter);$userProgress = $userProgressMapper->fetchOneByUserIdAndTopicId($currentUser->id, $topic->id);$progress = $userProgress->progress ?? 0;$completed = $userProgress->completed ?? 0;// Initialize storage service to get image paths$storage = Storage::getInstance($this->config, $this->adapter);$pathTopic = $storage->getPathMicrolearningTopic();// Fetch associated capsules using the private helper method$capsulesData = $this->_getCapsulesByTopic($topic, $storage);// Prepare data for JSON response$data = ['uuid' => $topic->uuid,'name' => $topic->name ? $topic->name : '','description' => $topic->description ? $topic->description : '','image' => $topic->image ? $storage->getGenericImage($pathTopic, $topic->uuid, $topic->image) : '','progress' => $progress,'completed' => $completed,'order' => $topic->order,'added_on' => $topic->added_on,'updated_on' => $topic->updated_on,'total_capsules' => count($capsulesData),'capsules' => $capsulesData,];return new JsonModel(['success' => true,'data' => $data]);} else {// Return error if not a GET requestreturn new JsonModel(['success' => false,'data' => 'ERROR_METHOD_NOT_ALLOWED']);}}/*** @param MicrolearningTopic $topic The topic object.* @param Storage $storage The storage object.* @return array The capsules data.*/private function _getCapsulesByTopic($topic, $storage){$data = [];$accessGrantedIds = $this->getAccessGranted();if (!$topic) {return $data;}if (!in_array($topic->id, $accessGrantedIds->topics)) {return $data;}$currentUserPlugin = $this->plugin('currentUserPlugin');$currentUser = $currentUserPlugin->getUser();$topicCapsuleMapper = MicrolearningTopicCapsuleMapper::getInstance($this->adapter);$topicCapsuleRelations = $topicCapsuleMapper->fetchAllActiveByTopicId($topic->id);$userProgressMapper = MicrolearningUserProgressMapper::getInstance($this->adapter);$capsuleCommentMapper = MicrolearningCapsuleCommentMapper::getInstance($this->adapter);$path = $storage->getPathMicrolearningCapsule();foreach ($topicCapsuleRelations as $relation) {if(!in_array($relation->topic_id, $accessGrantedIds->topics)) {continue;}$capsuleMapper = MicrolearningCapsuleMapper::getInstance($this->adapter);$capsule = $capsuleMapper->fetchOne($relation->capsule_id);if(!$capsule) {continue;}$userProgress = $userProgressMapper->fetchOneByUseridAndCapsuleId($currentUser->id, $capsule->id);$progress = $userProgress->progress ?? 0;$completed = $userProgress->completed ?? 0;$dataCountAndRatingAverage = $capsuleCommentMapper->fetchCountAndRatingAverage($capsule->company_id, $capsule->id);$image = $capsule->image ? $storage->getGenericImage($path, $capsule->uuid, $capsule->image) : '';$total_comments = strval($dataCountAndRatingAverage['total_comments']);$total_rating = strval($dataCountAndRatingAverage['total_rating']);array_push($data, ['uuid' => $capsule->uuid,'name' => $capsule->name ? $capsule->name : '','description' => $capsule->description ? $capsule->description : '','image' => $image,'total_comments' => $total_comments,'total_rating' => $total_rating,'progress' => $progress,'completed' => $completed,'added_on' => $capsule->added_on,'updated_on' => $capsule->updated_on,]);}return $data;}/*** @param MicrolearningCapsule $capsule The capsule object.* @param Storage $storage The storage object.* @return array The slides data.*/private function _getSlidesByCapsule($capsule, $storage){$data = [];$accessGrantedIds = $this->getAccessGranted();if (!$capsule) {return $data;}if (!in_array($capsule->id, $accessGrantedIds->capsules)) {return $data;}$currentUserPlugin = $this->plugin('currentUserPlugin');$currentUser = $currentUserPlugin->getUser();$slideMapper = MicrolearningSlideMapper::getInstance($this->adapter);$userProgressMapper = MicrolearningUserProgressMapper::getInstance($this->adapter);$quizMapper = MicrolearningQuizMapper::getInstance($this->adapter);$path = $storage->getPathMicrolearningSlide();$slides = $slideMapper->fetchAllByCompanyIdAndCapsuleId($capsule->company_id, $capsule->id);foreach ($slides as $slide) {$userProgress = $userProgressMapper->fetchOneByUserIdAndSlideId($currentUser->id, $slide->id);$completed = $userProgress ? $userProgress->completed : 0;$quiz_uuid = '';$quiz_data = [];$link_take_a_test = '';if ($slide->quiz_id) {$quiz = $quizMapper->fetchOne($slide->quiz_id);if ($quiz) {$quiz_uuid = $quiz->uuid;$quiz_data = $this->getQuiz($slide->quiz_id);$link_take_a_test = $this->url()->fromRoute('microlearning/take-a-test', ['slide_id' => $slide->uuid], ['force_canonical' => true]);}}array_push($data, ['quiz' => $quiz_uuid,'quiz_data' => $quiz_data,'uuid' => $slide->uuid,'name' => $slide->name ? $slide->name : '','description' => $slide->description ? $slide->description : '','type' => $slide->type,'background' => $slide->background ? $storage->getGenericImage($path, $slide->uuid, $slide->background) : '','file' => $slide->file ? $storage->getGenericFile($path, $slide->uuid, $slide->file) : '','order' => $slide->order,'completed' => $completed,'link_take_a_test' => $link_take_a_test,'added_on' => $slide->added_on,'updated_on' => $slide->updated_on,]);}// Sort slides by order, then by added_on, then by nameusort($data, function($a, $b) {$result = $a['order'] <=> $b['order'];if (0 == $result) {$result = strcasecmp($a['added_on'], $b['added_on']);if (0 == $result) {$result = strcasecmp($a['name'], $b['name']);}}if ($result < 0) {return 1;} else if ($result > 0) {return -1;} else {return 0;}});return $data;}public function capsulesAction(){$request = $this->getRequest();if($request->isGet()) {$currentUserPlugin = $this->plugin('currentUserPlugin');$currentUser = $currentUserPlugin->getUser();$topic_id_param = $this->params()->fromRoute('topic_id');$topicMapper = MicrolearningTopicMapper::getInstance($this->adapter);$topic = $topicMapper->fetchOneByUuid($topic_id_param);if(!$topic) {return new JsonModel(['success' => false,'data' => 'ERROR_TOPIC_NOT_FOUND']);}$accessGrantedIds = $this->getAccessGranted();if(!in_array($topic->id, $accessGrantedIds->topics)) {return new JsonModel(['success' => false,'data' => 'ERROR_YOU_DO_NOT_HAVE_ACCESS_TO_THIS_TOPIC']);}$storage = Storage::getInstance($this->config, $this->adapter);// Use the _getCapsulesByTopic method to fetch capsules$data = $this->_getCapsulesByTopic($topic, $storage);// The _getCapsulesByTopic method already returns capsules with the required data structure.// We just need to sort them.usort($data, function($a, $b) {$result = $a['order'] <=> $b['order'];if(0 == $result) {$result = strcasecmp($a['added_on'], $b['added_on']);if(0 == $result) {$result = strcasecmp($a['name'], $b['name']);}}if($result < 0) {return 1;} else if($result > 0) {return -1;} else {return 0;}});return new JsonModel(['success' => true,'data' => $data]);} else {return new JsonModel(['success' => false,'data' => 'ERROR_METHOD_NOT_ALLOWED']);}}public function takeTestAction(){$request = $this->getRequest();if($request->isPost()) {$currentUserPlugin = $this->plugin('currentUserPlugin');$currentUser = $currentUserPlugin->getUser();$slide_id = $this->params()->fromRoute('slide_id');$slideMapper = MicrolearningSlideMapper::getInstance($this->adapter);$slide = $slideMapper->fetchOneByUuid($slide_id);if(!$slide) {return new JsonModel(['success' => false,'data' => 'ERROR_SLIDE_NOT_FOUND']);}if($slide->type != MicrolearningSlide::TYPE_QUIZ) {return new JsonModel(['success' => false,'data' => 'ERROR_SLIDE_IS_NOT_QUIZ']);}$capsuleMapper = MicrolearningCapsuleMapper::getInstance($this->adapter);$capsule = $capsuleMapper->fetchOne($slide->capsule_id);if(!$capsule) {return new JsonModel(['success' => false,'data' => 'ERROR_CAPSULE_NOT_FOUND']);}$accessGrantedIds = $this->getAccessGranted();if(!in_array($capsule->id, $accessGrantedIds->capsules)) {return new JsonModel(['success' => false,'data' => 'ERROR_YOU_DO_NOT_HAVE_ACCESS_TO_THIS_CAPSULE']);}$userLogMapper = MicrolearningUserLogMapper::getInstance($this->adapter);$userLog = $userLogMapper->fetchOneTakeATestByUserIdAndSlideId($currentUser->id, $slide->id);if($userLog) {$activity = MicrolearningUserLog::ACTIVITY_RETAKE_A_TEST;} else {$activity = MicrolearningUserLog::ACTIVITY_TAKE_A_TEST;}$added_on = $userLogMapper->getDatebaseNow();$userLog = new MicrolearningUserLog();$userLog->activity = $activity;$userLog->user_id = $currentUser->id;$userLog->company_id = $slide->company_id;$userLog->topic_id = $slide->topic_id;$userLog->capsule_id = $slide->capsule_id;$userLog->slide_id = $slide->id;$userLog->added_on = $added_on;if($userLogMapper->insert($userLog)) {return new JsonModel(['success' => true,]);} else {return new JsonModel(['success' => false,'data' => $userLogMapper->getError()]);}} else {return new JsonModel(['success' => false,'data' => 'ERROR_METHOD_NOT_ALLOWED']);}}public function getCapsuleAction(){$request = $this->getRequest();if($request->isGet()) {$currentUserPlugin = $this->plugin('currentUserPlugin');$currentUser = $currentUserPlugin->getUser();$capsule_uuid = $this->params()->fromRoute('id');$capsuleMapper = MicrolearningCapsuleMapper::getInstance($this->adapter);$capsule = $capsuleMapper->fetchOneByUuid($capsule_uuid);if(!$capsule) {return new JsonModel(['success' => false,'data' => 'ERROR_CAPSULE_NOT_FOUND']);}$accessGrantedIds = $this->getAccessGranted();if(!in_array($capsule->id, $accessGrantedIds->capsules)) {return new JsonModel(['success' => false,'data' => 'ERROR_YOU_DO_NOT_HAVE_ACCESS_TO_THIS_CAPSULE']);}$userProgressMapper = MicrolearningUserProgressMapper::getInstance($this->adapter);$capsuleCommentMapper = MicrolearningCapsuleCommentMapper::getInstance($this->adapter);$userProgress = $userProgressMapper->fetchOneByUseridAndCapsuleId($currentUser->id, $capsule->id);$progress = $userProgress->progress ?? 0;$completed = $userProgress->completed ?? 0;$dataCountAndRatingAverage = $capsuleCommentMapper->fetchCountAndRatingAverage($capsule->company_id, $capsule->id);// Get comments data$userMapper = UserMapper::getInstance($this->adapter);$storage = Storage::getInstance($this->config, $this->adapter);$serviceDatetimeFormat = $this->config['leaderslinked.services.datetime'];$comments = [];$records = $capsuleCommentMapper->fetchAllByCapsuleId($capsule->id);foreach($records as $record) {$user = $userMapper->fetchOne($record->user_id);if(!$user) {continue;}$dt = \DateTime::createFromFormat('Y-m-d H:i:s', $record->added_on);array_push($comments, ['uuid' => $record->uuid,'date' => $dt->format($serviceDatetimeFormat),'image' => $storage->getUserImage($user),'fullname' => trim(trim($user->first_name) . ' ' . trim($user->last_name)),'rating' => strval($record->rating),'comment' => $record->comment,'link_delete' => $record->user_id == $currentUser->id ? $this->url()->fromRoute('microlearning/capsules-comments/delete', ['capsule_id' => $capsule->uuid, 'comment_id' => $record->uuid], ['force_canonical' => true]) : '']);}$path = $storage->getPathMicrolearningCapsule();$slides = $this->_getSlidesByCapsule($capsule, $storage);$image = $storage->getGenericImage($path, $capsule->uuid, $capsule->image);$data = ['uuid' => $capsule->uuid,'name' => $capsule->name ?? '','description' => $capsule->description ?? '','image' => $image,'link_comment_add' => $this->url()->fromRoute('microlearning/capsules-comments/add', ['capsule_id' => $capsule->uuid], ['force_canonical' => true]),'total_comments' => strval($dataCountAndRatingAverage['total_comments']),'total_rating' => strval($dataCountAndRatingAverage['total_rating']),'comments' => $comments,'progress' => $progress,'completed' => $completed,'total_slides' => count($slides),'slides' => $slides,'added_on' => $capsule->added_on,'updated_on' => $capsule->updated_on,];return new JsonModel(['success' => true,'data' => $data]);}return new JsonModel(['success' => false,'data' => 'ERROR_METHOD_NOT_ALLOWED']);}public function slidesAction(){$request = $this->getRequest();if($request->isGet()) {$currentUserPlugin = $this->plugin('currentUserPlugin');$currentUser = $currentUserPlugin->getUser();$topic_id = $this->params()->fromRoute('topic_id');$topicMapper = MicrolearningTopicMapper::getInstance($this->adapter);$topic = $topicMapper->fetchOneByUuid($topic_id);if(!$topic) {return new JsonModel(['success' => false,'data' => 'ERROR_TOPIC_NOT_FOUND']);}$accessGrantedIds = $this->getAccessGranted();if(!in_array($topic->id, $accessGrantedIds->topics)) {return new JsonModel(['success' => false,'data' => 'ERROR_YOU_DO_NOT_HAVE_ACCESS_TO_THIS_TOPIC']);}$capsule_id = $this->params()->fromRoute('capsule_id');$capsuleMapper = MicrolearningCapsuleMapper::getInstance($this->adapter);$capsule = $capsuleMapper->fetchOneByUuid($capsule_id);if(!$capsule) {return new JsonModel(['success' => false,'data' => 'ERROR_CAPSULE_NOT_FOUND']);}if(!in_array($capsule->id, $accessGrantedIds->capsules)) {return new JsonModel(['success' => false,'data' => 'ERROR_YOU_DO_NOT_HAVE_ACCESS_TO_THIS_CAPSULE']);}$data = [];$quizMapper = MicrolearningQuizMapper::getInstance($this->adapter);$slideMapper = MicrolearningSlideMapper::getInstance($this->adapter);$userProgressMapper = MicrolearningUserProgressMapper::getInstance($this->adapter);$storage = Storage::getInstance($this->config, $this->adapter);$path = $storage->getPathMicrolearningSlide();$slides = $slideMapper->fetchAllByCompanyIdAndTopicIdAndCapsuleId($capsule->company_id, $capsule->topic_id, $capsule->id);foreach($slides as $slide){$userProgress = $userProgressMapper->fetchOneByUserIdAndSlideId($currentUser->id, $slide->id);if($userProgress) {$completed = $userProgress->completed ;} else {$completed = 0;}$link_take_a_test = '';if($slide->quiz_id) {$quizMapper = MicrolearningQuizMapper::getInstance($this->adapter);$quiz = $quizMapper->fetchOne($slide->quiz_id);if($quiz) {$quiz_uuid = $quiz->uuid;$quiz_data = $this->getQuiz($slide->quiz_id);$link_take_a_test = $this->url()->fromRoute('microlearning/take-a-test', ['slide_id' => $slide->uuid], ['force_canonical' => true]);}}array_push($data, ['quiz' => $quiz_uuid,'quiz_data' => $quiz_data,'uuid' => $slide->uuid,'name' => $slide->name ? $slide->name : '','description' => $slide->description ? $slide->description : '','type' => $slide->type,'background' => $slide->background ? $storage->getGenericImage($path, $slide->uuid, $slide->background) : '','file' => $slide->file ? $storage->getGenericFile($path, $slide->uuid, $slide->file) : '','order' => $slide->order,'completed' => $completed,'link_take_a_test' => $link_take_a_test,'added_on' => $slide->added_on,'updated_on' => $slide->updated_on,]);}usort($data, function($a, $b) {$result = $a['order'] <=> $b['order'];if(0 == $result) {$result = strcasecmp($a['added_on'], $b['added_on']);if(0 == $result) {$result = strcasecmp($a['name'], $b['name']);}}if($result < 0) {return 1;} else if($result > 0) {return -1;} else {return 0;}});return new JsonModel(['success' => true,'data' => $data]);} else {return new JsonModel(['success' => false,'data' => 'ERROR_METHOD_NOT_ALLOWED']);}}private function getQuiz($id){$serviceDatetimeFormat = $this->config['leaderslinked.services.datetime'];$data = [];$quizMapper = MicrolearningQuizMapper::getInstance($this->adapter);$quiz = $quizMapper->fetchOne($id);if(!$quiz) {return [];}$companyMapper = CompanyMapper::getInstance($this->adapter);$company = $companyMapper->fetchOne($quiz->company_id);$questionMapper = MicrolearningQuestionMapper::getInstance($this->adapter);$answerMapper = MicrolearningAnswerMapper::getInstance($this->adapter);$record_questions = [];$questions = $questionMapper->fetchAllByQuizId($quiz->id);foreach($questions as $question){$record_answers = [];$answers = $answerMapper->fetchAllByQuizIdAndQuestionId($question->quiz_id, $question->id);foreach($answers as $answer){$dtAddedOn = \DateTime::createFromFormat('Y-m-d H:i:s', $answer->added_on);$dtUpdatedOn = \DateTime::createFromFormat('Y-m-d H:i:s', $answer->updated_on);array_push($record_answers, ['uuid' => $answer->uuid,'text' => trim($answer->text),'correct' => $answer->correct ? $answer->correct : 0 ,'points' => strval(intval($answer->points, 10)),'added_on' => $dtAddedOn->format($serviceDatetimeFormat),'updated_on' => $dtUpdatedOn->format($serviceDatetimeFormat),]);}$dtAddedOn = \DateTime::createFromFormat('Y-m-d H:i:s', $question->added_on);$dtUpdatedOn = \DateTime::createFromFormat('Y-m-d H:i:s', $question->updated_on);array_push($record_questions, ['uuid' => $question->uuid,'text' => trim($question->text),'type' => $question->type,'maxlength' => strval($question->maxlength),'points' => strval($question->points),'answers' => $record_answers,'added_on' => $dtAddedOn->format($serviceDatetimeFormat),'updated_on' => $dtUpdatedOn->format($serviceDatetimeFormat),]);}$storage = Storage::getInstance($this->config, $this->adapter);$dtAddedOn = \DateTime::createFromFormat('Y-m-d H:i:s', $quiz->added_on);$dtUpdatedOn = \DateTime::createFromFormat('Y-m-d H:i:s', $quiz->updated_on);array_push($data, ['uuid' => $quiz->uuid,'name' => $quiz->name,'text' => trim($quiz->text ? $quiz->text : ''),'failed' => trim($quiz->failed ? $quiz->failed : ''),'points' => strval($quiz->points),'minimum_points_required' => strval($quiz->minimum_points_required),'max_time' => $quiz->max_time ? $quiz->max_time : 5,'company_uuid' => $company->uuid,'company_name' => $company->name,'company_image' => $storage->getCompanyImage($company),'questions' => $record_questions,'added_on' => $dtAddedOn->format($serviceDatetimeFormat),'updated_on' => $dtUpdatedOn->format($serviceDatetimeFormat),]);return $data;}public function getSlideAction(){$request = $this->getRequest();if($request->isGet()) {$currentUserPlugin = $this->plugin('currentUserPlugin');$currentUser = $currentUserPlugin->getUser();$id = $this->params()->fromRoute('id');$slideMapper = MicrolearningSlideMapper::getInstance($this->adapter);$slide = $slideMapper->fetchOneByUuid($id);if(!$slide) {return new JsonModel(['success' => false,'data' => 'ERROR_SLIDE_NOT_FOUND']);}$accessGrantedIds = $this->getAccessGranted();if(!in_array($slide->capsule_id, $accessGrantedIds->capsules)) {return new JsonModel(['success' => false,'data' => 'ERROR_YOU_DO_NOT_HAVE_ACCESS_TO_THIS_CAPSULE']);}$slideMapper = MicrolearningSlideMapper::getInstance($this->adapter);$userProgressMapper = MicrolearningUserProgressMapper::getInstance($this->adapter);$userProgress = $userProgressMapper->fetchOneByUserIdAndSlideId($currentUser->id, $slide->id);if($userProgress) {$completed = $userProgress->completed;} else {$completed = 0;}$quiz_uuid = '';$quiz_data = [];$link_take_a_test = '';if($slide->quiz_id) {$quizMapper = MicrolearningQuizMapper::getInstance($this->adapter);$quiz = $quizMapper->fetchOne($slide->quiz_id);if($quiz) {$quiz_uuid = $quiz->uuid;$quiz_data = $this->getQuiz($slide->quiz_id);$link_take_a_test = $this->url()->fromRoute('microlearning/take-a-test', ['slide_id' => $slide->uuid], ['force_canonical' => true]);}}$storage = Storage::getInstance($this->config, $this->adapter);$path = $storage->getPathMicrolearningSlide();$image = $storage->getGenericImage($path, $slide->uuid, $slide->background);$file = $storage->getGenericFile($path, $slide->uuid, $slide->file);$data =['quiz' => $quiz_uuid,'quiz_data' => $quiz_data,'uuid' => $slide->uuid,'name' => $slide->name ? $slide->name : '','description' => $slide->description ? $slide->description : '','type' => $slide->type,'background' => $image,'file' => $file,'order' => $slide->order,'completed' => $completed,'link_take_a_test' => $link_take_a_test,'added_on' => $slide->added_on,'updated_on' => $slide->updated_on,];return new JsonModel(['success' => true,'data' => $data]);} else {return new JsonModel(['success' => false,'data' => 'ERROR_METHOD_NOT_ALLOWED']);}}public function profileAction(){$request = $this->getRequest();if($request->isGet()) {$currentUserPlugin = $this->plugin('currentUserPlugin');$currentUser = $currentUserPlugin->getUser();$accessGrantedIds = $this->getAccessGranted();$companyMapper = CompanyMapper::getInstance($this->adapter);$companyExtendUserMapper = MicrolearningExtendUserMapper::getInstance($this->adapter);$companyExtendUserCompanyMapper = MicrolearningExtendUserCompanyMapper::getInstance($this->adapter);$companyExtendUserFunctionMapper = MicrolearningExtendUserFunctionMapper::getInstance($this->adapter);$companyExtendUserGroupMapper = MicrolearningExtendUserGroupMapper::getInstance($this->adapter);$companyExtendUserInstitutionMapper = MicrolearningExtendUserInstitutionMapper::getInstance($this->adapter);$companyExtendUserPartnerMapper = MicrolearningExtendUserPartnerMapper::getInstance($this->adapter);$companyExtendUserProgramMapper = MicrolearningExtendUserProgramMapper::getInstance($this->adapter);$companyExtendUserStudentTypeMapper = MicrolearningExtendUserStudentTypeMapper::getInstance($this->adapter);$companyExtendUserSectorMapper = MicrolearningExtendUserSectorMapper::getInstance($this->adapter);$storage = Storage::getInstance($this->config, $this->adapter);$data = [];foreach($accessGrantedIds->companies as $company_id){$company = $companyMapper->fetchOne($company_id);if(!$company) {continue;}$record = ['name' => $company->name,'image' => $storage->getCompanyImage($company),'details' => [],];$companyExtendUser = $companyExtendUserMapper->fetchOneByCompanyIdAndUserId($company->id, $currentUser->id);if(!$companyExtendUser) {continue;}if($companyExtendUser->extend_company_id) {$extendedCompany = $companyExtendUserCompanyMapper->fetchOne($companyExtendUser->company_id);if($extendedCompany) {array_push($record['details'],['uuid' => $extendedCompany->uuid,'label' => 'LABEL_COMPANY','value' => $extendedCompany->name]);}}if($companyExtendUser->extend_function_id) {$extendedFunction = $companyExtendUserFunctionMapper->fetchOne($companyExtendUser->extend_function_id);if($extendedFunction) {array_push($record['details'],['uuid' => $extendedFunction->uuid,'label' => 'LABEL_FUNCTION','value' => $extendedFunction->name]);}}if($companyExtendUser->extend_group_id) {$extendedGroup = $companyExtendUserGroupMapper->fetchOne($companyExtendUser->extend_group_id);if($extendedGroup) {array_push($record['details'],['uuid' => $extendedGroup->uuid,'label' => 'LABEL_GROUP','value' => $extendedGroup->name]);}}if($companyExtendUser->extend_institution_id) {$extendedInstitution= $companyExtendUserInstitutionMapper->fetchOne($companyExtendUser->extend_institution_id);if($extendedInstitution) {array_push($record['details'],['uuid' => $extendedInstitution->uuid,'label' => 'LABEL_INSTITUTION','value' => $extendedInstitution->name]);}}if($companyExtendUser->extend_program_id) {$extendedProgram = $companyExtendUserProgramMapper->fetchOne($companyExtendUser->extend_program_id);if($extendedProgram) {array_push($record['details'],['uuid' => $extendedProgram->uuid,'label' => 'LABEL_PROGRAM','value' => $extendedProgram->name]);}}if($companyExtendUser->extend_sector_id) {$extendedSector = $companyExtendUserSectorMapper->fetchOne($companyExtendUser->extend_sector_id);if($extendedSector) {array_push($record['details'],['uuid' => $extendedSector->uuid,'label' => 'LABEL_SECTOR','value' => $extendedSector->name]);}}if($companyExtendUser->extend_partner_id) {$extendedPartner = $companyExtendUserPartnerMapper->fetchOne($companyExtendUser->extend_partner_id);if($extendedPartner) {array_push($record['details'],['uuid' => $extendedPartner->uuid,'label' => 'LABEL_PARTNER','value' => $extendedPartner->name]);}}if($companyExtendUser->extend_student_type_id) {$extendedStudentType = $companyExtendUserStudentTypeMapper->fetchOne($companyExtendUser->extend_student_type_id);if($extendedStudentType) {array_push($record['details'],['uuid' => $extendedStudentType->uuid,'label' => 'LABEL_TYPE','value' => $extendedStudentType->name]);}}array_push($data, $record);}return new JsonModel(['success' => true,'data' => $data]);} else {return new JsonModel(['success' => false,'data' => 'ERROR_METHOD_NOT_ALLOWED']);}}/**** @return \LeadersLinked\Controller\MicrolearningUserAccessGrantedIds*/private function getAccessGranted(){$currentUserPlugin = $this->plugin('currentUserPlugin');$currentUser = $currentUserPlugin->getUser();$topicUserMapper = MicrolearningTopicUserMapper::getInstance($this->adapter);$topicCapsuleMapper = MicrolearningTopicCapsuleMapper::getInstance($this->adapter);$now = $topicUserMapper->getDatebaseNow();$records = $topicUserMapper->fetchAllActiveByUserId($currentUser->id);$accessGrantedIds = new MicrolearningUserAccessGrantedIds();foreach($records as $record){if($record->access != MicrolearningTopicUser::ACCESS_UNLIMITED && $record->access != MicrolearningTopicUser::ACCESS_PAY_PERIOD) {continue;}if($record->access == MicrolearningTopicUser::ACCESS_PAY_PERIOD) {if($now < $record->paid_from || $now > $record->paid_to) {continue;}}// Verificar si la empresa está en la lista de empresas permitidasif(!in_array($record->company_id, $accessGrantedIds->companies )) {array_push($accessGrantedIds->companies, $record->company_id);}// Verificar si el tópico está en la lista de tópicos permitidosif(!in_array($record->topic_id, $accessGrantedIds->topics )) {array_push( $accessGrantedIds->topics, $record->topic_id);}// Verificar si la cápsula está en la lista de cápsulas permitidas$topicCapsules = $topicCapsuleMapper->fetchAllActiveByTopicId($record->topic_id);foreach($topicCapsules as $topicCapsule) {if(!in_array($topicCapsule->capsule_id, $accessGrantedIds->capsules)) {array_push($accessGrantedIds->capsules, $topicCapsule->capsule_id);}}}return $accessGrantedIds;}/*** Marks a slide as completed and updates progress for capsule and topic** @return \Laminas\View\Model\JsonModel*/public function markSlideCompletedAction(){$request = $this->getRequest();if (!$request->isPost()) {return new JsonModel(['success' => false, 'data' => 'ERROR_INVALID_REQUEST']);}// Get parameters$slide_uuid = $this->params()->fromRoute('slide_uuid');if (empty($slide_uuid)) {return new JsonModel(['success' => false, 'data' => 'ERROR_MISSING_PARAMETERS']);}// Get current user$currentUser = $this->plugin('currentUserPlugin')->getUser();$user_id = $currentUser->id ?? null;if (!$user_id) {return new JsonModel(['success' => false, 'data' => 'ERROR_USER_NOT_FOUND']);}// Get access permissions$accessGrantedIds = $this->getAccessGranted();// Get slide$slideMapper = MicrolearningSlideMapper::getInstance($this->adapter);$slide = $slideMapper->fetchOneByUuid($slide_uuid);if (!$slide) {return new JsonModel(['success' => false, 'data' => 'ERROR_SLIDE_NOT_FOUND']);}// Get capsule and verify access$capsuleMapper = MicrolearningCapsuleMapper::getInstance($this->adapter);$capsule = $capsuleMapper->fetchOne($slide->capsule_id);if (!$capsule || !in_array($capsule->id, $accessGrantedIds->capsules)) {return new JsonModel(['success' => false, 'data' => 'ERROR_CAPSULE_ACCESS_DENIED']);}// Get topic-capsule relations$topicCapsuleMapper = MicrolearningTopicCapsuleMapper::getInstance($this->adapter);$relations = $topicCapsuleMapper->fetchAllByCapsuleId($capsule->id);if (!$relations) {return new JsonModel(['success' => false, 'data' => 'ERROR_CAPSULE_DOES_NOT_BELONG_TO_TOPIC']);}$progressMapper = MicrolearningUserProgressMapper::getInstance($this->adapter);// Actualizar progresoforeach ($relations as $relation) {// Actualizar progreso de la diapositivaif(!$progressMapper->updateSlideProgress($user_id, $relation->company_id, $slide->id, $relation->capsule_id, $relation->topic_id)){$this->logger->err('Error updating slide progress: ' . $progressMapper->getError());return new JsonModel(['success' => false, 'data' => 'ERROR_COULD_NOT_UPDATE_SLIDE_PROGRESS']);}// Actualizar progreso de la cápsulaif(!$progressMapper->updateCapsuleProgress($user_id, $relation->company_id, $slide->id, $relation->capsule_id, $relation->topic_id)){$this->logger->err('Error updating capsule progress: ' . $progressMapper->getError());return new JsonModel(['success' => false, 'data' => 'ERROR_COULD_NOT_UPDATE_CAPSULE_PROGRESS']);}// Actualizar progreso del tópicoif(!$progressMapper->updateTopicProgress($user_id, $relation->company_id, $slide->id, $relation->capsule_id, $relation->topic_id)){$this->logger->err('Error updating topic progress: ' . $progressMapper->getError());return new JsonModel(['success' => false, 'data' => 'ERROR_COULD_NOT_UPDATE_TOPIC_PROGRESS']);}}return new JsonModel(['success' => true, 'data' => "LABEL_THE_USER_PROGRESS_FOR_THIS_SLIDE_HAS_BEEN_COMPLETED"]);}}