Proyectos de Subversion LeadersLinked - Antes de SPA

Rev

Rev 16 | Ir a la última revisión | Autoría | Comparar con el anterior | Ultima modificación | Ver Log |

<?php
declare(strict_types=1);

namespace LeadersLinked\Controller;


use Laminas\Authentication\AuthenticationService;
use Laminas\Authentication\Result as AuthResult;
use Laminas\Db\Adapter\AdapterInterface;
use Laminas\Cache\Storage\Adapter\AbstractAdapter;
use Laminas\Mvc\Controller\AbstractActionController;
use Laminas\Log\LoggerInterface;
use Laminas\View\Model\JsonModel;

use LeadersLinked\Authentication\AuthAdapter;
use LeadersLinked\Mapper\UserMapper;
use LeadersLinked\Mapper\EmailTemplateMapper;
use LeadersLinked\Model\User;
use LeadersLinked\Model\UserType;

use LeadersLinked\Library\QueueEmail;
use LeadersLinked\Library\Functions;
use LeadersLinked\Model\EmailTemplate;
use LeadersLinked\Mapper\UserPasswordMapper;
use LeadersLinked\Mapper\DeviceMapper;
use LeadersLinked\Model\Device;
use LeadersLinked\Mapper\ApplicationMapper;
use LeadersLinked\Model\Application;
use LeadersLinked\Validator\PasswordStrengthCheck;

use LeadersLinked\Mapper\CompanyMapper;
use LeadersLinked\Model\Company;
use LeadersLinked\Mapper\CompanyMicrolearningTopicMapper;
use LeadersLinked\Mapper\CompanyMicrolearningCapsuleMapper;
use LeadersLinked\Mapper\CompanyMicrolearningSlideMapper;
use LeadersLinked\Model\CompanyMicrolearningSlide;
use LeadersLinked\Mapper\CompanyMicrolearningUserLogMapper;
use LeadersLinked\Mapper\CompanyMicrolearningUserProgressMapper;
use LeadersLinked\Mapper\CompanyMicrolearningQuizMapper;
use LeadersLinked\Mapper\CompanyMicrolearningQuestionMapper;
use LeadersLinked\Mapper\CompanyMicrolearningAnswerMapper;
use LeadersLinked\Model\CompanyMicrolearningUserProgress;
use LeadersLinked\Model\CompanyMicrolearningUserLog;
use LeadersLinked\Mapper\DeviceHistoryMapper;
use LeadersLinked\Model\DeviceHistory;
use LeadersLinked\Mapper\PushMapper;
use LeadersLinked\Model\Push;
use LeadersLinked\Mapper\CompanyMicrolearningCapsuleUserMapper;
use LeadersLinked\Mapper\CompanyServiceMapper;
use LeadersLinked\Model\Service;
use LeadersLinked\Model\CompanyService;
use LeadersLinked\Model\CompanyMicrolearningCapsuleUser;
use LeadersLinked\Model\CompanyMicrolearningUserQuiz;
use LeadersLinked\Mapper\CompanyMicrolearningUserQuizMapper;
use LeadersLinked\Mapper\CompanyUserMapper;
use LeadersLinked\Model\CompanyUser;
use LeadersLinked\Mapper\CompanyMicrolearningUserMapper;
use LeadersLinked\Model\CompanyMicrolearningUser;
use LeadersLinked\Mapper\PushTemplateMapper;
use LeadersLinked\Model\PushTemplate;


class ServiceController extends AbstractActionController
{

    
    /**
     *
     * @var AdapterInterface
     */
    private $adapter;
    
    
    /**
     *
     * @var AbstractAdapter
     */
    private $cache;
    
    /**
     *
     * @var  LoggerInterface
     */
    private $logger;

    /**
     * 
     * @var array
     */
    private $config;
    
    /**
     * 
     * @param AdapterInterface $adapter
     * @param AbstractAdapter $cache
     * @param LoggerInterface $logger
     * @param array $config
     */
    public function __construct($adapter, $cache , $logger, $config)
    {
        $this->adapter      = $adapter;
        $this->cache        = $cache;
        $this->logger       = $logger;
        $this->config       = $config;
    }
    
    public function signoutAction()
    {
        $currentUser = $this->plugin('currentUserPlugin');
        if($currentUser->hasIdentity()) {
            $device_uuid = $currentUser->getDeviceId();
            if($device_uuid) {
                $deviceMapper = DeviceMapper::getInstance($this->adapter);
                $device = $deviceMapper->fetchOne($device_uuid);
                if($device) {
                    $deviceMapper->signout($device);
                }
            }
            
            
            $this->logger->info('Desconexión del mobile', ['user_id' => $currentUser->getUserId(), 'ip' => Functions::getUserIP()]);
        }
        $authService = new \Laminas\Authentication\AuthenticationService();
        $authService->clearIdentity();
        
        return new JsonModel([
            'success' => true,
            'data' => 'LABEL_SIGNOUT_SUCCESSFULL'
        ]);
    }
    
    public function fcmAction()
    {
        $request = $this->getRequest();
        
        if($request->isPost()) {
            
            $rawdata = file_get_contents("php://input");
            error_log('$rawdata = ' . $rawdata );
            
            $device_uuid      = filter_var($this->params()->fromPost('device_uuid', ''), FILTER_SANITIZE_STRING);
            $token          = filter_var($this->params()->fromPost('token', ''), FILTER_SANITIZE_STRING);
            $sync_id        = filter_var($this->params()->fromPost('sync_id', ''), FILTER_SANITIZE_NUMBER_INT);

            /*
            echo '$device_uuid = ' . $device_uuid .PHP_EOL;
            echo '$token = ' . $token .PHP_EOL;
            echo '$sync_id  = ' . $sync_id  .PHP_EOL;
            */
            $ok = $device_uuid && strlen($device_uuid) == 36 && $sync_id;
            $ok = $ok && strlen($token) <= 512;

            
            if(!$ok) {
                return new JsonModel([
                    'success' => false,
                    'data' => 'ERROR_PARAMETERS_ARE_INVALID',
                ]);
            }
            
            $deviceMapper = DeviceMapper::getInstance($this->adapter);
            $device = $deviceMapper->fetchOne($device_uuid);
            if(!$device) {
                return new JsonModel([
                    'success' => false,
                    'data' => 'ERROR_DEVICE_NOT_FOUND',
                ]);
            }
            
            
            $applicationMapper = ApplicationMapper::getInstance($this->adapter);
            $application = $applicationMapper->fetchOne($device->application_id);
            if(!$application) {
                return new JsonModel([
                    'success' => false,
                    'data' => 'ERROR_APPLICATION_NOT_FOUND',
                ]);
            }
            
            if($application->status == Application::STATUS_INACTIVE) {
                return new JsonModel([
                    'success' => false,
                    'data' => 'ERROR_APPLICATION_IS_INACTIVE',
                ]);
            }
            
            $device->token = $token;
            $device->ip = Functions::getUserIP();
            $result = $deviceMapper->update($device);

            
            if($result) {
                return new JsonModel([
                    'success' => true,
                    'data' => [
                        'sync_id' => $sync_id
                    ]
                ]);
            } else {
                return new JsonModel([
                    'success' => false,
                    'data' => 'ERROR_THERE_WAS_AN_ERROR',
                ]);
            }
            
        }
        
        return new JsonModel([
            'success' => false,
            'data' => 'ERROR_METHOD_NOT_ALLOWED'
        ]);
    }
    
    public function checkSessionAction()
    {
        $request = $this->getRequest();
        
        if($request->isPost()) {
            $device_uuid  = trim(filter_var($this->params()->fromPost('device_id', ''), FILTER_SANITIZE_STRING));
            $secret     = trim(filter_var($this->params()->fromPost('secret', ''), FILTER_SANITIZE_STRING));
            $rand       = filter_var($this->params()->fromPost('rand', ''), FILTER_SANITIZE_NUMBER_INT);
            $created    = trim(filter_var($this->params()->fromPost('created', ''), FILTER_SANITIZE_STRING));
            
            if(!$device_uuid || !$secret || !$rand || !$created) {
                return new JsonModel([
                    'success' => false,
                    'data' => 'ERROR_PARAMETERS_ARE_INVALID'
                ]);
            }
            
            $dt = \DateTime::createFromFormat('Y-m-d\TH:i:s',  $created);
            if(!$dt) {
                return new JsonModel([
                    'success' => false,
                    'data' => 'ERROR_PARAMETERS_ARE_INCORRECTLY_FORMATTED'
                ]);
            }
            
            
            $deviceMapper = DeviceMapper::getInstance($this->adapter);
            $device = $deviceMapper->fetchOne($device_uuid);
            if(!$device) {
                return new JsonModel([
                    'success' => false,
                    'data' => 'ERROR_DEVICE_NOT_FOUND'
                ]);
            }
            
            
            $passworVerification = md5($device->password . ':' . $created . ':'  . $rand);
            if($secret != $passworVerification) {
                return new JsonModel([
                    'success' => false,
                    'data' => 'ERROR_WEBSERVICE_PASSWORD'
                ]);
            }
            
            
            $userMapper = UserMapper::getInstance($this->adapter);
            $user = $userMapper->fetchOne($device->user_id);
            
            if(User::BLOCKED_YES == $user->blocked) {
                return new JsonModel([
                    'success' => false,
                    'data' => 'ERROR_USER_IS_BLOCKED'
                ]);
            }
            
            if(User::STATUS_INACTIVE == $user->status) {
                return new JsonModel([
                    'success' => false,
                    'data' =>'ERROR_USER_IS_INACTIVE'
                ]);
            }
            

            return new JsonModel([
                'success' => true,
                'data' => [
                    'user_uuid' => $device->user_uuid
                ]
            ]);
            
        }
        
        return new JsonModel([
            'success' => false,
            'data' => 'ERROR_METHOD_NOT_ALLOWED'
        ]);
    }
    
    public function deviceAction()
    {
        
        $rawdata = file_get_contents("php://input");
        error_log('$rawdata = ' . $rawdata );
        
        $request = $this->getRequest();
        
        if($request->isPost()) {
            //print_r($_POST);
            
            
            $application_id = filter_var($this->params()->fromPost('application_id', 0), FILTER_SANITIZE_NUMBER_INT);
            $device_uuid    = filter_var($this->params()->fromPost('device_uuid', ''), FILTER_SANITIZE_STRING);
            $manufacturer   = filter_var($this->params()->fromPost('manufacturer', ''), FILTER_SANITIZE_STRING);
            $platform       = filter_var($this->params()->fromPost('platform', ''), FILTER_SANITIZE_STRING);
            $brand          = filter_var($this->params()->fromPost('brand', ''), FILTER_SANITIZE_STRING);
            $version        = filter_var($this->params()->fromPost('version', ''), FILTER_SANITIZE_STRING);
            $model          = filter_var($this->params()->fromPost('model', ''), FILTER_SANITIZE_STRING);
            $sync_id        = filter_var($this->params()->fromPost('sync_id', ''), FILTER_SANITIZE_NUMBER_INT);

            $ok = $application_id && $device_uuid && strlen($device_uuid) == 36 && $sync_id;
            $ok = $ok && strlen($manufacturer) <= 250;
            $ok = $ok && strlen($brand) <= 250;
            $ok = $ok && strlen($version) <= 250;
            $ok = $ok && strlen($model) <= 250;
            
            if(!$ok) {
                return new JsonModel([
                    'success' => false,
                    'data' => 'ERROR_PARAMETERS_ARE_INVALID',
                ]);
            }
            
            
            $applicationMapper = ApplicationMapper::getInstance($this->adapter);
            $application = $applicationMapper->fetchOne($application_id);
            if(!$application) {
                return new JsonModel([
                    'success' => false,
                    'data' => 'ERROR_APPLICATION_NOT_FOUND',
                ]);
            }
            
            if($application->status == Application::STATUS_INACTIVE) {
                return new JsonModel([
                    'success' => false,
                    'data' => 'ERROR_APPLICATION_IS_INACTIVE',
                ]);
            }
            
            $deviceMapper = DeviceMapper::getInstance($this->adapter);
            $device = $deviceMapper->fetchOne($device_uuid);
            
            
            
            
            if($device) {
                $device->platform       = $platform;
                $device->manufacturer   = $manufacturer;
                $device->brand          = $brand;
                $device->version        = $version;
                $device->model          = $model;
                $device->ip             = Functions::getUserIP();
                $result                 = $deviceMapper->update($device); 
                
            } else {
                $device                 = new Device();
                $device->id             = $device_uuid;
                $device->application_id = $application->id;
                $device->manufacturer   = $manufacturer;
                $device->brand          = $brand;
                $device->version        = $version;
                $device->model          = $model;
                $device->platform       = $platform;
                $device->ip             = Functions::getUserIP();
                $device->aes            = Functions::generatePassword(16);
                $device->password       = Functions::generatePassword(32);
                $result                 = $deviceMapper->insert($device);
            }
            

            
            if($result) {
                return new JsonModel([
                    'success' => true,
                    'data' => [
                        'sync_id'   => $sync_id,
                        'aes'       => $device->aes,
                        'password'  => $device->password,
                    ]
                ]);
            } else {
                return new JsonModel([
                    'success' => false,
                    'data' => 'ERROR_THERE_WAS_AN_ERROR',
                ]);
            }
            
        }
        
        return new JsonModel([
            'success' => false,
            'data' => 'ERROR_METHOD_NOT_ALLOWED'
        ]);
        
    }
    
