Proyectos de Subversion LeadersLinked - Antes de SPA

Rev

Rev 6849 | 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\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\AesCipher;
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\CompanyMicrolearningUserMapper;
use LeadersLinked\Model\CompanyMicrolearningUser;
use LeadersLinked\Mapper\PushTemplateMapper;
use LeadersLinked\Model\PushTemplate;
use LeadersLinked\Mapper\SyncLogMapper;
use LeadersLinked\Model\SyncLog;
use LeadersLinked\Model\CompanyMicrolearningExtendUser;
use LeadersLinked\Mapper\CompanyMicrolearningExtendUserMapper;
use LeadersLinked\Model\CompanyMicrolearningExtendUserCompany;
use LeadersLinked\Mapper\CompanyMicrolearningCapsuleCommentMapper;
use LeadersLinked\Mapper\CompanyMicrolearningExtendUserCompanyMapper;
use LeadersLinked\Mapper\CompanyMicrolearningExtendUserFunctionMapper;
use LeadersLinked\Mapper\CompanyMicrolearningExtendUserGroupMapper;
use LeadersLinked\Mapper\CompanyMicrolearningExtendUserInstitutionMapper;
use LeadersLinked\Mapper\CompanyMicrolearningExtendUserPartnerMapper;
use LeadersLinked\Mapper\CompanyMicrolearningExtendUserProgramMapper;
use LeadersLinked\Mapper\CompanyMicrolearningExtendUserStudentTypeMapper;
use LeadersLinked\Mapper\CompanyMicrolearningExtendUserSectorMapper;
use Nullix\CryptoJsAes\CryptoJsAes;
use LeadersLinked\Model\CompanyMicrolearningTopic;
use LeadersLinked\Model\CompanyMicrolearningCapsule;
use LeadersLinked\Model\UserDeleted;
use LeadersLinked\Mapper\UserDeletedMapper;
use LeadersLinked\Mapper\ApplicationVariantMapper;


class ServiceController extends AbstractActionController
{
    /**
     *
     * @var \Laminas\Db\Adapter\AdapterInterface
     */
    private $adapter;
    
    /**
     *
     * @var \LeadersLinked\Cache\CacheInterface
     */
    private $cache;
    
    
    /**
     *
     * @var \Laminas\Log\LoggerInterface
     */
    private $logger;
    
    /**
     *
     * @var array
     */
    private $config;
    
    
    /**
     *
     * @var \Laminas\Mvc\I18n\Translator
     */
    private $translator;
    
    
    /**
     *
     * @param \Laminas\Db\Adapter\AdapterInterface $adapter
     * @param \LeadersLinked\Cache\CacheInterface $cache
     * @param \Laminas\Log\LoggerInterface LoggerInterface $logger
     * @param array $config
     * @param \Laminas\Mvc\I18n\Translator $translator
     */
    public function __construct($adapter, $cache, $logger, $config, $translator)
    {
        $this->adapter      = $adapter;
        $this->cache        = $cache;
        $this->logger       = $logger;
        $this->config       = $config;
        $this->translator   = $translator;
    }
    