    public function microlearningCheckChangesAction()
    {
        $request = $this->getRequest();
        
        if($request->isPost()) {
            $currentUserPlugin = $this->plugin('currentUserPlugin');
            $user = $currentUserPlugin->getUser();
            
            $rawdata = file_get_contents("php://input");
            error_log('$rawdata = ' . $rawdata );
            
            
            $serviceDatetimeFormat = $this->config['leaderslinked.services.datetime'];
            
            
            $device_uuid        = filter_var($this->params()->fromPost('device_uuid', ''), FILTER_SANITIZE_STRING);
            $max_date_changes   = filter_var($this->params()->fromPost('max_date_changes', ''), FILTER_SANITIZE_STRING);
            $max_ids            = filter_var($this->params()->fromPost('max_ids', ''), FILTER_SANITIZE_NUMBER_INT);
            
            
            $ids = [];
            for($i = 1; $i <= $max_ids; $i++)
            {
                $id = filter_var($this->params()->fromPost('id_' . $i, ''), FILTER_SANITIZE_STRING);
                if(empty($id)) {
                    continue;
                }
                
                $pattern = '/[A-Za-z0-9\-]+\|[A-Za-z0-9\-]+/';
                $matches = [];  preg_match($pattern, $id, $matches, PREG_OFFSET_CAPTURE);
                if(count($matches) > 1) {
                    array_push($ids, $matches[0]);
                }

            }
            
            
            
            if($max_date_changes) {
                $dt = \DateTime::createFromFormat($serviceDatetimeFormat, $max_date_changes);
                if($dt) {
                  $max_date_changes = $dt->format('Y-m-d H:i:s');  
                } else {
                    $max_date_changes = '';
                }
            } else {
                $max_date_changes = '';
            } 
            
            
            error_log('device_uuid = ' . $device_uuid . ' max_date_changes = ' . $max_date_changes);
            
            $ok = $device_uuid && strlen($device_uuid);
            
            if(!$ok) {
                return new JsonModel([
                    'success' => false,
                    'data' => 'ERROR_PARAMETERS_ARE_INVALID',
                ]);
            }
            
            $deviceMapper = DeviceMapper::getInstance($this->adapter);
            $device = $deviceMapper->fetchOne($device_uuid);
            
            
            if(!$device) {
                return new JsonModel([
                    'success' => false,
                    'data' => 'ERROR_DEVICE_NOT_FOUND'
                ]);
            } else {
                $device->ip = Functions::getUserIP();
                $deviceMapper->update($device);
            }
            
            //Cargamos la fecha máxima del cambio
            $companyMicrolearningUserMapper = CompanyMicrolearningUserMapper::getInstance($this->adapter);
            $max_date_changes_db = $companyMicrolearningUserMapper->fetchMaxDateChanges($user->id);
            
            //Si la fecha es vacia agregamos la fecha máxima de la asignación de la capsula
            if(!$max_date_changes_db) {
                $companyUsers = [];
                $companyMicrolearningCapsuleUserMapper = CompanyMicrolearningCapsuleUserMapper::getInstance($this->adapter);
                $capsules = $companyMicrolearningCapsuleUserMapper->fetchAllActiveByUserId($user->id);
                foreach($capsules as $capsule)
                {
                    
                    
                    
                    if(empty($companyUsers[$capsule->company_id])) {
                        $companyUsers[$capsule->company_id] = $capsule->updated_on;
                    } else {
                        
                        if($capsule->updated_on > $companyUsers[$capsule->company_id]) {
                            $companyUsers[$capsule->company_id] = $capsule->updated_on;
                        }
                        
                    }
                    
                }
                
                $max_date_changes_db = '';
                foreach($companyUsers as $company_id => $update_on)
                {
                    
                    $max_date_changes_db = $max_date_changes_db < $update_on ? $update_on : $max_date_changes_db;
                    
                    $companyMicrolearningUser = new CompanyMicrolearningUser();
                    $companyMicrolearningUser->company_id = $company_id;
                    $companyMicrolearningUser->user_id = $user->id;
                    $companyMicrolearningUser->added_on = $update_on;
                    $companyMicrolearningUser->updated_on = $update_on;
                    
                    $companyMicrolearningUserMapper->insert($companyMicrolearningUser);
                }
            }
            
            
            error_log("max_date_changes = $max_date_changes, max_date_changes_db = $max_date_changes_db");
            
            //Si la que tiene el dispositivo es diferente a la fecha máxima almacenada
            $newCapsules = 0;
            if($max_date_changes != $max_date_changes_db) {
                if(is_array($ids)) {
                    $companyMicrolearningTopicMapper = CompanyMicrolearningTopicMapper::getInstance($this->adapter);
                    $companyMicrolearningTopics = $companyMicrolearningTopicMapper->fetchAllActive();
                        
                    $topics = [];
                    foreach($companyMicrolearningTopics as $topic)
                    {
                        $topics[$topic->id] = $topic->uuid;
                    }
                        
                    $companyMicrolearningCapsuleMapper = CompanyMicrolearningCapsuleMapper::getInstance($this->adapter);
                    $companyMicrolearningCapsules = $companyMicrolearningCapsuleMapper->fetchAllActiveAndPublic();
                        
                    $capsules = [];
                    foreach($companyMicrolearningCapsules as $capsule)
                    {                            
                        $capsules[$capsule->id] = $capsule->uuid;
                    }
                        
                    $companyMicrolearningCapsuleUserMapper = CompanyMicrolearningCapsuleUserMapper::getInstance($this->adapter);
                    $user_capsules = $companyMicrolearningCapsuleUserMapper->fetchAllActiveByUserId($user->id);
                        
                    foreach($user_capsules as $user_capsule) 
                    {
                        $topic_uuid     = isset($topics[$user_capsule->topic_id]) ? $topics[$user_capsule->topic_id] : '';
                        $capsule_uuid   = isset($capsules[$user_capsule->capsule_id]) ?  $capsules[$user_capsule->capsule_id] : '';
                            
                        if(!$topic_uuid || !$capsule_uuid) {
                            continue;
                        }
                            
                        $key = $topic_uuid . '|' . $capsule_uuid;
                        if(!in_array($key, $ids)) {
                            $newCapsules++;
                        }
                    }
                }
            }

     
            //echo 'Vamos a lanzar un PUSH' . PHP_EOL;
            if($newCapsules) {

                if($device->token)
                {
                
                    $pushMapper = PushMapper::getInstance($this->adapter);
                    $pushTemplateMapper = PushTemplateMapper::getInstance($this->adapter);
                    $pushTemplate = $pushTemplateMapper->fetchOne(PushTemplate::ID_MICRO_LEARNING_NEW_CONTENT);
                    
                    //echo 'PushTemplate' . PHP_EOL;
                    //print_r($pushTemplate);
                    
                    $applicationMapper = ApplicationMapper::getInstance($this->adapter);
                    $application = $applicationMapper->fetchOne(Application::TWOGETSKILLS);
                    
                    
                    //echo 'Application';
                    //print_r($application);
                    if($pushTemplate && $application) {
                         $push = new Push();
                        $push->status = Push::STATUS_PENDING;
                        $push->data = json_encode([
                            'server' => [
                                'key' =>   $application->key,
                            ],
                            'push' => [
                                'registration_ids'   => [
                                    $device->token,
                                ],
                                'notification' => [
                                    'body' =>  $pushTemplate->body,
                                    'title' => $pushTemplate->title,
                                    'vibrate' => 1,
                                    'sound' =>  1,
                                    
                                    
                                ],
                                'data' => [
                                    'new_capsules' => $newCapsules,
                                ]
                            ]
                        ]);
                        $pushMapper->insert($push);
                    }
                }
                
                $dataSync = $this->getSyncData($user,false, false);
            } else {
                $dataSync = [];
            } 
                
           
            
            //error_log('$max_date_changes_db = ' . $max_date_changes_db);
            
            $dt = \DateTime::createFromFormat('Y-m-d H:i:s', $max_date_changes_db);
            if($dt) {
                $max_date_changes_db = $dt->format($serviceDatetimeFormat);
            } else {
                $max_date_changes_db = '';
            }
            
            $data = [
                'success'   => true,
                'data'      =>[
                    'user' => [
                        'uuid' => $user->uuid,
                        'first_name' => $user->first_name,
                        'last_name' => $user->last_name,
                        'email' => $user->email,
                        'image' => $this->url()->fromRoute('services/storage',['type' => 'user', 'code' => $user->uuid, 'filename' => $user->image], ['force_canonical' => true]),
                    ],
                    'max_date_changes' => $max_date_changes_db,
                    'topics'    => isset( $dataSync['topics'] ) ? $dataSync['topics'] : [],
                    'quizzes'   => isset( $dataSync['quizzes'] ) ? $dataSync['quizzes'] : [],
                    
                ]
            ];
            
            //error_log(print_r($data, true));
            
            return new JsonModel($data);
        }
        
        return new JsonModel([
            'success' => false,
            'data' => 'ERROR_METHOD_NOT_ALLOWED'
        ]);
        
    }
    
    
    
    public function microlearningRefreshAction()
    {
        $request = $this->getRequest();
        
        if($request->isGet()) {
            $currentUserPlugin = $this->plugin('currentUserPlugin');
            $user = $currentUserPlugin->getUser();
            
            $dataSync = $this->getSyncData($user,false, false);
            
            //Cargamos la fecha máxima del cambio
            $companyMicrolearningUserMapper = CompanyMicrolearningUserMapper::getInstance($this->adapter);
            $max_date_changes_db = $companyMicrolearningUserMapper->fetchMaxDateChanges($user->id);
            
            //Si la fecha es vacia agregamos la fecha máxima de la asignación de la capsula
            if(!$max_date_changes_db) {
                $companyUsers = [];
                $companyMicrolearningCapsuleUserMapper = CompanyMicrolearningCapsuleUserMapper::getInstance($this->adapter);
                $capsules = $companyMicrolearningCapsuleUserMapper->fetchAllActiveByUserId($user->id);
                foreach($capsules as $capsule)
                {
                    
                    
                    
                    if(empty($companyUsers[$capsule->company_id])) {
                        $companyUsers[$capsule->company_id] = $capsule->updated_on;
                    } else {
                        
                        if($capsule->updated_on > $companyUsers[$capsule->company_id]) {
                            $companyUsers[$capsule->company_id] = $capsule->updated_on;
                        }
                        
                    }
                    
                }
                
                $max_date_changes_db = '';
                foreach($companyUsers as $company_id => $update_on)
                {
                    
                    $max_date_changes_db = $max_date_changes_db < $update_on ? $update_on : $max_date_changes_db;
                    
                    $companyMicrolearningUser = new CompanyMicrolearningUser();
                    $companyMicrolearningUser->company_id = $company_id;
                    $companyMicrolearningUser->user_id = $user->id;
                    $companyMicrolearningUser->added_on = $update_on;
                    $companyMicrolearningUser->updated_on = $update_on;
                    
                    $companyMicrolearningUserMapper->insert($companyMicrolearningUser);
                }
            }
            
            $dt = \DateTime::createFromFormat('Y-m-d H:i:s', $max_date_changes_db);
            if($dt) {
                $serviceDatetimeFormat = $this->config['leaderslinked.services.datetime'];
                $max_date_changes_db = $dt->format($serviceDatetimeFormat);
            } else {
                $max_date_changes_db = '';
            }
            
            return new JsonModel([
                'success'   => true,
                'data'      =>[
                    'user' => [
                        'uuid' => $user->uuid,
                        'first_name' => $user->first_name,
                        'last_name' => $user->last_name,
                        'email' => $user->email,
                        'image' => $this->url()->fromRoute('services/storage',['type' => 'user', 'code' => $user->uuid, 'filename' => $user->image], ['force_canonical' => true]),
                    ],
                    'max_date_changes' => $max_date_changes_db,
                    'topics'    => $dataSync['topics'],
                    'quizzes'   => $dataSync['quizzes'],

                ]
            ]);
        }
        
        return new JsonModel([
            'success' => false,
            'data' => 'ERROR_METHOD_NOT_ALLOWED'
        ]);
    }
    
    
    public function signinAction()
    {
        $request = $this->getRequest();
        
        if($request->isPost()) {
            
            
            $rawdata = file_get_contents("php://input");
            error_log('$rawdata = ' . $rawdata );

            
            $application_id = filter_var($this->params()->fromPost('application_id', 0), FILTER_SANITIZE_NUMBER_INT);
            $device_uuid    = filter_var($this->params()->fromPost('device_uuid', ''), FILTER_SANITIZE_STRING);
            $email          = filter_var($this->params()->fromPost('email', ''), FILTER_SANITIZE_EMAIL);
            $password       = filter_var($this->params()->fromPost('password', ''), FILTER_SANITIZE_STRING);
            //$encrypter      = filter_var($this->params()->fromPost('encrypter', ''), FILTER_SANITIZE_STRING);


            
            $ok = $application_id && $device_uuid && strlen($device_uuid) == 36;
            $ok = $ok && $email && $password;
            //$ok = $ok && in_array($encrypter, ['CryptoJsAes','RNCryptor','AesCipher']);

            if(!$ok) {
                return new JsonModel([
                    'success' => false,
                    'data' => 'ERROR_PARAMETERS_ARE_INVALID',
                ]);
            }
            
            
            $applicationMapper = ApplicationMapper::getInstance($this->adapter);
            $application = $applicationMapper->fetchOne($application_id);
            if(!$application) {
                return new JsonModel([
                    'success' => false,
                    'data' => 'ERROR_APPLICATION_NOT_FOUND',
                ]);
            }
            
            if($application->status == Application::STATUS_INACTIVE) {
                return new JsonModel([
                    'success' => false,
                    'data' => 'ERROR_APPLICATION_IS_INACTIVE',
                ]);
            }
            
            
            $deviceMapper = DeviceMapper::getInstance($this->adapter);
            $device = $deviceMapper->fetchOne($device_uuid);
            if(!$device) {
                $device                 = new Device();
                $device->id             = $device_uuid;
                $device->application_id = $application->id;
                $device->ip             = Functions::getUserIP();
                $device->aes            = Functions::generatePassword(16);
                $device->password       = Functions::generatePassword(32);
                $result                 = $deviceMapper->insert($device);
                
                if(!$result) {
                    return new JsonModel([
                        'success' => false,
                        'data' => 'ERROR_DEVICE_NOT_FOUND',
                    ]);
                }
            }
            
            /*
            if($encrypter == 'CryptoJsAes') {
                
                
                $email = html_entity_decode($email);
                $password = html_entity_decode($password);
                
            
                ob_start();
                
                $email      = CryptoJsAes::decrypt($email, $device->aes);
                $password   = CryptoJsAes::decrypt($password, $device->aes);
                
                ob_end_clean();
                
                if(!$email || !$password) {
                    return new JsonModel([
                        'success' => false,
                        'data' => 'ERROR_WEBSERVICE_PASSWORD_ENCRYPTION_FAILED',
                    ]);
                } 
            } else if($encrypter == 'RNCryptor') {
                $cryptor = new \RNCryptor\RNCryptor\Decryptor;
                $email = $cryptor->decrypt($email, $device->aes);
                $password = $cryptor->decrypt($password, $device->aes);
                
                if(!$email || !$password) {
                    return new JsonModel([
                        'success' => false,
                        'data' => 'ERROR_WEBSERVICE_PASSWORD_ENCRYPTION_FAILED',
                    ]);
                } 
                
               
            } else if($encrypter == 'AesCipher') {
                
                $emailDecrypted = AesCipher::decrypt($device->aes,$email);
                $passwordDecrypted = AesCipher::decrypt($device->aes,$password);
                if($emailDecrypted->hasError() || $passwordDecrypted->hasError()) {
                    return new JsonModel([
                        'success' => false,
                        'data' => 'ERROR_WEBSERVICE_PASSWORD_ENCRYPTION_FAILED',
                    ]);
                }
                
                $email = $emailDecrypted->getData();
                $password = $passwordDecrypted->getData();
            } else {
                return new JsonModel([
                    'success' => false,
                    'data' => 'ERROR_WEBSERVICE_PASSWORD_ENCRYPTION_FAILED',
                ]);
            }*/
            
      
            $authAdapter = new AuthAdapter($this->adapter);
            $authAdapter->setData($email, $password);
            
            $authService = new AuthenticationService();
            $result = $authService->authenticate($authAdapter);
            
            if($result->getCode() == AuthResult::SUCCESS) {
                
                $userMapper = UserMapper::getInstance($this->adapter);
                $user = $userMapper->fetchOneByEmail($email);
              
                
                $device->user_id    = $user->id;
                $device->ip         = Functions::getUserIP();
                if($deviceMapper->update($device)) {
                    
                    $ip = Functions::getUserIP();
                    
                    $deviceHistoryMapper = DeviceHistoryMapper::getInstance($this->adapter);
                    $deviceHistory = $deviceHistoryMapper->fetchOneByDeviceIdAndUserIdAndIp($device->id, $user->id, $ip);
                    if($deviceHistory) {
                        $deviceHistoryMapper->update($deviceHistory);
                    } else {
                        $deviceHistory = new DeviceHistory();
                        $deviceHistory->device_id = $device->id;
                        $deviceHistory->user_id = $user->id;
                        $deviceHistory->ip = $ip;
                        $deviceHistoryMapper->insert($deviceHistory);
                    }
                    
                    $pushMapper = PushMapper::getInstance($this->adapter);
                    
                    $userDevices =  $deviceMapper->fetchAllByUserId($user->id);
                    foreach($userDevices as $userDevice)
                    {
       
                    
                        if($userDevice->id != $device->id && $userDevice->token) {
                            
                            $push = new Push();
                            $push->status = Push::STATUS_PENDING;
                            $push->data = json_encode([
                                'server' => [
                                    'key' =>   $application->key
                                 ],
                                 'push' => [
                                    'registration_ids'   => [ 
                                        $userDevice->token,
                                     ],
                                     /*'notification' => [
                                         'body' =>  'Se registro un inicio de sessión desde otro dispositivo',
                                         'title' => 'Inicio de sessión',
                                         'vibrate' => 1,
                                         'sound' =>  1
                                     ],*/
                                    'data' => [
                                        'command' => 'signout'
                                    ]
                                 ]
                             ]);
                            
                            $pushMapper->insert($push);
                            
                        }
                    }
                    
                    
                    $companyUsers = [];
                    $companyMicrolearningCapsuleUserMapper = CompanyMicrolearningCapsuleUserMapper::getInstance($this->adapter);
                    $capsules = $companyMicrolearningCapsuleUserMapper->fetchAllActiveByUserId($user->id);
                    foreach($capsules as $capsule)
                    {
                        
                        
                        
                        if(empty($companyUsers[$capsule->company_id])) {
                            $companyUsers[$capsule->company_id] = $capsule->updated_on;
                        } else {
                            
                            if($capsule->updated_on > $companyUsers[$capsule->company_id]) {
                                $companyUsers[$capsule->company_id] = $capsule->updated_on;
                            }
                            
                        }
                        
                    }
                    
                    $companyMicrolearningUserMapper = CompanyMicrolearningUserMapper::getInstance($this->adapter);
                    
                    $maxDateChanges = $companyMicrolearningUserMapper->fetchMaxDateChanges($user->id);
                    if(!$maxDateChanges) {
                        
                       
                        $maxDateChanges = ''; 
                        foreach($companyUsers as $company_id => $update_on)
                        {
                            
                            $maxDateChanges = $maxDateChanges < $update_on ? $update_on : $maxDateChanges;
                            
                            $companyMicrolearningUser = new CompanyMicrolearningUser();
                            $companyMicrolearningUser->company_id = $company_id;
                            $companyMicrolearningUser->user_id = $user->id;
                            $companyMicrolearningUser->added_on = $update_on;
                            $companyMicrolearningUser->updated_on = $update_on;
                            
                            $companyMicrolearningUserMapper->insert($companyMicrolearningUser);
                        }
                        
                        
                    }
                    
                    
                   
                   $dt = \DateTime::createFromFormat('Y-m-d H:i:s', $maxDateChanges);
                   if($dt) {
                       $serviceDatetimeFormat = $this->config['leaderslinked.services.datetime'];
                       $maxDateChanges = $dt->format($serviceDatetimeFormat);
                   } else {
                       $maxDateChanges = '';
                   }
                    
                    
                    $data = [
                        'success'   => true,
                        'data'      =>[
                            'user' => [
                                'uuid' => $user->uuid,
                                'first_name' => $user->first_name,
                                'last_name' => $user->last_name,
                                'email' => $user->email,
                                'image' => $this->url()->fromRoute('services/storage',['type' => 'user', 'code' => $user->uuid, 'filename' => $user->image], ['force_canonical' => true]),
                                
                             ],
                            'max_date_changes' => $maxDateChanges,
                            'device' => [
                                'aes' => $device->aes,
                                'password' => $device->password
                            ]
                            
                        ]
                    ];
                    
                    if($application->id == Application::TWOGETSKILLS) {
                        $dataSync = $this->getSyncData($user);
                        
                        $data['data']['topics'] = $dataSync['topics'];
                        $data['data']['quizzes'] = $dataSync['quizzes'];
                        $data['data']['userlog'] = $dataSync['userlog'];
                        $data['data']['progress'] = $dataSync['progress'];
                    }
                    
                    
  
                    return new JsonModel($data);
                    

                    
                } else {
                    return new JsonModel([
                        'success' => false,
                        'data' => 'ERROR_THERE_WAS_AN_ERROR',
                    ]);
                }
                
                
            } else {
                $message = $result->getMessages()[0];
                if(!in_array($message, ['ERROR_USER_NOT_FOUND', 'ERROR_USER_PROVIDER_NOT_FOUND', 'ERROR_USER_EMAIL_HASNT_BEEN_VARIFIED', 'ERROR_USER_IS_BLOCKED',
                    'ERROR_USER_IS_INACTIVE', 'ERROR_ENTERED_PASS_INCORRECT_USER_IS_BLOCKED', 'ERROR_ENTERED_PASS_INCORRECT_2',
                    'ERROR_ENTERED_PASS_INCORRECT_1'])) {
                }
                
                switch($message)
                {
                    case 'ERROR_USER_NOT_FOUND' :
                        $this->logger->err('Error de ingreso a LeadersLinked de ' . $email . ' - Email no existe', ['ip' => Functions::getUserIP()]);
                        break;
                        
                    case 'ERROR_USER_EMAIL_HASNT_BEEN_VARIFIED' :
                        $this->logger->err('Error de ingreso a LeadersLinked de ' . $email . ' - Email no verificado', ['ip' => Functions::getUserIP()]);
                        break;
                        
                    case 'ERROR_USER_IS_BLOCKED' :
                        $this->logger->err('Error de ingreso a LeadersLinked de ' . $email . ' - Usuario bloqueado', ['ip' => Functions::getUserIP()]);
                        break;
                        
                    case 'ERROR_USER_IS_INACTIVE' :
                        $this->logger->err('Error de ingreso a LeadersLinked de ' . $email . ' - Usuario inactivo', ['ip' => Functions::getUserIP()]);
                        break;
                        
                        
                    case 'ERROR_ENTERED_PASS_INCORRECT_USER_IS_BLOCKED':
                        $this->logger->err('Error de ingreso a LeadersLinked de ' . $email . ' - 3er Intento Usuario bloqueado', ['ip' => Functions::getUserIP()]);
                        break;
                        
                        
                    case 'ERROR_ENTERED_PASS_INCORRECT_2' :
                        $this->logger->err('Error de ingreso a LeadersLinked de ' . $email . ' - 1er Intento', ['ip' => Functions::getUserIP()]);
                        break;
                        
                        
                    case 'ERROR_ENTERED_PASS_INCORRECT_1' :
                        $this->logger->err('Error de ingreso a LeadersLinked de ' . $email . ' - 2do Intento', ['ip' => Functions::getUserIP()]);
                        break;
                        
                        
                    default :
                        $message = 'ERROR_UNKNOWN';
                        $this->logger->err('Error de ingreso a LeadersLinked de ' . $email . ' - Error desconocido', ['ip' => Functions::getUserIP()]);
                        break;
                        
                        
                }

                
                return new JsonModel([
                    'success'   => false,
                    'data'   => $message
                ]);
            }
            
        }
        
        return new JsonModel([
            'success' => false,
            'data' => 'ERROR_METHOD_NOT_ALLOWED'
        ]);
        
    }
    
    
    
    
    public function storageAction()
    {
        
        // Get the file name from GET variable.
        $code       = $this->params()->fromRoute('code', '');
        $fileName   = $this->params()->fromRoute('filename', '');
        $type       = $this->params()->fromRoute('type', 'user');
        
        
        $no_image = $this->config['leaderslinked.images_default.no_image'];
        $path = '';
        switch($type)
        {
            case 'user' :
                $no_image = $this->config['leaderslinked.images_default.user_image'];
                $path = $this->config['leaderslinked.fullpath.user'];
                break;
                
                
            case 'user-profile' :
                $no_image = $this->config['leaderslinked.images_default.user_profile'];
                $path = $this->config['leaderslinked.fullpath.user'];
                break;
                
            case 'user-cover' :
                $no_image = $this->config['leaderslinked.images_default.user_cover'];
                $path = $this->config['leaderslinked.fullpath.user'];
                break;
                
            case 'company' :
                $no_image = $this->config['leaderslinked.images_default.company_profile'];
                $path = $this->config['leaderslinked.fullpath.company'];
                break;
                
            case 'company-cover' :
                $no_image = $this->config['leaderslinked.images_default.company_cover'];
                $path = $this->config['leaderslinked.fullpath.company'];
                break;
                
            case 'group' :
                $no_image = $this->config['leaderslinked.images_default.group_profile'];
                $path = $this->config['leaderslinked.fullpath.group'];
                break;
                
            case 'group-cover' :
                $no_image = $this->config['leaderslinked.images_default.group_cover'];
                $path = $this->config['leaderslinked.fullpath.group'];
                break;
                
            case 'job' :
                $path = $this->config['leaderslinked.fullpath.job'];
                break;
                
            case 'chat' :
                $path = $this->config['leaderslinked.fullpath.chat'];
                break;
                
            case 'feed' :
                $path = $this->config['leaderslinked.fullpath.feed'];
                break;
                
            case 'post' :
                $path = $this->config['leaderslinked.fullpath.post'];
                break;
                
            case 'microlearning-topic' :
                $path = $this->config['leaderslinked.fullpath.microlearning_topic'];
                break;
                
            case 'microlearning-capsule' :
                $path = $this->config['leaderslinked.fullpath.microlearning_capsule'];
                break;
                
            case 'microlearning-slide' :
                $path = $this->config['leaderslinked.fullpath.microlearning_slide'];
                break;
                
            default :
                $path = $this->config['leaderslinked.fullpath.image'];
                break;
                
        }
        if($code && $fileName) {
            $request_fullpath = $path . $code . DIRECTORY_SEPARATOR . $fileName;
        } else {
            $request_fullpath = $no_image;
        }
        
        if(empty($fileName)) {
            $extensions     = explode('.',$request_fullpath);
            $extension      = strtolower(trim($extensions[count($extensions)-1]));
            if ($extension=='jpg' || $extension=='jpeg' || $extension=='gif' || $extension == 'png') {
                $request_fullpath =  $no_image;
            }
        }

       
        if(file_exists($request_fullpath)) {
            
            // Try to open file
            if (!is_readable($request_fullpath)) {
                return $this->getResponse()->setStatusCode(500);
            }
            
            // Get file size in bytes.
            $fileSize = filesize($request_fullpath);
            
            // Get MIME type of the file.
            $mimeType = mime_content_type($request_fullpath);
            if($mimeType===false) {
                $mimeType = 'application/octet-stream';
            }
            
            $request_fullpath = trim($request_fullpath);
            $length = strlen($request_fullpath);
            if(substr($request_fullpath, $length - 1) == '/') {
                $request_fullpath = substr($request_fullpath, 0, $length - 1);
            }
            
            
            $filename = basename($request_fullpath);

            header('Content-type: ' . $mimeType);
            readfile($request_fullpath);
            
            
            exit;
            //header("X-Sendfile: $request_fullpath"); 
            //header("Content-type: application/octet-stream"); 
            //header('Content-Disposition: attachment; filename="' . basename($filename) . '"');
            
            
            /*
            

            if ($fd = fopen ($request_fullpath, "r")) {
                
                $fsize = filesize($request_fullpath);
                
                header("Content-type: $mimeType");
                header("Accept-Ranges: bytes");
                
                //header("Content-Disposition: attachment; filename=\"$filename\"");
                
                header("Content-length: $fsize");
                header("Cache-control: private");
                
                while(!feof($fd)) {
                    $buffer = fread($fd, 2048);
                    echo $buffer;
                }
            }
            
            fclose ($fd);
            exit;*/
  
            
            /*
             $fileContent = file_get_contents($request_fullpath);
            $response = $this->getResponse();
            $headers = $response->getHeaders();
            $headers->addHeaderLine('Accept-Ranges: bytes');
            $headers->addHeaderLine('Content-type: ' . $mimeType);
            $headers->addHeaderLine('Content-length: ' . $fileSize);
     
            /*
            Date: Tue, 13 Jul 2021 03:11:42 GMT
            Server: Apache/2.4.41 (Ubuntu)
            Last-Modified: Mon, 28 Jun 2021 16:43:04 GMT
            ETag: "54e4-5c5d62eed581e"
            Accept-Ranges: bytes
            Content-Length: 21732
            Cache-Control: max-age=1
            Expires: Tue, 13 Jul 2021 03:11:43 GMT
            Keep-Alive: timeout=5, max=100
            Connection: Keep-Alive
            Content-Type: audio/mpeg
            */
            
            /*
            if($fileContent!==false) {
                error_log($_SERVER['REQUEST_URI']);
                error_log($request_fullpath);
                return $response->setContent($fileContent);
             
                header('Content-Type: '.$mimeType );
                readfile_chunked($filename);
                exit;
                
            } else {
                error_log('500');
                $this->getResponse()->setStatusCode(500);
                return;
            }*/
        } else {
            error_log('404');
            return $this->getResponse()->setStatusCode(404);
        }
        
        return $this->getResponse();
    }  
   