    public function indexAction() 
    {
        return new JsonModel(['ok' => false]);
    }
    
    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      = Functions::sanitizeFilterString($this->params()->fromPost('device_uuid', ''));
            $token          = Functions::sanitizeFilterString($this->params()->fromPost('token', ''));
            $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',
                ]);
            }
            
            
            $syncLog = new SyncLog();
            $syncLog->data = json_encode(['token' => $token]);
            $syncLog->type = 'token';
            $syncLog->device_uuid = $device->id;
            $syncLog->ip = Functions::getUserIP();
            
            $syncLogMapper = SyncLogMapper::getInstance($this->adapter);
            $syncLogMapper->insert($syncLog);
            
            $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  = Functions::sanitizeFilterString($this->params()->fromPost('device_id', ''));
            $secret     = Functions::sanitizeFilterString($this->params()->fromPost('secret', ''));
            $rand       = filter_var($this->params()->fromPost('rand', ''), FILTER_SANITIZE_NUMBER_INT);
            $created    = Functions::sanitizeFilterString($this->params()->fromPost('created', ''));
            
            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);
            $variant_id     = filter_var($this->params()->fromPost('variant_id', 0), FILTER_SANITIZE_NUMBER_INT);
            $device_uuid    = Functions::sanitizeFilterString($this->params()->fromPost('device_uuid', ''));
            $manufacturer   = Functions::sanitizeFilterString($this->params()->fromPost('manufacturer', ''));
            $platform       = Functions::sanitizeFilterString($this->params()->fromPost('platform', ''));
            $brand          = Functions::sanitizeFilterString($this->params()->fromPost('brand', ''));
            $version        = Functions::sanitizeFilterString($this->params()->fromPost('version', ''));
            $model          = Functions::sanitizeFilterString($this->params()->fromPost('model', ''));
            $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;
            
            /*
            echo "application_id = $application_id" . PHP_EOL;
            echo "variant_id = $variant_id" . PHP_EOL;
            echo "device_uuid = $device_uuid" . PHP_EOL;
            echo "sync_id = $sync_id" . PHP_EOL;
            echo "manufacture = $manufacturer" . PHP_EOL;
            echo "brand = $brand" . PHP_EOL;
            echo "version = $version" . PHP_EOL;
            echo "model = $model" . PHP_EOL;
            */
            
            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',
                ]);
            }
            
            $applicationVariantMapper = ApplicationVariantMapper::getInstance($this->adapter);
            if ($variant_id) {
                $applicationVariant = $applicationVariantMapper->fetchOneByApplicationIdAndVariantId($application->id, $variant_id);
                if(!$applicationVariant) {
                
                    return new JsonModel([
                        'success' => false,
                        'data' => 'ERROR_APPLICATION_VARIANT_IS_INVALID',
                    ]);
                }
            } else {
                $applicationVariant = $applicationVariantMapper->fetchOneByApplicationIdAndDefault($application->id);
            }
            
            
            
            $syncLog = new SyncLog();
            $syncLog->data = json_encode([
                'platform' => $platform,
                'manufacturer' => $manufacturer,
                'brand' => $brand,
                'version' => $version,
                'model' => $model,
            ]);
            $syncLog->type = 'device';
            $syncLog->device_uuid = $device_uuid;
            $syncLog->ip = Functions::getUserIP();
            
            $syncLogMapper = SyncLogMapper::getInstance($this->adapter);
            $syncLogMapper->insert($syncLog);
            
            
            $deviceMapper = DeviceMapper::getInstance($this->adapter);
            $device = $deviceMapper->fetchOne($device_uuid);
            
            
            
            
            if($device) {
                $device->application_id = $application->id;
                $device->variant_id     = $applicationVariant->variant_id;
                $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->variant_id     = $applicationVariant->variant_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('url = ' . $_SERVER['REQUEST_URI']);
           // error_log('query = ' . $_SERVER['QUERY_STRING']);
           // error_log('$rawdata = ' . $rawdata );
        
            
            $serviceDatetimeFormat = $this->config['leaderslinked.services.datetime'];
            
            
            $device_uuid        = Functions::sanitizeFilterString($this->params()->fromPost('device_uuid', ''));
            $max_date_changes   = Functions::sanitizeFilterString($this->params()->fromPost('max_date_changes', ''));
            $max_ids            = filter_var($this->params()->fromPost('max_ids', 0), FILTER_SANITIZE_NUMBER_INT);
            $is_foreground      = filter_var($this->params()->fromPost('is_foreground', 0), FILTER_SANITIZE_NUMBER_INT);
            $application_id     = filter_var($this->params()->fromPost('application_id', 0), FILTER_SANITIZE_NUMBER_INT);
            $variant_id         = filter_var($this->params()->fromPost('variant_id', 0), FILTER_SANITIZE_NUMBER_INT);
      
            
            $ids = [];
            for($i = 1; $i <= $max_ids; $i++)
            {
                $id = trim(Functions::sanitizeFilterString($this->params()->fromPost('id_' . $i, '')));
               

                
                if(empty($id)) {
                    continue;
                }
                
              
                
       
                $pattern = '/[A-Za-z0-9\-]+\|[A-Za-z0-9\-]+/';
                $matches = [];  
                preg_match($pattern, $id, $matches, PREG_OFFSET_CAPTURE);
       
                
                
                if($matches) {
                    array_push($ids, $id);
                }
            }

            
            if(empty($ids)) {
                $max_date_changes = '';
            }  else {
            
            
                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 = '';
                } 
            }
            
            $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 {
                if ($application_id && $variant_id) {
                    $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',
                        ]);
                    }
                    
                    $applicationVariantMapper = ApplicationVariantMapper::getInstance($this->adapter);
                    if ($variant_id) {
                        $applicationVariant = $applicationVariantMapper->fetchOneByApplicationIdAndVariantId($application->id, $variant_id);
                        if(!$applicationVariant) {
                            
                            return new JsonModel([
                                'success' => false,
                                'data' => 'ERROR_APPLICATION_VARIANT_IS_INVALID',
                            ]);
                        }
                    } else {
                        $applicationVariant = $applicationVariantMapper->fetchOneByApplicationIdAndDefault($application->id);
                    }
                    
                    
                    $device->application_id = $application->id;
                    $device->variant_id = $applicationVariant->variant_id;
                }
                
                
                $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);
                }
            }
            
            /*
            echo '$max_date_changes  = ' . $max_date_changes  . PHP_EOL;
            echo '$max_date_changes_db  = ' . $max_date_changes_db. PHP_EOL;
            exit;
            */
           // $max_date_changes = '';
            

            //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->fetchAllActive();
                        
                    $capsules = [];
                    foreach($companyMicrolearningCapsules as $capsule)
                    {                            
                        $capsules[$capsule->id] = $capsule->uuid;
                    }
                    */
                    
                    $topicMapper = CompanyMicrolearningTopicMapper::getInstance($this->adapter);
                    $capsuleMapper = CompanyMicrolearningCapsuleMapper::getInstance($this->adapter);
                    
                        
                    $companyMicrolearningCapsuleUserMapper = CompanyMicrolearningCapsuleUserMapper::getInstance($this->adapter);
                    $userCapsules = $companyMicrolearningCapsuleUserMapper->fetchAllActiveByUserId($user->id);
                        
                    
                    //print_r($user_capsules); 
                    
                    foreach($userCapsules as $userCapsule) 
                    {
                        
                        $topic  = $topicMapper->fetchOne($userCapsule->topic_id);
                        $capsule = $capsuleMapper->fetchOne($userCapsule->capsule_id);
                        
                        if($topic && $capsule) {
                            if($topic->status == CompanyMicrolearningTopic::STATUS_ACTIVE && $capsule->status == CompanyMicrolearningCapsule::STATUS_ACTIVE) {
                                $key = $topic->uuid . '|' . $capsule->uuid;
                                if(!in_array($key, $ids)) {
                                    $newCapsules++;
                                }
                            }
                        }
                    }
                }
            }

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

             
                if($device->token && $is_foreground)
                {
                    
            
                    
                    $applicationMapper = ApplicationMapper::getInstance($this->adapter);
                    $application = $applicationMapper->fetchOne(Application::TWOGETSKILLS);
                    
      
                    
                
                    $pushMapper = PushMapper::getInstance($this->adapter);
                    $pushTemplateMapper = PushTemplateMapper::getInstance($this->adapter);
                    $pushTemplate = $pushTemplateMapper->fetchOneByCodeAndCompanyId(PushTemplate::ID_MICRO_LEARNING_NEW_CONTENT, $applicationVariant->company_id);
                    
                    if(!$pushTemplate) {
                        $pushTemplate = $pushTemplateMapper-> fetchOneByCodeDefault(PushTemplate::ID_MICRO_LEARNING_NEW_CONTENT);
                        
                    }
                    
                    
                    //echo 'PushTemplate' . PHP_EOL;
                    //print_r($pushTemplate);
  
                    
                    
                    //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,
                                    
                                    
                                ],
                                'content_available' => true,
                                'data' => [
                                    'command' => 'content-refresh',
                                    'new_capsules' => strval($newCapsules),
                                ]
                            ]
                        ]);
                        
                        
                        //print_r($push);
                        
                        $pushMapper->insert($push);
                    }
                }
                
                /*
                if(!$is_foreground) {
                    $dataSync = $this->getSyncData($user,false, false);
                }
                */
            }
           
            
            //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 = '';
            }
            
            $ratingAndComments = [];
            
            $capsuleMapper = CompanyMicrolearningCapsuleMapper::getInstance($this->adapter);
            $capsuleCommentMapper = CompanyMicrolearningCapsuleCommentMapper::getInstance($this->adapter);
            
            $companyMicrolearningCapsuleUserMapper = CompanyMicrolearningCapsuleUserMapper::getInstance($this->adapter);
            $userCapsules = $companyMicrolearningCapsuleUserMapper->fetchAllActiveByUserId($user->id);
            
            foreach($userCapsules as $userCapsule) 
            {
                $capsule = $capsuleMapper->fetchOne($userCapsule->capsule_id);
                if($capsule) {
                    
                    $record = $capsuleCommentMapper->fetchCountAndRatingAverage($capsule->company_id, $capsule->topic_id, $capsule->id);
                    
                    
                    array_push($ratingAndComments, [
                        'uuid' => $capsule->uuid, 
                        'total_comments' => $record['total_comments'],
                        'total_rating' => $record['total_rating'],
                    ]);  
                }
                
            }
            
            
            
            
            $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]),
                    ],
                    'rating_and_comments'   => $ratingAndComments,
                    'new_capsules'          => strval($newCapsules),
                    'max_date_changes'      => $max_date_changes_db,
                    
                    'topics'            => [],
                    'quizzes'           => [],
                    'extended'          => [],
                ]
            ];
            
            /*
            
            
            $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]),
                    ],
                    'new_capsules' => $newCapsules,
                    'max_date_changes' => $max_date_changes_db,
                    'topics'    => isset( $dataSync['topics'] ) ? $dataSync['topics'] : [],
                    'quizzes'   => isset( $dataSync['quizzes'] ) ? $dataSync['quizzes'] : [],
                    'extended'=> isset( $dataSync['extended'] ) ? $dataSync['extended'] : [],
                ]
            ];
            */
            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'],
                    'extended'   => $dataSync['extended'],

                ]
            ]);
        }
        
        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('url = ' . $_SERVER['REQUEST_URI']);
            error_log('query = ' . $_SERVER['QUERY_STRING']);
            error_log('$rawdata = ' . $rawdata );
         
            
            $application_id = filter_var($this->params()->fromPost('application_id', 0), FILTER_SANITIZE_NUMBER_INT);
            $variant_id     = filter_var($this->params()->fromPost('variant_id', 0), FILTER_SANITIZE_NUMBER_INT);
            $device_uuid    = Functions::sanitizeFilterString($this->params()->fromPost('device_uuid', ''));
            $email          = filter_var($this->params()->fromPost('email', ''), FILTER_SANITIZE_EMAIL);
            $password       = Functions::sanitizeFilterString($this->params()->fromPost('password', ''));
            $encrypter      = Functions::sanitizeFilterString($this->params()->fromPost('encrypter', ''));


            
            $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',
                ]);
            }
            
            $applicationVariantMapper = ApplicationVariantMapper::getInstance($this->adapter);
            if ($variant_id) {
                $applicationVariant = $applicationVariantMapper->fetchOneByApplicationIdAndVariantId($application->id, $variant_id);
            } else {
                $applicationVariant = $applicationVariantMapper->fetchOneByApplicationIdAndDefault($application->id);
            }
            
            
            $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->variant_id     = $applicationVariant->variant_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(!$device) {
                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') {
                
                error_log("RNCryptor");
                error_log("Device UUID : " . $device->id);
                error_log("AES : " . $device->aes);
                error_log("Email Encrypted : " . $email);
                error_log("Password Encrypted : " . $password);
                
                $cryptor = new \RNCryptor\RNCryptor\Decryptor;
                $email = $cryptor->decrypt($email, $device->aes);
                $password = $cryptor->decrypt($password, $device->aes);
                
                error_log("Email Decrypted : " . $email . PHP_EOL);
                error_log("Password Decrypted : " . $password . PHP_EOL);
                
                if(!$email || !$password) {
                    return new JsonModel([
                        'success' => false,
                        'data' => 'ERROR_WEBSERVICE_PASSWORD_ENCRYPTION_FAILED',
                    ]);
                } 
                
               
            } else if($encrypter == 'AesCipher') {
                
                error_log("AesCipher");
                error_log("Device UUID : " . $device->id);
                error_log("AES : " . $device->aes);
                error_log("Email Encrypted : " . $email);
                error_log("Password Encrypted : " . $password);
                
                $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();
                
                error_log("Email Decrypted : " . $email . PHP_EOL);
                error_log("Password Decrypted : " . $password . PHP_EOL);
                
            } else {
                $email   = filter_var($email, FILTER_SANITIZE_EMAIL);
            }
      
            $companyMapper = CompanyMapper::getInstance($this->adapter);
            $company = $companyMapper->fetchOne($applicationVariant->company_id);
            
      
            $authAdapter = new AuthAdapter($this->adapter);
            $authAdapter->setData($email, $password, $company->network_id);
            
            $authService = new AuthenticationService();
            $result = $authService->authenticate($authAdapter);
            
            $ip = Functions::getUserIP();
            if($result->getCode() == AuthResult::SUCCESS) {
                
                $userMapper = UserMapper::getInstance($this->adapter);
                $user = $userMapper->fetchOneByEmailAndNetworkId($email, $company->network_id);
              
                
                $device->user_id    = $user->id;
                $device->ip         = $ip;
                
                if ($application_id && $variant_id) {
                    $device->application_id = $application_id;
                    $device->variant_id = $variant_id;
                }
                
                if($deviceMapper->update($device)) {
                    
                    
                    
                    $deviceHistoryMapper = DeviceHistoryMapper::getInstance($this->adapter);
                    $deviceHistory = $deviceHistoryMapper->fetchOneByDeviceIdAndUserIdAndIp($device->id, $user->id, $ip);
                    if($deviceHistory) {
                        $deviceHistory->ip = $ip;
                        $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->fetchAllByUserIdAndApplicationId($user->id, $device->application_id);
                    foreach($userDevices as $userDevice)
                    {
       
                        if($userDevice->id != $device->id ) {
                            $deviceMapper->releaseUserFormDevice($userDevice);
                            
                    
                            if($userDevice->token) {
                                
                                $key = $application->key;
                                if ($device->variant_id) {
                                    $applicationVariant = $applicationVariantMapper->fetchOneByApplicationIdAndVariantId($application->id, $variant_id);
                                    if($applicationVariant) {
                                        $key = $applicationVariant->key;
                                        
                                    } else {
                                        $applicationVariant = $applicationVariantMapper->fetchOneByApplicationIdAndDefault($application->id);
                                        if($applicationVariant) {
                                            $key = $applicationVariant->key;
                                        }
                                    }
                                }
                                
                                
                                $push = new Push();
                                $push->status = Push::STATUS_PENDING;
                                $push->data = json_encode([
                                    'server' => [
                                        'key' =>  $key,
                                     ],
                                     'push' => [
                                        'registration_ids'   => [ 
                                            $userDevice->token,
                                         ],
                                         'notification' => [
                                             'body' =>  'Se registro un inicio de sesión en otro dispositivo',
                                             'title' => 'Nuevo inicio de sesió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'];
                        $data['data']['extended'] = $dataSync['extended'];
                    }
                    
                    
  
                    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', 'ERROR_USER_REQUEST_ACCESS_IS_PENDING', 'ERROR_USER_REQUEST_ACCESS_IS_REJECTED'  ])) {
                }
                
                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;
                        
                        
                    case 'ERROR_USER_REQUEST_ACCESS_IS_PENDING' :
                        $this->logger->err('Error de ingreso a LeadersLinked de ' . $email . ' - Falta verificar que pertence a la Red Privada', ['ip' => Functions::getUserIP()]);
                        break;
                        
                    case  'ERROR_USER_REQUEST_ACCESS_IS_REJECTED' :
                        $this->logger->err('Error de ingreso a LeadersLinked de ' . $email . ' - Rechazado por no pertence a la Red Privada', ['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()) {
            
           
            
            
            $serviceDatetimeFormat = $this->config['leaderslinked.services.datetime'];
            
            $device_uuid    = Functions::sanitizeFilterString($this->params()->fromPost('device_uuid', ''));
            $sync_id        = filter_var($this->params()->fromPost('sync_id', ''), FILTER_SANITIZE_NUMBER_INT);
            $data           = $this->params()->fromPost('data', '');
            $application_id = filter_var($this->params()->fromPost('application_id', 0), FILTER_SANITIZE_NUMBER_INT);
            $variant_id     = filter_var($this->params()->fromPost('variant_id', 0), FILTER_SANITIZE_NUMBER_INT);
           
            
            //error_log('device_uuid = ' . $device_uuid);
            //error_log('sync_id = ' . $sync_id);
            //error_log(print_r($data, true));
            
            
            //$rawdata = file_get_contents("php://input");
           // error_log('$rawdata = ' . $rawdata );
           
            $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 {
                
                if ($application_id && $variant_id) {
                    $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',
                        ]);
                    }
                    
                    $applicationVariantMapper = ApplicationVariantMapper::getInstance($this->adapter);
                    if ($variant_id) {
                        $applicationVariant = $applicationVariantMapper->fetchOneByApplicationIdAndVariantId($application->id, $variant_id);
                        if(!$applicationVariant) {
                            
                            return new JsonModel([
                                'success' => false,
                                'data' => 'ERROR_APPLICATION_VARIANT_IS_INVALID',
                            ]);
                        }
                    } else {
                        $applicationVariant = $applicationVariantMapper->fetchOneByApplicationIdAndDefault($application->id);
                    }
                    
                    
                    $device->application_id = $application->id;
                    $device->variant_id = $applicationVariant->variant_id;
                }
                
                $device->ip = Functions::getUserIP();
                $deviceMapper->update($device);
            }
            

            
           
            
            $data = json_decode($data, true);
            $sync_type      = isset($data['sync_type']) ? Functions::sanitizeFilterString($data['sync_type']) : '';
            $user_uuid      = isset($data['user_uuid']) ? Functions::sanitizeFilterString($data['user_uuid']) : '';
            $company_uuid   = isset($data['company_uuid']) ? Functions::sanitizeFilterString($data['company_uuid']) :  '';
            
            
            $syncLog = new SyncLog();
            $syncLog->data = json_encode($data);
            $syncLog->type = $sync_type;
            $syncLog->device_uuid = $device->id;
            $syncLog->ip = Functions::getUserIP();
            
            

            
            $syncLogMapper = SyncLogMapper::getInstance($this->adapter);
            $syncLogMapper->insert($syncLog);
            
            
    //
            
            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']) ? Functions::sanitizeFilterString($data['topic_uuid']) :  '';
                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']) ? Functions::sanitizeFilterString($data['capsule_uuid']) :  '';
                $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']) ? Functions::sanitizeFilterString($data['slide_uuid']) :  '';
           
                
                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'])      ? Functions::sanitizeFilterString($data['added_on'])  :  '';
                  
                    $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 1',
                            ]
                        ]);
                    }
         
                    
                    $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'])      ? Functions::sanitizeFilterString($data['added_on'])  :  '';
                    $updated_on = isset($data['updated_on'])    ? Functions::sanitizeFilterString($data['updated_on']) :  '';
                    
                    $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 2',
                            ]
                        ]);
                    }
                    
                           //$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'])      ? Functions::sanitizeFilterString($data['activity'])  :  '';
                    $added_on   = isset($data['added_on'])      ? Functions::sanitizeFilterString($data['added_on'])  :  '';

                    
                    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 3',
                            ]
                        ]);
                    }
                                
                    $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'])      ? Functions::sanitizeFilterString($data['activity'])  :  '';
                $added_on   = isset($data['added_on'])      ? Functions::sanitizeFilterString($data['added_on'])  :  '';
                
                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 4',
                        ]
                    ]);
                }
                
                $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 );
            error_log(print_r($_POST, true));
            
            $serviceDatetimeFormat = $this->config['leaderslinked.services.datetime'];
            
            $device_uuid = Functions::sanitizeFilterString($this->params()->fromPost('device_uuid', ''));
            $application_id = filter_var($this->params()->fromPost('application_id', 0), FILTER_SANITIZE_NUMBER_INT);
            $variant_id     = filter_var($this->params()->fromPost('variant_id', 0), FILTER_SANITIZE_NUMBER_INT);
            $max_records = filter_var($this->params()->fromPost('max_records', 0), FILTER_SANITIZE_NUMBER_INT);
            

            

            $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 {
                
                if ($application_id && $variant_id) {
                    $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',
                        ]);
                    }
                    
                    $applicationVariantMapper = ApplicationVariantMapper::getInstance($this->adapter);
                    if ($variant_id) {
                        $applicationVariant = $applicationVariantMapper->fetchOneByApplicationIdAndVariantId($application->id, $variant_id);
                        if(!$applicationVariant) {
                            
                            return new JsonModel([
                                'success' => false,
                                'data' => 'ERROR_APPLICATION_VARIANT_IS_INVALID',
                            ]);
                        }
                    } else {
                        $applicationVariant = $applicationVariantMapper->fetchOneByApplicationIdAndDefault($application->id);
                    }
                    
                    
                    $device->application_id = $application->id;
                    $device->variant_id = $applicationVariant->variant_id;
                }
                
                
                $device->ip = Functions::getUserIP();
                $deviceMapper->update($device);
            }
            
            

            
            $syncLogMapper = SyncLogMapper::getInstance($this->adapter);

            

            $result_sync_ids = [];
            
            
          
            
            $users = [];
            $companies = [];
            $company_services = [];
            $topics = [];
            $capsules = [];
            $capsule_users = [];
            $slides = [];
            $quizzes = [];
            $questions = [];
            $answers = [];
            
            $userMapper = UserMapper::getInstance($this->adapter);
            $companyMapper = CompanyMapper::getInstance($this->adapter);
            $companyServiceMapper = CompanyServiceMapper::getInstance($this->adapter);
            $topicMapper = CompanyMicrolearningTopicMapper::getInstance($this->adapter);
            $capsuleMapper = CompanyMicrolearningCapsuleMapper::getInstance($this->adapter);
            $capsuleUserMapper = CompanyMicrolearningCapsuleUserMapper::getInstance($this->adapter);
            $slideMapper = CompanyMicrolearningSlideMapper::getInstance($this->adapter);
            $quizMapper = CompanyMicrolearningQuizMapper::getInstance($this->adapter);
            $questionMapper = CompanyMicrolearningQuestionMapper::getInstance($this->adapter);
            $answerMapper = CompanyMicrolearningAnswerMapper::getInstance($this->adapter);
            
            
            $userProgressMapper = CompanyMicrolearningUserProgressMapper::getInstance($this->adapter);
            $userLogMapper = CompanyMicrolearningUserLogMapper::getInstance($this->adapter);

            
            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']) ? Functions::sanitizeFilterString($record['sync_type']) : '';
                $user_uuid      = isset($record['user_uuid']) ? Functions::sanitizeFilterString($record['user_uuid']) : '';
                $company_uuid   = isset($record['company_uuid']) ? Functions::sanitizeFilterString($record['company_uuid']) : '';

                
             
                
      
                
                if(!$sync_id) {
                    continue;
                }
                
                $syncLog = new SyncLog();
                $syncLog->data = $record_data;
                $syncLog->type = $sync_type;
                $syncLog->device_uuid = $device->id;
                $syncLog->ip = Functions::getUserIP();
                $syncLogMapper->insert($syncLog);
                
                /***** INICIO MICROLEARNING *****/
                
                if($user_uuid && $device->application_id = Application::TWOGETSKILLS  && $company_uuid && in_array($sync_type, ['microlearning-progress', 'microlearning-userlog', 'microlearning-quiz'])) {
                    
                    
                    if(isset($users[$user_uuid])) {
                        $user = $users[$user_uuid];
                    } else {
                       
                        $user = $userMapper->fetchOneByUuid($user_uuid);
                        if($user) {
                            $users[$user_uuid] = $user;
                        }
                    }
                    

                    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;
                    }
                    
                    
                    if(isset($companies[$company_uuid])) {
                        $company = $companies[$company_uuid];
                    } else {
                        $company = $companyMapper->fetchOneByUuid($company_uuid);
                        if($company) {
                            $companies[$company_uuid] = $company;
                        }
                    }
                    
                    
                   
                    
                    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;
                    }
                    
                    
                    
                    $key = $company->id . '-' .  Service::MICRO_LEARNING;
                    if(isset($company_services[$key])) {
                        $companyService = $company_services[$key];
                    } else {
                        $companyService = $companyServiceMapper->fetchOneByCompanyIdAndServiceId($company->id, Service::MICRO_LEARNING);
                        if($companyService) {
                            $company_services[$key] = $companyService;
                        }
                    }
                    
                    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;
                    }
                    
                   
                    $topic_uuid = isset($record['topic_uuid']) ?   Functions::sanitizeFilterString($record['topic_uuid']) :  '';
                    if($topic_uuid) {
                        
                        if(isset($topics[$topic_uuid])) {
                            $topic = $topics[$topic_uuid];
                        } else {
                            $topic = $topicMapper->fetchOneByUuid($topic_uuid);
                            if($topic) {
                                $topics[$topic_uuid] = $topic;
                            }
                        }
                        
                        if(!$topic) {
                            error_log(print_r($record, true));
                            
                            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']) ? Functions::sanitizeFilterString($record['capsule_uuid']) :  '';
                    
                    if($capsule_uuid) {
                        
                        if(isset($capsules[$capsule_uuid])) {
                            $capsule = $capsules[$capsule_uuid];
                        } else {
                            $capsule = $capsuleMapper->fetchOneByUuid($capsule_uuid);
                            if($capsule) {
                                $capsules[$capsule_uuid] = $capsule;
                            }
                        }
                        if(!$capsule) {
                            error_log(print_r($record, true));
                            
                            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;
                        
                        $key = $user->id . '-' . $capsule->id;
                        
                        if(isset($capsule_users[$key])) {
                            $capsuleUser = $capsule_users[$key];
                        } else {
                        
                            $capsuleUser = $capsuleUserMapper->fetchOneByUserIdAndCapsuleId($user->id, $capsule->id);
                            if($capsuleUser) {
                                $capsule_users[$key] = $capsuleUser;        
                            }
                        
                        }
                        
                        $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;
                        }
                    }
                    
                    
                    $slide_uuid      = $record['slide_uuid'] ? Functions::sanitizeFilterString($record['slide_uuid']) :  '';
                    if($slide_uuid) {
                        
                        if(isset($slides[$slide_uuid])) {
                            $slide = $slides[$slide_uuid];
                        } else {
                            
                            $slide = $slideMapper->fetchOneByUuid($slide_uuid);
                            if($slide) {
                                $slides[$slide_uuid] = $slide;
                            }
                        }
                        if(!$slide) {
                            error_log(print_r($record, true));
                            
                            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'] : '';
                       
                        if(isset($quizzes[$quiz_uuid])) {
                            $quiz = $quizzes[$quiz_uuid];
                        } else {
                            $quiz = $quizMapper->fetchOneByUuid($quiz_uuid);
                            if($quiz) {
                                $quizzes[$quiz_uuid] = $quiz;
                            }
                        }
                        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'])      ? Functions::sanitizeFilterString($record['added_on'])  :  '';
                        
                        $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 9',
                            ]);
                            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(isset($questions[$question_uuid])) {
                                $question = $questions[$question_uuid];
                            } else {
                                $question = $questionMapper->fetchOneByUuid($question_uuid);
                                if($question) {
                                    $questions[$question_uuid] = $question;
                                }
                            }
                            
                            if(!$question || $question->quiz_id != $quiz->id) {
                                array_push($result_sync_ids, [
                                    'success' => false,
                                    'sync_id' => $sync_id,
                                    'message' => 'ERROR_INVALID_PARAMETERS_QUIZ_QUESTION_SLIDE',
                                ]);
                                continue;
                            }
                            
                            if(isset($answers[$answer_uuid])) {
                                $answer = $answers[$answer_uuid];
                            } else {
                                $answer = $answerMapper->fetchOneByUuid($answer_uuid);
                                if($answer) {
                                    $answers[$answer_uuid] = $answer;
                                }
                            }
                            
                            if($answer && $answer->question_id != $question->id) {
                                array_push($result_sync_ids, [
                                    'success' => false,
                                    'sync_id' => $sync_id,
                                    'message' => 'ERROR_INVALID_PARAMETERS_QUIZ_ANSWER_SLIDE',
                                ]);
                                continue;
                            }
                            
                            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'])      ? Functions::sanitizeFilterString($record['added_on'])  :  '';
                        $updated_on = isset($record['updated_on'])    ? Functions::sanitizeFilterString($record['updated_on']) :  '';
                        
                        $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 10',
                            ]);
                            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;
                        
  
                        $recordProgress = null;
                        switch($type) {
                            case CompanyMicrolearningUserProgress::TYPE_TOPIC  :
                                $recordProgress = $userProgressMapper->fetchOneByUserIdAndTopicId($user->id, $topic->id);
                                
                                break;
                                
                            case CompanyMicrolearningUserProgress::TYPE_CAPSULE  :
                                $recordProgress = $userProgressMapper->fetchOneByUseridAndCapsuleId($user->id, $capsule->id);
                                break;
                                
                            case CompanyMicrolearningUserProgress::TYPE_SLIDE  :
                                $recordProgress = $userProgressMapper->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;
                        } 
                        /*
                        else {
                            
                            if($recordProgress->updated_on > $updated_on) {
                                array_push($result_sync_ids, [
                                    'success' => true,
                                    'sync_id' => $sync_id,
                                ]);
                                continue;
                            }
                            
                            
                            
                        }*/
                        $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);
                                    }
                                }
                            }
          
                            $recordProgress->progress       = $progress;
                            $recordProgress->total_slides   = $total_slides;
                            $recordProgress->view_slides    = $view_slides;
                        }
                        else if($type == CompanyMicrolearningUserProgress::TYPE_CAPSULE ) {

                            $recordProgress->progress       = $progress;
                            $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 = $userProgressMapper->update($recordProgress);
                        } else {
                            $result = $userProgressMapper->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' => $userProgressMapper->getError()
                            ]);
                        }
                        continue;
                    }
                    
                    
                    
                    if($sync_type == 'microlearning-userlog') {
                        $activity   = isset($record['activity'])      ? Functions::sanitizeFilterString($record['activity'])  :  '';
                        $added_on   = isset($record['added_on'])      ? Functions::sanitizeFilterString($record['added_on'])  :  '';
                        
                        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 11',
                            ]);
                            continue;
                        }
                        
                        
                        
                        
                        $userLog = $userLogMapper->fetchLastBy($user->id);
                        if($userLog) {
                            $insert = $userLog->added_on <= $added_on;
                        } else {
                            $insert = true;
                        }
            
            
                        if($insert) {
                        
                            $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;
                            
                            
                            
                           
                            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()
                                ]);
                            }
                        } else {
                            array_push($result_sync_ids, [
                                'success' => true,
                                'sync_id' => $sync_id
                            ]);
                        }
                        continue;
                    }
                    
                }
                
                /***** FIN MICROLEARNING *****/
                
                
                /***** INICIO LOG DE USUARIO GENERAL *****/
                
                if($user_uuid && $sync_type == 'userlog' && $device->application_id = Application::TWOGETSKILLS) {
                    
                    
                    
                    if(isset($users[$user_uuid])) {
                        $user = $users[$user_uuid];
                    } else {
                        $user = $userMapper->fetchOneByUuid($user_uuid);
                        if($user) {
                            $users[$user_uuid] = $user;
                        }
                    }
                    
                    
                    
                    
                    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'])      ? Functions::sanitizeFilterString($record['activity'])  :  '';
                    $added_on   = isset($record['added_on'])      ? Functions::sanitizeFilterString($record['added_on'])  :  '';
                    
                    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 12',
                        ]);
                        continue;
                    }
                    
                    
                    $userLog = $userLogMapper->fetchLastBy($user->id);
                    if($userLog) {
                        $insert = $userLog->added_on <= $added_on;
                    } else {
                        $insert = true;
                    }
                    
                    
                    if($insert) {
                        $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()
                            ]);
                        }
                    } else {
                        array_push($result_sync_ids, [
                            'success' => true,
                            'sync_id' => $sync_id
                        ]);
                    }
                    
             
                    
                    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 13'
                ]);
            }
           
            
        }
        
        return new JsonModel([
            'success' => false,
            'data' => 'ERROR_METHOD_NOT_ALLOWED'
        ]);
    }
    
    public function deleteAccountAction()
    {
        $rawdata = file_get_contents("php://input");
        error_log('url = ' . $_SERVER['REQUEST_URI']);
        error_log('query = ' . $_SERVER['QUERY_STRING']);
        error_log('$rawdata = ' . $rawdata );

        
        $currentUserPlugin = $this->plugin('currentUserPlugin');
        $user = $currentUserPlugin->getUser();
        
        
        
        $request = $this->getRequest();
        
        if($request->isGet()) {
            
            $this->sendEmailDeleteAccountKey($user);
            
            
            return new JsonModel([
                'success' => true,
                'data' => [
                    'message' => 'LABEL_DELETE_ACCOUNT_WE_HAVE_SENT_A_CONFIRMATION_CODE'
                ]
            ]);
            
        } else  if($request->isPost()) {
            
            $code = $this->params()->fromPost('code');
            if(empty($code) || $code != $user->delete_account_key) {
                
                $this->sendEmailDeleteAccountKey($user);
                
                return new JsonModel([
                    'success' => false,
                    'data' => [
                        'message' => 'ERROR_DELETE_ACCOUNT_CONFIRMATION_CODE_IS_WRONG'
                    ]
                ]);
            }
            
            $delete_account_generated_on = strtotime($user->delete_account_generated_on);
            $expiry_time = $delete_account_generated_on + $this->config['leaderslinked.security.delete_account_expired'];
            
            
            if (time() > $expiry_time) {
                
                $this->sendEmailDeleteAccountKey($user) ;
                
                return new JsonModel([
                    'success' => false,
                    'data' => [
                        'message' => 'ERROR_DELETE_ACCOUNT_CONFIRMATION_CODE_EXPIRED'
                    ]
                ]);
                
                
            }
            
            $userDeleted  = new UserDeleted();
            $userDeleted->user_id = $user->id;
            $userDeleted->first_name = $user->first_name;
            $userDeleted->last_name = $user->last_name;
            $userDeleted->email = $user->email;
            $userDeleted->image = $user->image;
            $userDeleted->phone = $user->phone;
            $userDeleted->pending = UserDeleted::PENDING_YES;
            
            
            $userDeletedMapper = UserDeletedMapper::getInstance($this->adapter);
            if ($userDeletedMapper->insert($userDeleted)) {
                
                $this->sendEmailDeleteAccountCompleted($user);
                
                $user->first_name = 'LABEL_DELETE_ACCOUNT_FIRST_NAME';
                $user->last_name = 'LABEL_DELETE_ACCOUNT_LAST_NAME';
                $user->email = 'user-deleted-' . uniqid() . '@leaderslinked.com';
                $user->image = '';
                $user->usertype_id = UserType::USER_DELETED;
                $user->status = User::STATUS_DELETED;
                $user->delete_account_key = '';
                $user->delete_account_generated_on = '';
                
                $userMapper = UserMapper::getInstance($this->adapter);
                if($userMapper->update($user)) {
                    
                   
                    
                    return new JsonModel([
                        'success' => true,
                        'data' => [
                            'message' => 'LABEL_DELETE_ACCOUNT_WE_HAVE_STARTED_DELETING_YOUR_DATA',
                        ]
                    ]);
                    
                    
                } else {
                    return new JsonModel([
                        'success' => false,
                        'data' => [
                            'message' => $userDeletedMapper->getError()
                        ]
                    ]);
                }
                
                
                
            } else {
                return new JsonModel([
                    'success' => false,
                    'data' => [
                        'message' => $userDeletedMapper->getError()
                    ]
                ]);
            }
            
            
            
            
            
        }
            
            
            return new JsonModel([
                'success' => false,
                'data' => 'ERROR_METHOD_NOT_ALLOWED'
            ]);
    }
    
    
    private function sendEmailDeleteAccountKey($user) 
    {
        $delete_account_key = Functions::generatePassword(8);
        
        $userMapper = UserMapper::getInstance($this->adapter);
        $userMapper->updateDeleteAccountKey($user->id, $delete_account_key);
        
        $emailTemplateMapper = EmailTemplateMapper::getInstance($this->adapter);
        $emailTemplate = $emailTemplateMapper->fetchOneByCodeAndNetworkId(EmailTemplate::CODE_DELETE_ACCOUNT_CODE, $user->network_id);
        if($emailTemplate) {
            $arrayCont = [
                'firstname' => $user->first_name,
                'lastname'  => $user->last_name,
                'code'      => $delete_account_key,
                'link'      => ''
            ];
            
            $email = new QueueEmail($this->adapter);
            $email->processEmailTemplate($emailTemplate, $arrayCont, $user->email, trim($user->first_name . ' ' . $user->last_name));
        }
    }
    
    
    private function sendEmailDeleteAccountCompleted($user)
    {

        $emailTemplateMapper = EmailTemplateMapper::getInstance($this->adapter);
        $emailTemplate = $emailTemplateMapper->fetchOneByCodeAndNetworkId(EmailTemplate::CODE_DELETE_ACCOUNT_COMPLETED, $user->network_id);
        if($emailTemplate) {
            $arrayCont = [
                'firstname' => $user->first_name,
                'lastname'  => $user->last_name,
                'code'      => '',
                'link'      => ''
            ];
            
            $email = new QueueEmail($this->adapter);
            $email->processEmailTemplate($emailTemplate, $arrayCont, $user->email, trim($user->first_name . ' ' . $user->last_name));
        }
    }
    
    
    /**
     * 
     * @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'   => [],
            'extended'  => [],
        ];
        
        
        $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);
            $records = $userLogMapper->fetchAllByUserId($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                = [];
        
        
        $capsuleCommentMapper = CompanyMicrolearningCapsuleCommentMapper::getInstance($this->adapter);
        $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;
                        }
                        
                       
                        $dtAddedOn = \DateTime::createFromFormat('Y-m-d H:i:s', $slide->added_on);
                        $dtUpdatedOn = \DateTime::createFromFormat('Y-m-d H:i:s', $slide->updated_on);
                        
                        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]) : '',
                            'added_on'  => $dtAddedOn->format($serviceDatetimeFormat),
                            'updated_on'    => $dtUpdatedOn->format($serviceDatetimeFormat),
                        ]);
                    }
                    
                    $dtAddedOn = \DateTime::createFromFormat('Y-m-d H:i:s', $capsule->added_on);
                    $dtUpdatedOn = \DateTime::createFromFormat('Y-m-d H:i:s', $capsule->updated_on);
                    
                    $dataCountrAndRatingAverage = $capsuleCommentMapper->fetchCountAndRatingAverage($capsule->company_id, $capsule->topic_id, $capsule->id);
                    
                    
                    
                    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,
                        'link_comments' => $this->url()->fromRoute('services/microlearning/capsules/comments', ['capsule_id' => $capsule->uuid], ['force_canonical' => true]),
                        'link_comment_add' => $this->url()->fromRoute('services/microlearning/capsules/comments/add', ['capsule_id' => $capsule->uuid],['force_canonical' => true]),
                        'total_comments' => strval($dataCountrAndRatingAverage['total_comments']),
                        'total_rating' => strval($dataCountrAndRatingAverage['total_rating']),
                        'added_on'  => $dtAddedOn->format($serviceDatetimeFormat),
                        'updated_on'    => $dtUpdatedOn->format($serviceDatetimeFormat),
                    ]);
                }
                
                $dtAddedOn = \DateTime::createFromFormat('Y-m-d H:i:s', $topic->added_on);
                $dtUpdatedOn = \DateTime::createFromFormat('Y-m-d H:i:s', $topic->updated_on);
                
                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,
                    'added_on'  => $dtAddedOn->format($serviceDatetimeFormat),
                    'updated_on'    => $dtUpdatedOn->format($serviceDatetimeFormat),
                    
                ]);
                
                
                
          
            }
        }
        

        
        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)
                {
                    
                    $dtAddedOn = \DateTime::createFromFormat('Y-m-d H:i:s', $answer->added_on);
                    $dtUpdatedOn = \DateTime::createFromFormat('Y-m-d H:i:s', $answer->updated_on);
                    
                    array_push($record_answers, [
                        'uuid' => $answer->uuid,
                        'text' => trim($answer->text),
                        'correct' => $answer->correct ? $answer->correct  : 0 ,
                        'points' => strval(intval($answer->points, 10)),
                        'added_on'  => $dtAddedOn->format($serviceDatetimeFormat),
                        'updated_on'    => $dtUpdatedOn->format($serviceDatetimeFormat),
                    ]);
                }
                
                $dtAddedOn = \DateTime::createFromFormat('Y-m-d H:i:s', $question->added_on);
                $dtUpdatedOn = \DateTime::createFromFormat('Y-m-d H:i:s', $question->updated_on);
                
                array_push($record_questions, [
                    'uuid'          => $question->uuid,
                    'text'          => trim($question->text),
                    'type'          => $question->type,
                    'maxlength'     => strval($question->maxlength),
                    'points'        => strval($question->points),
                    'answers'       => $record_answers,
                    'added_on'      => $dtAddedOn->format($serviceDatetimeFormat),
                    'updated_on'    => $dtUpdatedOn->format($serviceDatetimeFormat),
                ]);
            }
            
            $dtAddedOn = \DateTime::createFromFormat('Y-m-d H:i:s', $quiz->added_on);
            $dtUpdatedOn = \DateTime::createFromFormat('Y-m-d H:i:s', $quiz->updated_on);
            
            
            array_push($data['quizzes'], [
                'uuid' => $quiz->uuid,
                'name' => $quiz->name,
                'text' => trim($quiz->text ? $quiz->text : ''),
                'failed' => trim($quiz->failed ? $quiz->failed : ''),
                'points' => strval($quiz->points),
                'minimum_points_required' => strval($quiz->minimum_points_required),
                'max_time' => $quiz->max_time ? $quiz->max_time : 5,
                'company_uuid' => $company->uuid,
                'company_name' => $company->name,
                'company_image' => $this->url()->fromRoute('services/storage',['type' => 'company', 'code' => $company->uuid, 'filename' => $company->image], ['force_canonical' => true]),
                'questions'     => $record_questions,
                'added_on'      => $dtAddedOn->format($serviceDatetimeFormat),
                'updated_on'    => $dtUpdatedOn->format($serviceDatetimeFormat),
            ]);
        }
        
        $companyExtendUserMapper = CompanyMicrolearningExtendUserMapper::getInstance($this->adapter);
        $companyExtendUserCompanyMapper = CompanyMicrolearningExtendUserCompanyMapper::getInstance($this->adapter);
        $companyExtendUserFunctionMapper = CompanyMicrolearningExtendUserFunctionMapper::getInstance($this->adapter);
        $companyExtendUserGroupMapper = CompanyMicrolearningExtendUserGroupMapper::getInstance($this->adapter);
        $companyExtendUserInstitutionMapper = CompanyMicrolearningExtendUserInstitutionMapper::getInstance($this->adapter);
        $companyExtendUserPartnerMapper = CompanyMicrolearningExtendUserPartnerMapper::getInstance($this->adapter);
        $companyExtendUserProgramMapper = CompanyMicrolearningExtendUserProgramMapper::getInstance($this->adapter);
        $companyExtendUserStudentTypeMapper = CompanyMicrolearningExtendUserStudentTypeMapper::getInstance($this->adapter);
        $companyExtendUserSectorMapper = CompanyMicrolearningExtendUserSectorMapper::getInstance($this->adapter);

        $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;
            }
            
            if(!$company) {
                continue;
            }
            
            $record = [
                '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]),
                'details' => [],
            ];
            
            $companyExtendUser = $companyExtendUserMapper->fetchOneByCompanyIdAndUserId($company->id, $user->id);
            if(!$companyExtendUser) {
                continue;
            }
            
            if($companyExtendUser->extend_company_id) {
                
                $extendedCompany = $companyExtendUserCompanyMapper->fetchOne($companyExtendUser->company_id);
                if($extendedCompany) {
                    array_push($record['details'],[
                        'uuid' => $extendedCompany->uuid,
                        'label' => 'LABEL_COMPANY',
                        'value' => $extendedCompany->name
                    ]);    
                }
            }
            
            if($companyExtendUser->extend_function_id) {
                $extendedFunction = $companyExtendUserFunctionMapper->fetchOne($companyExtendUser->extend_function_id);
                if($extendedFunction) {
                    array_push($record['details'],[
                        'uuid' => $extendedFunction->uuid,
                        'label' => 'LABEL_FUNCTION',
                        'value' => $extendedFunction->name
                    ]);
                }
            }
            
            if($companyExtendUser->extend_group_id) {
                $extendedGroup = $companyExtendUserGroupMapper->fetchOne($companyExtendUser->extend_group_id);
                if($extendedGroup) {
                    array_push($record['details'],[
                        'uuid' => $extendedGroup->uuid,
                        'label' => 'LABEL_GROUP',
                        'value' => $extendedGroup->name
                    ]);
                }
            }
            
            if($companyExtendUser->extend_institution_id) {
                $extendedInstitution= $companyExtendUserInstitutionMapper->fetchOne($companyExtendUser->extend_institution_id);
                if($extendedInstitution) {
                    array_push($record['details'],[
                        'uuid' => $extendedInstitution->uuid,
                        'label' => 'LABEL_INSTITUTION',
                        'value' => $extendedInstitution->name
                    ]);
                }
            }
            
            if($companyExtendUser->extend_program_id) {
                $extendedProgram = $companyExtendUserProgramMapper->fetchOne($companyExtendUser->extend_program_id);
                if($extendedProgram) {
                    array_push($record['details'],[
                        'uuid' => $extendedProgram->uuid,
                        'label' => 'LABEL_PROGRAM',
                        'value' => $extendedProgram->name
                    ]);

                }
            }
            
            if($companyExtendUser->extend_sector_id) {
                $extendedSector = $companyExtendUserSectorMapper->fetchOne($companyExtendUser->extend_sector_id);
                if($extendedSector) {
                    array_push($record['details'],[
                        'uuid' => $extendedSector->uuid,
                        'label' => 'LABEL_SECTOR',
                        'value' => $extendedSector->name
                    ]);
                }
            }
            
            if($companyExtendUser->extend_partner_id) {
                $extendedPartner = $companyExtendUserPartnerMapper->fetchOne($companyExtendUser->extend_partner_id);
                if($extendedPartner) {
                    array_push($record['details'],[
                        'uuid' => $extendedPartner->uuid,
                        'label' => 'LABEL_PARTNER',
                        'value' => $extendedPartner->name
                    ]);
                }
            }
            
            if($companyExtendUser->extend_student_type_id) {
                $extendedStudentType = $companyExtendUserStudentTypeMapper->fetchOne($companyExtendUser->extend_student_type_id);
                if($extendedStudentType) {
                    array_push($record['details'],[
                        'uuid' => $extendedStudentType->uuid,
                        'label' => 'LABEL_TYPE',
                        'value' => $extendedStudentType->name
                    ]);
                }
            }
            
            array_push($data['extended'], $record);
        }
        
        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;
    }
}