    public function syncAction()
    {
        $request = $this->getRequest();
        
        if($request->isPost()) {
            
            $rawdata = file_get_contents("php://input");
            error_log('$rawdata = ' . $rawdata );
            
            
            $serviceDatetimeFormat = $this->config['leaderslinked.services.datetime'];
            
            $device_uuid    = filter_var($this->params()->fromPost('device_uuid', ''), FILTER_SANITIZE_STRING);
            $sync_id        = filter_var($this->params()->fromPost('sync_id', ''), FILTER_SANITIZE_NUMBER_INT);
            $data           = $this->params()->fromPost('data', '');
            
           
            
            error_log('device_uuid = ' . $device_uuid);
            error_log('sync_id = ' . $sync_id);
            error_log(print_r($data, true));
           
                        
            $ok = $device_uuid && strlen($device_uuid) == 36 && $data && $sync_id;
            
            if(!$ok) {
                return new JsonModel([
                    'success' => false,
                    'data' => 'ERROR_PARAMETERS_ARE_INVALID',
                ]);
            }
            
            $deviceMapper = DeviceMapper::getInstance($this->adapter);
            $device = $deviceMapper->fetchOne($device_uuid);
            
            
            if(!$device) {
                return new JsonModel([
                    'success' => false,
                    'data' => 'ERROR_DEVICE_NOT_FOUND'
                ]);
            } else {
                $device->ip = Functions::getUserIP();
                $deviceMapper->update($device);
            }
            
           
            
            $data = json_decode($data, true);
            $sync_type      = isset($data['sync_type']) ? filter_var($data['sync_type'], FILTER_SANITIZE_STRING) : '';
            $user_uuid      = isset($data['user_uuid']) ? filter_var($data['user_uuid'], FILTER_SANITIZE_STRING) : '';
            $company_uuid   = isset($data['company_uuid']) ? filter_var($data['company_uuid'], FILTER_SANITIZE_STRING) :  '';
            
    //
            
            if($user_uuid && $device->application_id = Application::TWOGETSKILLS  && $company_uuid && in_array($sync_type, ['microlearning-progress', 'microlearning-userlog', 'microlearning-quiz'])) {
                $userMapper = UserMapper::getInstance($this->adapter);
                $user = $userMapper->fetchOneByUuid($user_uuid);
                
                if(!$user) {
                    return new JsonModel([
                        'success' => false,
                        'data' => [
                            'sync_id' => $sync_id,
                            'message' => 'ERROR_USER_NOT_FOUND',
                            'fatal' => true
                        ]
                    ]);
                }
                
                
                if($user->status != User::STATUS_ACTIVE) {
                    return new JsonModel([
                        'success' => false,
                        'data' => [
                            'sync_id' => $sync_id,
                            'message' => 'ERROR_USER_IS_NOT_ACTIVE',
                            'fatal' => true
                        ]
                    ]);
                }
                
                $companyMapper = CompanyMapper::getInstance($this->adapter);
                $company = $companyMapper->fetchOneByUuid($company_uuid);
                if(!$company) {
                    return new JsonModel([
                        'success' => false,
                        'data' => [
                            'sync_id' => $sync_id,
                            'message' => 'ERROR_COMPANY_NOT_FOUND',
                            'fatal' => true
                        ]
                    ]);
                }
                
                if($company->status != Company::STATUS_ACTIVE) {
                    return new JsonModel([
                        'success' => false,
                        'data' => [
                            'sync_id' => $sync_id,
                            'message' => 'ERROR_COMPANY_IS_NOT_FOUND',
                            'fatal' => true
                        ]
                    ]);
                }
                
                
               
                
                
                $companyServiceMapper = CompanyServiceMapper::getInstance($this->adapter);
                $companyService = $companyServiceMapper->fetchOneByCompanyIdAndServiceId($company->id, Service::MICRO_LEARNING);
                if(!$companyService) {
                    return new JsonModel([
                        'success' => false,
                        'data' => [
                            'sync_id' => $sync_id,
                            'message' => 'ERROR_COMPANY_SERVICE_NOT_FOUND',
                            'fatal' => true
                        ]
                    ]);
                }
                
                $serviceActive = true;
                $now = date('Y-m-d H:i:s');
                if($companyService->status == CompanyService::ACTIVE) {
                   
                    if($now < $companyService->paid_from || $now > $companyService->paid_to) {
                        $serviceActive = false;
                    }
                    
                } else {
                    $serviceActive = false;
                }
                
                if( !$serviceActive) {
                    return new JsonModel([
                        'success' => false,
                        'data' => [
                            'sync_id' => $sync_id,
                            'message' => 'ERROR_COMPANY_SERVICE_IS_NOT_ACTIVE',
                            'fatal' => true
                        ]
                    ]);
                }
                
                $topicMapper = CompanyMicrolearningTopicMapper::getInstance($this->adapter);
                $topic_uuid = isset($data['topic_uuid']) ? filter_var($data['topic_uuid'], FILTER_SANITIZE_STRING) :  '';
                if($topic_uuid) {
                    $topic = $topicMapper->fetchOneByUuid($topic_uuid);
                    
                    if(!$topic) {
                        return new JsonModel([
                            'success' => false,
                            'data' => [
                                'sync_id' => $sync_id,
                                'message' => 'ERROR_TOPIC_NOT_FOUND',
                            ]
                        ]);
                    }
                    
                    if($topic->company_id != $company->id) {
                        return new JsonModel([
                            'success' => false,
                            'data' => [
                                'sync_id' => $sync_id,
                                'message' => 'ERROR_INVALID_PARAMETERS_TOPIC_COMPANY',
                            ]
                        ]);
                    }
                    
                } else {
                    $topic = null;
                }
                
                $capsule_uuid     = isset($data['capsule_uuid']) ? filter_var($data['capsule_uuid'], FILTER_SANITIZE_STRING) :  '';
                $capsuleMapper = CompanyMicrolearningCapsuleMapper::getInstance($this->adapter);
                if($capsule_uuid) {
                   
                    $capsule = $capsuleMapper->fetchOneByUuid($capsule_uuid);
                    if(!$capsule) {
                        return new JsonModel([
                            'success' => false,
                            'data' => [
                                'sync_id' => $sync_id,
                                'message' => 'ERROR_CAPSULE_NOT_FOUND',
                            ]
                        ]);
                    }
                    
                    if(!$topic || $capsule->topic_id != $topic->id) {
                        return new JsonModel([
                            'success' => false,
                            'data' => [
                                'sync_id' => $sync_id,
                                'message' => 'ERROR_INVALID_PARAMETERS_CAPSULE_TOPIC',
                            ]
                        ]);
                    }
                } else {
                    $capsule = null;
                }
                
                if($capsule) {
       
                    $capsuleActive = true;
                    $capsuleMapper = CompanyMicrolearningCapsuleUserMapper::getInstance($this->adapter);
                    $capsuleUser = $capsuleMapper->fetchOneByUserIdAndCapsuleId($user->id, $capsule->id);
                    
                    
                    $now = date('Y-m-d H:i:s');
                    if($capsuleUser && in_array($capsuleUser->access, [CompanyMicrolearningCapsuleUser::ACCESS_UNLIMITED,CompanyMicrolearningCapsuleUser::ACCESS_PAY_PERIOD ])) {
                        
                        
                        if($capsuleUser->access == CompanyMicrolearningCapsuleUser::ACCESS_PAY_PERIOD) {
                            
                            if($now < $capsuleUser->paid_from || $now > $capsuleUser->paid_to) {
                                $capsuleActive = false;;
                            }
                        }
                        
                    } else {
                        $capsuleActive = false;
                    }

                    if(!$capsuleActive) {
                        return new JsonModel([
                            'success' => false,
                            'data' => [
                                'sync_id' => $sync_id,
                                'message' => 'ERROR_YOU_DO_NOT_HAVE_ACCESS_TO_THIS_CAPSULE',
                            ]
                        ]);
                    }
                }
                
                $slideMapper = CompanyMicrolearningSlideMapper::getInstance($this->adapter);
                $slide_uuid      = isset($data['slide_uuid']) ? filter_var($data['slide_uuid'], FILTER_SANITIZE_STRING) :  '';
                if($slide_uuid) {
                    $slide = $slideMapper->fetchOneByUuid($slide_uuid);
                    if(!$slide) {
                        return new JsonModel([
                            'success' => false,
                            'data' => [
                                'sync_id' => $sync_id,
                                'message' => 'ERROR_SLIDE_NOT_FOUND',
                            ]
                        ]);
                    }
                    
                    if(!$capsule || $slide->capsule_id != $capsule->id) {
                        return new JsonModel([
                            'success' => false,
                            'data' => [
                                'sync_id' => $sync_id,
                                'message' => 'ERROR_INVALID_PARAMETERS_SLIDE_CAPSULE',
                            ]
                        ]);
                    }
                } else {
                    $slide = null;
                }
                
                if($sync_type == 'microlearning-quiz') {
                    $ok = true;
                    
                    $quiz_uuid = isset($data['quiz_uuid']) ? $data['quiz_uuid'] : '';
                    $quizMapper = CompanyMicrolearningQuizMapper::getInstance($this->adapter);
                    
                    $quiz = $quizMapper->fetchOneByUuid($quiz_uuid);
                    if(!$quiz) {
                        return new JsonModel([
                            'success' => false,
                            'data' => [
                                'sync_id' => $sync_id,
                                'message' => 'ERROR_SLIDE_NOT_FOUND',
                            ]
                        ]);
                    }
                    
                    if(!$capsule || $slide->capsule_id != $capsule->id) {
                        return new JsonModel([
                            'success' => false,
                            'data' => [
                                'sync_id' => $sync_id,
                                'message' => 'ERROR_INVALID_PARAMETERS_QUIZ_SLIDE',
                            ]
                        ]);
                    }
                    
                    $added_on   = isset($data['added_on'])      ? filter_var($data['added_on'], FILTER_SANITIZE_STRING)  :  '';
                  
                    $dt = \DateTime::createFromFormat($serviceDatetimeFormat, $added_on);
                    if(!$dt) {
                        $ok = false;
                    } else {
                        $added_on = $dt->format('Y-m-d H:i:s');
                    }
                    

                    if(isset($data['points'])) { 
                        $points = intval($data['points'], 10);
                    } else {
                        $ok = false;
                    }
                    

                    if(isset($data['pass'])) {
                        $status = $data['pass'] == 'yes' ? CompanyMicrolearningUserQuiz::STATUS_PASS : CompanyMicrolearningUserQuiz::STATUS_FAIL;
                    } else {
                        $ok = false;
                    }
                    

                    if(!$ok) {
                        return new JsonModel([
                            'success' => false,
                            'data' => [
                                'sync_id' => $sync_id,
                                'message' => 'ERROR_INVALID_PARAMETERS',
                            ]
                        ]);
                    }
         
                    
                    $array_response = [];
                    $response = isset($data['response']) ? intval($data['response'], 10) : 0;
                    for($i = 0; $i < $response; $i++)
                    {
                        $question_uuid = isset($data["response_{$i}_question_uuid"]) ? $data["response_{$i}_question_uuid"] : '';
                        $answer_uuid = isset($data["response_{$i}_answer_uuid"]) ? $data["response_{$i}_answer_uuid"] : '';
                        $value = isset($data["response_{$i}_value"]) ?  intval($data["response_{$i}_value"], 10) : 0;
                        $points = isset($data["response_{$i}_points"]) ?  intval($data["response_{$i}_points"], 10) : 0;
                        
                        if($question_uuid && $answer_uuid)
                        {
                            array_push($array_response, [
                                'question_uuid' => $question_uuid,
                                'answer_uuid' => $answer_uuid,
                                'value' => $value,
                                'points' => $points
                                
                            ]);
                        }
                        
                        
                    }

                    
                    $userQuiz = new CompanyMicrolearningUserQuiz();
                    $userQuiz->company_id = $company->id;
                    $userQuiz->topic_id = $topic->id;
                    $userQuiz->capsule_id = $capsule->id;
                    $userQuiz->slide_id = $slide->id;
                    $userQuiz->quiz_id = $quiz->id;
                    $userQuiz->user_id = $user->id;
                    $userQuiz->added_on = $added_on;
                    $userQuiz->points = $points;
                    $userQuiz->status = $status;
                    $userQuiz->response = json_encode($array_response);
                    
                    $userQuizMapper = CompanyMicrolearningUserQuizMapper::getInstance($this->adapter);
                    
                    if($userQuizMapper->insert($userQuiz)) {
                        return new JsonModel([
                            'success' => true,
                            'data' => [
                                'sync_id' => $sync_id
                            ]
                        ]);
                    } else {
                        return new JsonModel([
                            'success' => false,
                            'data' => [
                                'sync_id' => $sync_id,
                                'message' => $userQuizMapper->getError()
                            ]
                        ]);
                    }
                    
                }
                
                
                if($sync_type == 'microlearning-progress') {
                    $ok = true;
                    
                    $type = isset($data['type']) ? $data['type'] : '';
                    switch($type)
                    {
                        case CompanyMicrolearningUserProgress::TYPE_TOPIC : 
                            if(!$topic) {
                                $ok = false;
                            }
                            break;
                            
                        case CompanyMicrolearningUserProgress::TYPE_CAPSULE :
                            if(!$topic || !$capsule) {
                                $ok = false;
                            }
                            break;
                            
                        case CompanyMicrolearningUserProgress::TYPE_SLIDE :
                            if(!$topic || !$capsule || !$slide) {
                                $ok = false;
                            }
                            break;
                            
                        default : 
                            $ok = false;
                            break;
                            
                    }
                    
                    
                    $added_on   = isset($data['added_on'])      ? filter_var($data['added_on'], FILTER_SANITIZE_STRING)  :  '';
                    $updated_on = isset($data['updated_on'])    ? filter_var($data['updated_on'], FILTER_SANITIZE_STRING) :  '';
                    
                    $dt = \DateTime::createFromFormat($serviceDatetimeFormat, $added_on);
                    if(!$dt) {
                        $ok = false;  
                    } else {
                        $added_on = $dt->format('Y-m-d H:i:s');
                    }
                    
                    $dt = \DateTime::createFromFormat($serviceDatetimeFormat, $updated_on );
                    if(!$dt) {
                        $ok = false;  
                    } else {
                        $updated_on = $dt->format('Y-m-d H:i:s');
                    }
                    
                    if(!$ok) {
                        return new JsonModel([
                            'success' => false,
                            'data' => [
                                'sync_id' => $sync_id,
                                'message' => 'ERROR_INVALID_PARAMETERS',
                            ]
                        ]);
                    }
                    
                           //$progress                   = isset($data['progress'])                  ? floatval($data['progress']) :  0;
                    //$total_slides               = isset($data['total_slides'])              ? intval($data['total_slides'], 10) :  0;
                    //$view_slides                = isset($data['view_slides'])               ? intval($data['view_slides'], 10) :  0;
                    $returning                  = isset($data['returning'])                 ? intval($data['returning'], 10) :  0;
                    $returning_after_completed  = isset($data['returning_after_completed']) ? intval($data['returning_after_completed'], 10) :  0;
                    $completed                  = isset($data['completed'])                 ? intval($data['completed'], 10) :  0;

                    $progressMapper = CompanyMicrolearningUserProgressMapper::getInstance($this->adapter);
                    $recordProgress = null;
                    switch($type) {
                        case CompanyMicrolearningUserProgress::TYPE_TOPIC  :
                            $recordProgress = $progressMapper->fetchOneByUserIdAndTopicId($user->id, $topic->id);
                            
                            break;
                                            
                        case CompanyMicrolearningUserProgress::TYPE_CAPSULE  :
                            $recordProgress = $progressMapper->fetchOneByUseridAndCapsuleId($user->id, $capsule->id);
                            break;
                                            
                        case CompanyMicrolearningUserProgress::TYPE_SLIDE  :
                            $recordProgress = $progressMapper->fetchOneByUserIdAndSlideId($user->id, $slide->id);
                            break;
                            
                        default : 
                            $recordProgress= null;
                    }

                    
                    if(!$recordProgress) {
                        $recordProgress = new CompanyMicrolearningUserProgress();
                       
                        $recordProgress->user_id    = $user->id;
                        $recordProgress->type       = $type;
                        $recordProgress->company_id = $topic->company_id;
                        $recordProgress->topic_id   = $topic->id;
                        $recordProgress->capsule_id = $capsule ? $capsule->id : null;
                        $recordProgress->slide_id   = $slide ? $slide->id : null;
                        $recordProgress->added_on   = $added_on;
                    }
                    $recordProgress->returning                  = $returning;
                    $recordProgress->returning_after_completed  = $returning_after_completed;
                    $recordProgress->completed                  = $completed;
                                    
                    if($type == CompanyMicrolearningUserProgress::TYPE_TOPIC ) {
                        
                        $capsule_ids = [];
                        $companyMicrolearningCapsuleUser = CompanyMicrolearningCapsuleUserMapper::getInstance($this->adapter);
                        $records =  $companyMicrolearningCapsuleUser->fetchAllActiveByUserId($user->id);
                        foreach($records as $record) 
                        {
                            if($now >= $record->paid_from || $now <= $capsuleUser->paid_to) {
                                if(!in_array($record->capsule_id, $capsule_ids)) {
                                    array_push($capsule_ids, $record->capsule_id);
                                }
                            }
                        }
                        
                        $view_slides    = 0;
                        $total_slides   = 0;
                        foreach($capsule_ids as $capsule_id)
                        {
                            $view_slides    += $progressMapper->fetchCountAllSlideViewedByUserIdAndCapsuleId($user->id, $capsule_id);
                            $total_slides   += $slideMapper->fetchTotalCountByCompanyIdAndTopicIdAndCapsuleId($topic->company_id, $topic->id, $capsule_id);
                            
                        }

                        
                        $recordProgress->progress       = $total_slides > 0 ? (($view_slides * 100) / $total_slides) : 0;
                        $recordProgress->total_slides   = $total_slides;
                        $recordProgress->view_slides    = $view_slides;
                    } 
                    else if($type == CompanyMicrolearningUserProgress::TYPE_CAPSULE ) {
                        $view_slides    = $progressMapper->fetchCountAllSlideViewedByUserIdAndCapsuleId($user->id, $capsule->id);
                        $total_slides   = $slideMapper->fetchTotalCountByCompanyIdAndTopicIdAndCapsuleId($topic->company_id, $capsule->topic_id, $capsule->id);
       
                        $recordProgress->progress       = $total_slides > 0 ? (($view_slides * 100) / $total_slides) : 0;
                        $recordProgress->total_slides   = $total_slides;
                        $recordProgress->view_slides    = $view_slides;
                    } 
                    else {
                        $recordProgress->progress       = 0;
                        $recordProgress->total_slides   = 0;
                        $recordProgress->view_slides    = 0;
                    }
                                    
                    $recordProgress->updated_on = $updated_on;
                    
      
                    
                    if($recordProgress->id) {
                        $result = $progressMapper->update($recordProgress);
                    } else {
                        $result = $progressMapper->insert($recordProgress);
                    }
                                    
                    if($result) {
                        return new JsonModel([
                            'success' => true,
                            'data' => [
                                'sync_id' => $sync_id
                            ]
                        ]);
                    } else {
                        return new JsonModel([
                            'success' => false,
                            'data' => [
                                'sync_id' => $sync_id,
                                'message' => $progressMapper->getError()
                            ]
                        ]);
                    }
                }
                
             
                
                if($sync_type == 'microlearning-userlog') {
                    $activity   = isset($data['activity'])      ? filter_var($data['activity'], FILTER_SANITIZE_STRING)  :  '';
                    $added_on   = isset($data['added_on'])      ? filter_var($data['added_on'], FILTER_SANITIZE_STRING)  :  '';

                    
                    if(empty($activity)) {
                        $ok = false;
                    }
                    
                    $dt = \DateTime::createFromFormat($serviceDatetimeFormat, $added_on);
                    if(!$dt) {
                        $ok = false;
                    } else {
                        $added_on = $dt->format('Y-m-d H:i:s');
                    }
                    
                    if(!$ok) {
                        return new JsonModel([
                            'success' => false,
                            'data' => [
                                'sync_id' => $sync_id,
                                'message' => 'ERROR_INVALID_PARAMETERS',
                            ]
                        ]);
                    }
                                
                    $userLog = new CompanyMicrolearningUserLog();
                    $userLog->activity      = $activity;
                    $userLog->user_id       = $user->id;
                    $userLog->company_id    = $topic->company_id;
                    $userLog->topic_id      = $topic->id;
                    $userLog->capsule_id    = $capsule ? $capsule->id : null;
                    $userLog->slide_id      = $slide ? $slide->id : null;
                    $userLog->added_on      = $added_on;

       
                    
                    $userLogMapper = CompanyMicrolearningUserLogMapper::getInstance($this->adapter);
                    if($userLogMapper->insert($userLog)) {
                        return new JsonModel([
                            'success' => true,
                            'data' => [
                                'sync_id' => $sync_id
                            ]
                        ]);
                    } else {
                        return new JsonModel([
                            'success' => false,
                            'data' => [
                                'sync_id' => $sync_id,
                                'message' => $userLogMapper->getError()
                            ]
                        ]);
                    }
                }
                
            }
            
            
            
            
            if($user_uuid && $sync_type == 'userlog' && $device->application_id = Application::TWOGETSKILLS) {
                
                $userMapper = UserMapper::getInstance($this->adapter);
                $user = $userMapper->fetchOneByUuid($user_uuid);
                
                if(!$user) {
                    return new JsonModel([
                        'success' => false,
                        'data' => [
                            'sync_id' => $sync_id,
                            'message' => 'ERROR_USER_NOT_FOUND',
                            'fatal' => true
                        ]
                    ]);
                }
                
                
                if($user->status != User::STATUS_ACTIVE) {
                    return new JsonModel([
                        'success' => false,
                        'data' => [
                            'sync_id' => $sync_id,
                            'message' => 'ERROR_USER_IS_NOT_ACTIVE',
                            'fatal' => true
                        ]
                    ]);
                }
                
                $activity   = isset($data['activity'])      ? filter_var($data['activity'], FILTER_SANITIZE_STRING)  :  '';
                $added_on   = isset($data['added_on'])      ? filter_var($data['added_on'], FILTER_SANITIZE_STRING)  :  '';
                
                if(empty($activity)) {
                    $ok = false;
                }
                
                $dt = \DateTime::createFromFormat($serviceDatetimeFormat, $added_on);
                if(!$dt) {
                    $ok = false;
                } else {
                    $added_on = $dt->format('Y-m-d H:i:s');
                }
                
                if(!$ok) {
                    return new JsonModel([
                        'success' => false,
                        'data' => [
                            'sync_id' => $sync_id,
                            'message' => 'ERROR_INVALID_PARAMETERS',
                        ]
                    ]);
                }
                
                $userLog = new CompanyMicrolearningUserLog();
                $userLog->company_id = null;
                $userLog->user_id = $user->id;
                $userLog->activity = $activity;
                $userLog->added_on = $added_on;
                

                $userLogMapper = CompanyMicrolearningUserLogMapper::getInstance($this->adapter);
                if($userLogMapper->insert($userLog)) {
                    return new JsonModel([
                        'success' => true,
                        'data' => [
                            'sync_id' => $sync_id
                        ]
                    ]);
                } else {
                    return new JsonModel([
                        'success' => false,
                        'data' => [
                            'sync_id' => $sync_id,
                            'message' => $userLogMapper->getError()
                        ]
                    ]);
                }
            }
            
            return new JsonModel([
                'success' => true,
                'data' => [
                    'sync_id' => $sync_id
                ]
            ]);

        }
        
        return new JsonModel([
            'success' => false,
            'data' => 'ERROR_METHOD_NOT_ALLOWED'
        ]);
    }
    
    
    public function syncBatchAction()
    {
        $request = $this->getRequest();
        
        if($request->isPost()) {
            
            $rawdata = file_get_contents("php://input");
            error_log('$rawdata = ' . $rawdata );
            
            
            $serviceDatetimeFormat = $this->config['leaderslinked.services.datetime'];
            
            $device_uuid = filter_var($this->params()->fromPost('device_uuid', ''), FILTER_SANITIZE_STRING);
            $max_records = filter_var($this->params()->fromPost('max_records', 0), FILTER_SANITIZE_NUMBER_INT);
            
            
            
            error_log('device_uuid = ' . $device_uuid . ' max_records = ' . $max_records);
            
            $ok = $device_uuid && strlen($device_uuid) == 36 && $max_records;
            
            if(!$ok) {
                return new JsonModel([
                    'success' => false,
                    'data' => 'ERROR_PARAMETERS_ARE_INVALID',
                ]);
            }
            
            $deviceMapper = DeviceMapper::getInstance($this->adapter);
            $device = $deviceMapper->fetchOne($device_uuid);
            
            
            if(!$device) {
                return new JsonModel([
                    'success' => false,
                    'data' => 'ERROR_DEVICE_NOT_FOUND'
                ]);
            } else {
                $device->ip = Functions::getUserIP();
                $deviceMapper->update($device);
            }

            $result_sync_ids = [];
            
            
          
            
            for($i = 1; $i <= $max_records; $i++)
            {
                $sync_id        = filter_var($this->params()->fromPost('record_sync_id' . $i, ''), FILTER_SANITIZE_NUMBER_INT);
                $record_data    = $this->params()->fromPost('record_data' . $i, '');

                if(empty($record_data) || empty($sync_id )) {
                    continue;
                }

                $record         = json_decode($record_data, true);
                $sync_type      = isset($record['sync_type']) ? filter_var($record['sync_type'],  FILTER_SANITIZE_STRING) : '';
                $user_uuid      = isset($record['user_uuid']) ? filter_var($record['user_uuid'],  FILTER_SANITIZE_STRING) : '';
                $company_uuid   = isset($record['company_uuid']) ? filter_var($record['company_uuid'], FILTER_SANITIZE_STRING) : '';

                if(!$sync_id) {
                    continue;
                }
                
                /***** INICIO MICROLEARNING *****/
                
                if($user_uuid && $device->application_id = Application::TWOGETSKILLS  && $company_uuid && in_array($sync_type, ['microlearning-progress', 'microlearning-userlog', 'microlearning-quiz'])) {
                    $userMapper = UserMapper::getInstance($this->adapter);
                    $user = $userMapper->fetchOneByUuid($user_uuid);
                    
                    if(!$user) {
                        array_push($result_sync_ids, [
                            'success' => false,
                            'sync_id' => $sync_id,
                            'message' => 'ERROR_USER_NOT_FOUND',
                            'fatal' => true
                        ]);
                        continue;
                    }
                    
                    
                    if($user->status != User::STATUS_ACTIVE) {
                        array_push($result_sync_ids, [
                            'success' => false,
                            'sync_id' => $sync_id,
                            'message' => 'ERROR_USER_IS_NOT_ACTIVE',
                            'fatal' => true
                        ]);
                        continue;
                    }
                    
                    $companyMapper = CompanyMapper::getInstance($this->adapter);
                    $company = $companyMapper->fetchOneByUuid($company_uuid);
                    if(!$company) {
                        array_push($result_sync_ids, [
                            'success' => false,
                            'sync_id' => $sync_id,
                            'message' => 'ERROR_COMPANY_NOT_FOUND',
                            'fatal' => true
                        ]);
                        continue;
                    }
                    
                    if($company->status != Company::STATUS_ACTIVE) {
                        array_push($result_sync_ids, [
                            'success' => false,
                            'sync_id' => $sync_id,
                            'message' => 'ERROR_COMPANY_IS_NOT_FOUND',
                            'fatal' => true
                        ]);
                        continue;
                    }
                    
                    
                    
                    
                    
                    $companyServiceMapper = CompanyServiceMapper::getInstance($this->adapter);
                    $companyService = $companyServiceMapper->fetchOneByCompanyIdAndServiceId($company->id, Service::MICRO_LEARNING);
                    if(!$companyService) {
                        array_push($result_sync_ids, [
                            'success' => false,
                            'sync_id' => $sync_id,
                            'message' => 'ERROR_COMPANY_SERVICE_NOT_FOUND',
                            'fatal' => true
                        ]);
                        continue;
                    }
                    
                    $serviceActive = true;
                    $now = date('Y-m-d H:i:s');
                    if($companyService->status == CompanyService::ACTIVE) {
                        
                        if($now < $companyService->paid_from || $now > $companyService->paid_to) {
                            $serviceActive = false;
                        }
                        
                    } else {
                        $serviceActive = false;
                    }
                    
                    if( !$serviceActive) {
                        array_push($result_sync_ids, [
                            'success' => false,
                            'sync_id' => $sync_id,
                            'message' => 'ERROR_COMPANY_SERVICE_IS_NOT_ACTIVE',
                            'fatal' => true
                        ]);
                        continue;
                    }
                    
                    $topicMapper = CompanyMicrolearningTopicMapper::getInstance($this->adapter);
                    $topic_uuid = isset($record['topic_uuid']) ? filter_var($record['topic_uuid'], FILTER_SANITIZE_STRING) :  '';
                    if($topic_uuid) {
                        $topic = $topicMapper->fetchOneByUuid($topic_uuid);
                        
                        if(!$topic) {
                            array_push($result_sync_ids, [
                                'success' => false,
                                'sync_id' => $sync_id,
                                'message' => 'ERROR_TOPIC_NOT_FOUND',
                            ]);
                            continue;
                        }
                        
                        if($topic->company_id != $company->id) {
                            array_push($result_sync_ids, [
                                'success' => false,
                                'sync_id' => $sync_id,
                                'message' => 'ERROR_INVALID_PARAMETERS_TOPIC_COMPANY',
                            ]);
                            continue;
                        }
                        
                    } else {
                        $topic = null;
                    }
                    
                    $capsule_uuid     = isset($record['capsule_uuid']) ? filter_var($record['capsule_uuid'], FILTER_SANITIZE_STRING) :  '';
                    $capsuleMapper = CompanyMicrolearningCapsuleMapper::getInstance($this->adapter);
                    if($capsule_uuid) {
                        
                        $capsule = $capsuleMapper->fetchOneByUuid($capsule_uuid);
                        if(!$capsule) {
                            array_push($result_sync_ids, [
                                'success' => false,
                                'sync_id' => $sync_id,
                                'message' => 'ERROR_CAPSULE_NOT_FOUND',
                            ]);
                            continue;
                        }
                        
                        if(!$topic || $capsule->topic_id != $topic->id) {
                            array_push($result_sync_ids, [
                                'success' => false,
                                'sync_id' => $sync_id,
                                'message' => 'ERROR_INVALID_PARAMETERS_CAPSULE_TOPIC',
                            ]);
                            continue;
                        }
                    } else {
                        $capsule = null;
                    }
                    
                    if($capsule) {
                        
                        $capsuleActive = true;
                        $capsuleMapper = CompanyMicrolearningCapsuleUserMapper::getInstance($this->adapter);
                        $capsuleUser = $capsuleMapper->fetchOneByUserIdAndCapsuleId($user->id, $capsule->id);
                        
                        
                        $now = date('Y-m-d H:i:s');
                        if($capsuleUser && in_array($capsuleUser->access, [CompanyMicrolearningCapsuleUser::ACCESS_UNLIMITED,CompanyMicrolearningCapsuleUser::ACCESS_PAY_PERIOD ])) {
                            
                            
                            if($capsuleUser->access == CompanyMicrolearningCapsuleUser::ACCESS_PAY_PERIOD) {
                                
                                if($now < $capsuleUser->paid_from || $now > $capsuleUser->paid_to) {
                                    $capsuleActive = false;;
                                }
                            }
                            
                        } else {
                            $capsuleActive = false;
                        }
                        
                        if(!$capsuleActive) {
                            array_push($result_sync_ids, [
                                'success' => false,
                                'sync_id' => $sync_id,
                                'message' => 'ERROR_YOU_DO_NOT_HAVE_ACCESS_TO_THIS_CAPSULE',
                            ]);
                            continue;
                        }
                    }
                    
                    $slideMapper = CompanyMicrolearningSlideMapper::getInstance($this->adapter);
                    $slide_uuid      = isset($record['slide_uuid']) ? filter_var($record['slide_uuid'], FILTER_SANITIZE_STRING) :  '';
                    if($slide_uuid) {
                        $slide = $slideMapper->fetchOneByUuid($slide_uuid);
                        if(!$slide) {
                            array_push($result_sync_ids, [
                                'success' => false,
                                'sync_id' => $sync_id,
                                'message' => 'ERROR_SLIDE_NOT_FOUND',
                            ]);
                            continue;
                        }
                        
                        if(!$capsule || $slide->capsule_id != $capsule->id) {
                            array_push($result_sync_ids, [
                                'success' => false,
                                'sync_id' => $sync_id,
                                'message' => 'ERROR_INVALID_PARAMETERS_SLIDE_CAPSULE',
                            ]);
                            continue;
                        }
                    } else {
                        $slide = null;
                    }
                    
                    if($sync_type == 'microlearning-quiz') {
                        $ok = true;
                        
                        $quiz_uuid = isset($record['quiz_uuid']) ? $record['quiz_uuid'] : '';
                        $quizMapper = CompanyMicrolearningQuizMapper::getInstance($this->adapter);
                        
                        $quiz = $quizMapper->fetchOneByUuid($quiz_uuid);
                        if(!$quiz) {
                            array_push($result_sync_ids, [
                                'success' => false,
                                'sync_id' => $sync_id,
                                'message' => 'ERROR_SLIDE_NOT_FOUND',
                            ]);
                            continue;
                        }
                        
                        if(!$capsule || $slide->capsule_id != $capsule->id) {
                            array_push($result_sync_ids, [
                                'success' => false,
                                'sync_id' => $sync_id,
                                'message' => 'ERROR_INVALID_PARAMETERS_QUIZ_SLIDE',
                            ]);
                            continue;
                        }
                        
                        $added_on   = isset($record['added_on'])      ? filter_var($record['added_on'], FILTER_SANITIZE_STRING)  :  '';
                        
                        $dt = \DateTime::createFromFormat($serviceDatetimeFormat, $added_on);
                        if(!$dt) {
                            $ok = false;
                        } else {
                            $added_on = $dt->format('Y-m-d H:i:s');
                        }

                        if(isset($record['points'])) {
                            $points = intval($record['points'], 10);
                        } else {
                            $ok = false;
                        }

                        if(isset($record['pass'])) {
                            $status = $record['pass'] == 'yes' ? CompanyMicrolearningUserQuiz::STATUS_PASS : CompanyMicrolearningUserQuiz::STATUS_FAIL;
                        } else {
                            $ok = false;
                        }

                        if(!$ok) {
                            array_push($result_sync_ids, [
                                'success' => false,
                                'sync_id' => $sync_id,
                                'message' => 'ERROR_INVALID_PARAMETERS',
                            ]);
                            continue;
                        }
 
                        $array_response = [];
                        $response = isset($record['response']) ? intval($record['response'], 10) : 0;
                        for($i = 0; $i < $response; $i++)
                        {
                            $question_uuid = isset($record["response_{$i}_question_uuid"]) ? $record["response_{$i}_question_uuid"] : '';
                            $answer_uuid = isset($record["response_{$i}_answer_uuid"]) ? $record["response_{$i}_answer_uuid"] : '';
                            $value = isset($record["response_{$i}_value"]) ?  intval($record["response_{$i}_value"], 10) : 0;
                            $points = isset($record["response_{$i}_points"]) ?  intval($record["response_{$i}_points"], 10) : 0;
                            
                            if($question_uuid && $answer_uuid)
                            {
                                array_push($array_response, [
                                    'question_uuid' => $question_uuid,
                                    'answer_uuid' => $answer_uuid,
                                    'value' => $value,
                                    'points' => $points
                                ]);
                            } 
                        }
                        
                        $userQuiz = new CompanyMicrolearningUserQuiz();
                        $userQuiz->company_id = $company->id;
                        $userQuiz->topic_id = $topic->id;
                        $userQuiz->capsule_id = $capsule->id;
                        $userQuiz->slide_id = $slide->id;
                        $userQuiz->quiz_id = $quiz->id;
                        $userQuiz->user_id = $user->id;
                        $userQuiz->added_on = $added_on;
                        $userQuiz->points = $points;
                        $userQuiz->status = $status;
                        $userQuiz->response = json_encode($array_response);
                        
                        $userQuizMapper = CompanyMicrolearningUserQuizMapper::getInstance($this->adapter);
                        
                        if($userQuizMapper->insert($userQuiz)) {
                            array_push($result_sync_ids, [
                                'success' => true,
                                'sync_id' => $sync_id
                            ]);
                        } else {
                            array_push($result_sync_ids, [
                                'success' => false,
                                'sync_id' => $sync_id,
                                'message' => $userQuizMapper->getError()
                            ]);
                        }
                        continue;
                    }
                    
                    if($sync_type == 'microlearning-progress') {
                        $ok = true;
                        
                        $type = isset($record['type']) ? $record['type'] : '';
                        switch($type)
                        {
                            case CompanyMicrolearningUserProgress::TYPE_TOPIC :
                                if(!$topic) {
                                    $ok = false;
                                }
                                break;
                                
                            case CompanyMicrolearningUserProgress::TYPE_CAPSULE :
                                if(!$topic || !$capsule) {
                                    $ok = false;
                                }
                                break;
                                
                            case CompanyMicrolearningUserProgress::TYPE_SLIDE :
                                if(!$topic || !$capsule || !$slide) {
                                    $ok = false;
                                }
                                break;
                                
                            default :
                                $ok = false;
                                break;
                        }
                        
                        $added_on   = isset($record['added_on'])      ? filter_var($record['added_on'], FILTER_SANITIZE_STRING)  :  '';
                        $updated_on = isset($record['updated_on'])    ? filter_var($record['updated_on'], FILTER_SANITIZE_STRING) :  '';
                        
                        $dt = \DateTime::createFromFormat($serviceDatetimeFormat, $added_on);
                        if(!$dt) {
                            $ok = false;
                        } else {
                            $added_on = $dt->format('Y-m-d H:i:s');
                        }
                        
                        $dt = \DateTime::createFromFormat($serviceDatetimeFormat, $updated_on );
                        if(!$dt) {
                            $ok = false;
                        } else {
                            $updated_on = $dt->format('Y-m-d H:i:s');
                        }
                        
                        if(!$ok) {
                            array_push($result_sync_ids, [
                                'success' => false,
                                'sync_id' => $sync_id,
                                'message' => 'ERROR_INVALID_PARAMETERS',
                            ]);
                            continue;
                        }
                        
                        //$progress                   = isset($record['progress'])                  ? floatval($record['progress']) :  0;
                        //$total_slides               = isset($record['total_slides'])              ? intval($record['total_slides'], 10) :  0;
                        //$view_slides                = isset($record['view_slides'])               ? intval($record['view_slides'], 10) :  0;
                        $returning                  = isset($record['returning'])                 ? intval($record['returning'], 10) :  0;
                        $returning_after_completed  = isset($record['returning_after_completed']) ? intval($record['returning_after_completed'], 10) :  0;
                        $completed                  = isset($record['completed'])                 ? intval($record['completed'], 10) :  0;
                        
                        $progressMapper = CompanyMicrolearningUserProgressMapper::getInstance($this->adapter);
                        $recordProgress = null;
                        switch($type) {
                            case CompanyMicrolearningUserProgress::TYPE_TOPIC  :
                                $recordProgress = $progressMapper->fetchOneByUserIdAndTopicId($user->id, $topic->id);
                                
                                break;
                                
                            case CompanyMicrolearningUserProgress::TYPE_CAPSULE  :
                                $recordProgress = $progressMapper->fetchOneByUseridAndCapsuleId($user->id, $capsule->id);
                                break;
                                
                            case CompanyMicrolearningUserProgress::TYPE_SLIDE  :
                                $recordProgress = $progressMapper->fetchOneByUserIdAndSlideId($user->id, $slide->id);
                                break;
                                
                            default :
                                $recordProgress= null;
                        }
                        
                        
                        if(!$recordProgress) {
                            $recordProgress = new CompanyMicrolearningUserProgress();
                            
                            $recordProgress->user_id    = $user->id;
                            $recordProgress->type       = $type;
                            $recordProgress->company_id = $topic->company_id;
                            $recordProgress->topic_id   = $topic->id;
                            $recordProgress->capsule_id = $capsule ? $capsule->id : null;
                            $recordProgress->slide_id   = $slide ? $slide->id : null;
                            $recordProgress->added_on   = $added_on;
                        }
                        $recordProgress->returning                  = $returning;
                        $recordProgress->returning_after_completed  = $returning_after_completed;
                        $recordProgress->completed                  = $completed;
                        
                        if($type == CompanyMicrolearningUserProgress::TYPE_TOPIC ) {
                            
                            $capsule_ids = [];
                            $companyMicrolearningCapsuleUser = CompanyMicrolearningCapsuleUserMapper::getInstance($this->adapter);
                            $records =  $companyMicrolearningCapsuleUser->fetchAllActiveByUserId($user->id);
                            foreach($records as $record)
                            {
                                if($now >= $record->paid_from || $now <= $capsuleUser->paid_to) {
                                    if(!in_array($record->capsule_id, $capsule_ids)) {
                                        array_push($capsule_ids, $record->capsule_id);
                                    }
                                }
                            }
                            
                            $view_slides    = 0;
                            $total_slides   = 0;
                            foreach($capsule_ids as $capsule_id)
                            {
                                $view_slides    += $progressMapper->fetchCountAllSlideCompletedByUserIdAndCapsuleId($user->id, $capsule_id);
                                $total_slides   += $slideMapper->fetchTotalCountByCompanyIdAndTopicIdAndCapsuleId($topic->company_id, $topic->id, $capsule_id);
                            }
                            
                            $recordProgress->progress       = $total_slides > 0 ? (($view_slides * 100) / $total_slides) : 0;
                            $recordProgress->total_slides   = $total_slides;
                            $recordProgress->view_slides    = $view_slides;
                        }
                        else if($type == CompanyMicrolearningUserProgress::TYPE_CAPSULE ) {
                            $view_slides    = $progressMapper->fetchCountAllSlideCompletedByUserIdAndCapsuleId($user->id, $capsule->id);
                            $total_slides   = $slideMapper->fetchTotalCountByCompanyIdAndTopicIdAndCapsuleId($topic->company_id, $capsule->topic_id, $capsule->id);
                            
                            $recordProgress->progress       = $total_slides > 0 ? (($view_slides * 100) / $total_slides) : 0;
                            $recordProgress->total_slides   = $total_slides;
                            $recordProgress->view_slides    = $view_slides;
                        }
                        else {
                            $recordProgress->progress       = 0;
                            $recordProgress->total_slides   = 0;
                            $recordProgress->view_slides    = 0;
                        }
                        
                        $recordProgress->updated_on = $updated_on;
                        
                        
                        
                        if($recordProgress->id) {
                            $result = $progressMapper->update($recordProgress);
                        } else {
                            $result = $progressMapper->insert($recordProgress);
                        }
                        
                        if($result) {
                            array_push($result_sync_ids, [
                                'success' => true,
                                'sync_id' => $sync_id
                            ]);
                        } else {
                            array_push($result_sync_ids, [
                                'success' => false,
                                'sync_id' => $sync_id,
                                'message' => $progressMapper->getError()
                            ]);
                        }
                        continue;
                    }
                    
                    
                    
                    if($sync_type == 'microlearning-userlog') {
                        $activity   = isset($record['activity'])      ? filter_var($record['activity'], FILTER_SANITIZE_STRING)  :  '';
                        $added_on   = isset($record['added_on'])      ? filter_var($record['added_on'], FILTER_SANITIZE_STRING)  :  '';
                        
                        
                        if(empty($activity)) {
                            $ok = false;
                        }
                        
                        $dt = \DateTime::createFromFormat($serviceDatetimeFormat, $added_on);
                        if(!$dt) {
                            $ok = false;
                        } else {
                            $added_on = $dt->format('Y-m-d H:i:s');
                        }
                        
                        if(!$ok) {
                            array_push($result_sync_ids, [
                                'success' => false,
                                'sync_id' => $sync_id,
                                'message' => 'ERROR_INVALID_PARAMETERS',
                            ]);
                            continue;
                        }
                        
                        $userLog = new CompanyMicrolearningUserLog();
                        $userLog->activity      = $activity;
                        $userLog->user_id       = $user->id;
                        $userLog->company_id    = $topic->company_id;
                        $userLog->topic_id      = $topic->id;
                        $userLog->capsule_id    = $capsule ? $capsule->id : null;
                        $userLog->slide_id      = $slide ? $slide->id : null;
                        $userLog->added_on      = $added_on;
                        
                        
                        
                        $userLogMapper = CompanyMicrolearningUserLogMapper::getInstance($this->adapter);
                        if($userLogMapper->insert($userLog)) {
                            array_push($result_sync_ids, [
                                'success' => true,
                                'sync_id' => $sync_id 
                            ]);
                        } else {
                            array_push($result_sync_ids, [
                                'success' => false,
                                'sync_id' => $sync_id,
                                'message' => $userLogMapper->getError()
                            ]);
                        }
                        continue;
                    }
                    
                }
                
                /***** FIN MICROLEARNING *****/
                
                
                /***** INICIO LOG DE USUARIO GENERAL *****/
                
                if($user_uuid && $sync_type == 'userlog' && $device->application_id = Application::TWOGETSKILLS) {
                    
                    $userMapper = UserMapper::getInstance($this->adapter);
                    $user = $userMapper->fetchOneByUuid($user_uuid);
                    
                    if(!$user) {
                        array_push($result_sync_ids, [
                            'success' => false,
                            'sync_id' => $sync_id,
                            'message' => 'ERROR_USER_NOT_FOUND',
                            'fatal' => true
                        ]);
                        continue;
                    }
                    
                    
                    if($user->status != User::STATUS_ACTIVE) {
                        array_push($result_sync_ids, [
                            'success' => false,
                            'sync_id' => $sync_id,
                            'message' => 'ERROR_USER_IS_NOT_ACTIVE',
                            'fatal' => true
                        ]);
                        continue;
                    }
                    
                    $activity   = isset($record['activity'])      ? filter_var($record['activity'], FILTER_SANITIZE_STRING)  :  '';
                    $added_on   = isset($record['added_on'])      ? filter_var($record['added_on'], FILTER_SANITIZE_STRING)  :  '';
                    
                    if(empty($activity)) {
                        $ok = false;
                    }
                    
                    $dt = \DateTime::createFromFormat($serviceDatetimeFormat, $added_on);
                    if(!$dt) {
                        $ok = false;
                    } else {
                        $added_on = $dt->format('Y-m-d H:i:s');
                    }
                    
                    if(!$ok) {
                        array_push($result_sync_ids, [
                            'success' => false,
                            'sync_id' => $sync_id,
                            'message' => 'ERROR_INVALID_PARAMETERS',
                        ]);
                        continue;
                    }
                    
                    $userLog = new CompanyMicrolearningUserLog();
                    $userLog->company_id = null;
                    $userLog->user_id = $user->id;
                    $userLog->activity = $activity;
                    $userLog->added_on = $added_on;
                    
                    
                    $userLogMapper = CompanyMicrolearningUserLogMapper::getInstance($this->adapter);
                    if($userLogMapper->insert($userLog)) {
                        array_push($result_sync_ids, [
                            'success' => true,
                            'sync_id' => $sync_id
                        ]);
                    } else {
                        array_push($result_sync_ids, [
                            'success' => false,
                            'sync_id' => $sync_id,
                            'message' => $userLogMapper->getError()
                        ]);
                    }
                    
                    continue;
                }

                /***** FIN LOG DE USUARIO GENERAL ******/
            }

            if( $result_sync_ids) {
                return new JsonModel([
                    'success' => true,
                    'data' => $result_sync_ids
                ]);
            } else {
                return new JsonModel([
                    'success' => false,
                    'data' => 'ERROR_INVALID_PARAMETERS'
                ]);
            }
           
            
        }
        
        return new JsonModel([
            'success' => false,
            'data' => 'ERROR_METHOD_NOT_ALLOWED'
        ]);
    }
    
    /**
     * 
     * @param User $user
     * @param boolean $includeLogs
     * @param boolean $includeProgress
     * @return array[]
     */
    private function getSyncData($user, $includeLogs = true, $includeProgress = true)
    {

        $serviceDatetimeFormat = $this->config['leaderslinked.services.datetime'];
        
        $data = [
            'userlog'   => [],
            'progress'  => [],
            'topics'    => [],
            'quizzes'   => [],
        ];
        
        
        $companies = [];
        $companyMapper = CompanyMapper::getInstance($this->adapter);
        
        $topics = [];
        $topicMapper = CompanyMicrolearningTopicMapper::getInstance($this->adapter);
        
        $capsules = [];
        $capsuleMapper = CompanyMicrolearningCapsuleMapper::getInstance($this->adapter);
        
        $slides = [];
        $slideMapper = CompanyMicrolearningSlideMapper::getInstance($this->adapter);
        
        $quizzes = [];
        $quizMapper = CompanyMicrolearningQuizMapper::getInstance($this->adapter);

        $questions = [];
        $questionMapper = CompanyMicrolearningQuestionMapper::getInstance($this->adapter);
        
        $answers = [];
        $answerMapper = CompanyMicrolearningAnswerMapper::getInstance($this->adapter);
        
        
        $userLogMapper = CompanyMicrolearningUserLogMapper::getInstance($this->adapter);
        
        if($includeLogs) {
        
            $records = $userLogMapper->fetchLast20ByUserId($user->id);
            foreach($records as $record)
            {
                $dt = \DateTime::createFromFormat('Y-m-d H:i:s', $record->added_on);
                
                if($record->company_id) {
                    
                    if(isset($companies[$record->company_id])) {
                        $company = $companies[$record->company_id];
                    } else {
                        $company = $companyMapper->fetchOne($record->company_id);
                        $companies[$record->company_id] = $company;
                    }
                } else {
                    $company = null;
                }
                
                if($record->topic_id) {
                    
                    if(isset($topics[$record->topic_id])) {
                        $topic = $topics[$record->topic_id];
                    } else {
                        $topic = $topicMapper->fetchOne($record->topic_id);
                        $topics[$record->topic_id] = $topic;
                    }
                } else {
                    $topic = null;
                }
                
                
                if($record->capsule_id) {
                    
                    if(isset($capsules[$record->capsule_id])) {
                        $capsule = $capsules[$record->capsule_id];
                    } else {
                        $capsule = $capsuleMapper->fetchOne($record->capsule_id);
                        $capsules[$record->capsule_id] = $capsule;
                    }
                } else {
                    $capsule = null;
                }
                
                
                if($record->slide_id) {
                    
                    if(isset($slides[$record->slide_id])) {
                        $slide = $slides[$record->slide_id];
                    } else {
                        $slide = $slideMapper->fetchOne($record->slide_id);
                        $slides[$record->slide_id] = $slide;
                    }
                } else {
                    $slide = null;
                }
                
                
                array_push($data['userlog'], [
                    'user_uuid'     => $user->uuid,
                    'company_uuid'  => $company ? $company->uuid : '',
                    'topic_uuid'    => $topic ? $topic->uuid : '',
                    'capsule_uuid'  => $capsule ? $capsule->uuid : '',
                    'slide_uuid'    => $slide ? $slide->uuid : '',
                    'activity'      => $record->activity,
                    'added_on'      => $dt->format($serviceDatetimeFormat),
                ]);
                
                
            }
        }
        
        if($includeProgress) {
        
            $userProgressMapper = CompanyMicrolearningUserProgressMapper::getInstance($this->adapter);
            $records = $userProgressMapper->fetchAllByUserId($user->id);
            foreach($records as $record)
            {
                if($record->company_id) {
                    
                    if(isset($companies[$record->company_id])) {
                        $company = $companies[$record->company_id];
                    } else {
                        $company = $companyMapper->fetchOne($record->company_id);
                        $companies[$record->company_id] = $company;
                    }
                } else {
                    $company = null;
                }
                
                if($record->topic_id) {
                    
                    if(isset($topics[$record->topic_id])) {
                        $topic = $topics[$record->topic_id];
                    } else {
                        $topic = $topicMapper->fetchOne($record->topic_id);
                        $topics[$record->topic_id] = $topic;
                    }
                } else {
                    $topic = null;
                }
                
                
                if($record->capsule_id) {
                    
                    if(isset($capsules[$record->capsule_id])) {
                        $capsule = $capsules[$record->capsule_id];
                    } else {
                        $capsule = $capsuleMapper->fetchOne($record->capsule_id);
                        $capsules[$record->capsule_id] = $capsule;
                    }
                } else {
                    $capsule = null;
                }
                
                
                if($record->slide_id) {
                    
                    if(isset($slides[$record->slide_id])) {
                        $slide = $slides[$record->slide_id];
                    } else {
                        $slide = $slideMapper->fetchOne($record->slide_id);
                        $slides[$record->slide_id] = $slide;
                    }
                } else {
                    $slide = null;
                }
                

                $dtAddedOn = \DateTime::createFromFormat('Y-m-d H:i:s', $record->added_on);
                $dtUpdatedOn = \DateTime::createFromFormat('Y-m-d H:i:s', $record->updated_on);
                
                array_push($data['progress'], [
                    'user_uuid'                 => $user->uuid,
                    'company_uuid'              => $company ? $company->uuid : '',
                    'topic_uuid'                => $topic ? $topic->uuid : '',
                    'capsule_uuid'              => $capsule ? $capsule->uuid : '',
                    'slide_uuid'                => $slide ? $slide->uuid : '',
                    'progress'                  => $record->progress ? $record->progress : 0,
                    'total_slides'              => $record->total_slides ? $record->total_slides : 0,
                    'view_slides'               => $record->view_slides ? $record->view_slides : 0,
                    'type'                      => $record->type,
                    'returning'                 => $record->returning ? $record->returning : 0,
                    'returning_after_completed' => $record->returning_after_completed ? $record->returning_after_completed : 0,
                    'completed'                 => $record->completed ? $record->completed : 0,
                    'added_on'                  => $dtAddedOn->format($serviceDatetimeFormat),
                    'updated_on'                => $dtUpdatedOn->format($serviceDatetimeFormat),
                ]);
            }
        }
        

        $now = date('Y-m-d H:i:s');
        $companies_with_access  = [];
        $topics_with_access     = [];
        $capsules_with_access   = [];
        $quizzes_with_access    = [];
        $quizzes                = [];
        
        
        $capsuleUserMapper = CompanyMicrolearningCapsuleUserMapper::getInstance($this->adapter);
        $records = $capsuleUserMapper->fetchAllActiveByUserId($user->id);
        

        foreach($records as $record) 
        {
            if($record->access != CompanyMicrolearningCapsuleUser::ACCESS_UNLIMITED && $record->access != CompanyMicrolearningCapsuleUser::ACCESS_PAY_PERIOD) {
                continue;
            }
            if($record->access == CompanyMicrolearningCapsuleUser::ACCESS_PAY_PERIOD) {
                if($now < $record->paid_from || $now > $record->paid_to) {
                    continue;
                }
            }
            
            
            if(!in_array($record->company_id,$companies_with_access)) {
                array_push($companies_with_access, $record->company_id);
            }
            
            if(!in_array($record->topic_id,$topics_with_access)) {
                array_push($topics_with_access, $record->topic_id);
            }
            
            if(!in_array($record->capsule_id,$capsules_with_access)) {
                array_push($capsules_with_access, $record->capsule_id);
            }
        }
       
 /*
        echo '$companies_with_access ' . PHP_EOL;
        print_r($companies_with_access);
        
        echo '$topics_with_access ' . PHP_EOL;
        print_r($topics_with_access);
        
        echo '$capsules_with_access' . PHP_EOL;
        print_r($capsules_with_access);
        */
        
        $companyServiceMapper = CompanyServiceMapper::getInstance($this->adapter);
        foreach($companies_with_access as $company_id)
        {
            $companyService =  $companyServiceMapper->fetchOneActiveByCompanyIdAndServiceId($company_id, Service::MICRO_LEARNING);
            
            //print_r($companyService); exit;
            
            if(!$companyService) {
                continue;
            }

            
            if(isset($companies[$companyService->company_id])) {
                $company = $companies[$companyService->company_id]; 
            } else {
                $company = $companyMapper->fetchOne($companyService->company_id); 
                $companies[$companyService->company_id] = $company;
            }

            $topics = $topicMapper->fetchAllActiveByCompanyId($company_id);
            foreach($topics as $topic)
            {
                if(!in_array($topic->id, $topics_with_access)) {
                    continue;
                }
                
                $record_capsules = [];
                $capsules = $capsuleMapper->fetchAllActiveByCompanyIdAndTopicId($topic->company_id, $topic->id);
                foreach($capsules as $capsule)
                {
                    if(!in_array($capsule->id, $capsules_with_access)) {
                        continue;
                    }
                    
                    
                    $record_slides = [];
                    $slides = $slideMapper->fetchAllByCompanyIdAndTopicIdAndCapsuleId($capsule->company_id, $capsule->topic_id, $capsule->id);
                    foreach($slides as $slide)
                    {
                        if($slide->type == CompanyMicrolearningSlide::TYPE_QUIZ) {
                            if(!in_array($slide->quiz_id, $quizzes_with_access)) {
                                array_push($quizzes_with_access, $slide->quiz_id);
                            }
                            
                            if(isset($quizzes[$slide->quiz_id])) {
                                $quiz = $quizzes[$slide->quiz_id];
                                
                            } else {
                                $quiz = $quizMapper->fetchOne($slide->quiz_id);
                                $quizzes[$slide->quiz_id] =  $quiz;
                            }
                        } else {
                            $quiz = null;
                        }
                        
                       
                        
                        array_push($record_slides, [
                            'uuid' => $slide->uuid,
                            'quiz_uuid' => $quiz ? $quiz->uuid : '',
                            'name' => $slide->name ? $slide->name : '',
                            'description' => $slide->description ? $slide->description : '',
                            'position' => $slide->order,
                            'type' => $slide->type,
                            'background' => $slide->background ? $this->url()->fromRoute('services/storage',['type' => 'microlearning-slide', 'code' => $slide->uuid, 'filename' => $slide->background], ['force_canonical' => true]) : '',
                            'file' => $slide->file ? $this->url()->fromRoute('services/storage',['type' => 'microlearning-slide', 'code' => $slide->uuid, 'filename' => $slide->file], ['force_canonical' => true]) : '',
                        ]);
                    }
                    
                    array_push($record_capsules, [
                        'uuid' => $capsule->uuid,
                        'name' => $capsule->name ? $capsule->name : '',
                        'description' => $capsule->description ? $capsule->description : '',
                        'image' => $capsule->image ? $this->url()->fromRoute('services/storage',['type' => 'microlearning-capsule', 'code' => $capsule->uuid, 'filename' => $capsule->image ], ['force_canonical' => true])  : '',
                        'position' => $capsule->order,
                        'slides' => $record_slides,
                    ]);
                }
                
                array_push($data['topics'], [
                    'uuid' => $topic->uuid,
                    'name' => $topic->name ? $topic->name : '',
                    'description' => $topic->description ? $topic->description : '',
                    'image' => $topic->image ? $this->url()->fromRoute('services/storage',['type' => 'microlearning-topic', 'code' => $topic->uuid, 'filename' => $topic->image ], ['force_canonical' => true]) : '',
                    'position' => $topic->order,
                    'company_uuid' => $company->uuid,
                    'company_name' => $company->name,
                    'company_image' => $this->url()->fromRoute('services/storage',['type' => 'company', 'code' => $company->uuid, 'filename' => $company->image], ['force_canonical' => true]),
                    'capsules' => $record_capsules
                ]);
            }
        }
        

        
        foreach($quizzes_with_access as $quiz_id)
        {
            if(isset($quizzes[$quiz_id])) {
                $quiz = $quizzes[$quiz_id];
            } else {
                $quiz = $quizMapper->fetchOne($quiz_id);
                array_push($quizzes, $quiz);
            }
            
            if(isset($companies[$quiz->company_id])) {
                $company = $companies[$quiz->company_id];
            } else {
                $company = $companyMapper->fetchOne($quiz->company_id);
                $companies[$quiz->company_id] = $company;
            }
            
            
            $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)
                {
                    array_push($record_answers, [
                        'uuid' => $answer->uuid,
                        'text' => trim($answer->text),
                        'correct' => $answer->correct ? $answer->correct  : 0 ,
                        'points' => intval($answer->points, 10),
                    ]);
                }
                
                array_push($record_questions, [
                    'uuid' => $question->uuid,
                    'text' => trim($question->text),
                    'type' => $question->type,
                    'maxlength' => $question->maxlength,
                    'points' => $question->points,
                    'answers' => $record_answers,
                ]);
            }
            
            
            array_push($data['quizzes'], [
                'uuid' => $quiz->uuid,
                'name' => $quiz->name,
                'text' => trim($quiz->text ? $quiz->text : ''),
                'failed' => trim($quiz->failed ? $quiz->failed : ''),
                'points' => $quiz->points,
                'minimum_points_required' => $quiz->minimum_points_required,
                'max_time' => $quiz->max_time ? $quiz->max_time : 5,
                'company_uuid' => $company->uuid,
                'company_name' => $company->name,
                'company_image' => $this->url()->fromRoute('services/storage',['type' => 'company', 'code' => $company->uuid, 'filename' => $company->image], ['force_canonical' => true]),
                'questions' => $record_questions,
            ]);
        }
        return $data;
    }

    
    /**
     * 
     * @param string $filename
     * @param boolean $retbytes
     * @return boolean|number
     */
    private function readfile_chunked($filename, $retbytes = true) {
        $buffer = '';
        $cnt =0;;
        $handle = fopen($filename,'rb');
        if ($handle === false) {
            return false;
        }
        while (!feof($handle)) {
            $buffer = fread($handle, self::CHUNK_SIZE);
            echo $buffer;
            ob_flush();
            flush();
            if ($retbytes) {
                $cnt += strlen($buffer);
            }
        }
        $status = fclose($handle);
        if ($retbytes && $status) {
            return $cnt; // return num. bytes delivered like readfile() does.
        }
        return $status;
    }
}