Rev 3099 | Rev 3648 | Ir a la última revisión | Autoría | Comparar con el anterior | Ultima modificación | Ver Log |
<?php/**** Controlador: Mis Perfiles**/declare(strict_types=1);namespace LeadersLinked\Controller;use Laminas\Db\Adapter\AdapterInterface;use Laminas\Cache\Storage\Adapter\AbstractAdapter;use Laminas\Mvc\Controller\AbstractActionController;use Laminas\Log\LoggerInterface;use Laminas\View\Model\ViewModel;use LeadersLinked\Library\Functions;use LeadersLinked\Mapper\UserMapper;use LeadersLinked\Model\User;use LeadersLinked\Mapper\UserBlockedMapper;use LeadersLinked\Mapper\CompanyMapper;use LeadersLinked\Mapper\CompanyUserMapper;use LeadersLinked\Mapper\ConversationMapper;use LeadersLinked\Mapper\MessageMapper;use LeadersLinked\Model\Conversation;use LeadersLinked\Model\UserType;use LeadersLinked\Library\Image;use Laminas\View\Model\JsonModel;use LeadersLinked\Form\InMail\SendForm;use LeadersLinked\Model\Message;use LeadersLinked\Model\VideoConvert;use LeadersLinked\Mapper\VideoConvertMapper;use LeadersLinked\Mapper\UtilMapper;class InMailController extends AbstractActionController{/**** @var AdapterInterface*/private $adapter;/**** @var AbstractAdapter*/private $cache;/**** @var LoggerInterface*/private $logger;/**** @var array*/private $config;/**** @param AdapterInterface $adapter* @param AbstractAdapter $cache* @param LoggerInterface $logger* @param array $config*/public function __construct($adapter, $cache , $logger, $config){$this->adapter = $adapter;$this->cache = $cache;$this->logger = $logger;$this->config = $config;}/**** Generación del listado de conversationes** [* success: true,* data:[* [* uuid: uuid con quien se tiene la conversación,* name: nombre de con quien se tiene la conversacion,* image: imagen de con quien se tiene la conversación,* profile: url del profile con quien se tiene la conversación,* last_message: fecha del ultimo mensaje,* count_unread: cantidad de mensajes sin leer,* messages_link: url para recuperar los mensajes,* send_link: url para enviar el mensaje,* selected: 0 = no seleccionado, 1 = seleccionado* ]* ]*** @return \Laminas\View\Model\JsonModel*/public function indexAction(){$request = $this->getRequest();if($request->isGet()) {$currentUserPlugin = $this->plugin('currentUserPlugin');$currentUser = $currentUserPlugin->getUser();$id = $this->params()->fromRoute('id');$headers = $request->getHeaders();$isJson = false;if($headers->has('Accept')) {$accept = $headers->get('Accept');$prioritized = $accept->getPrioritized();foreach($prioritized as $key => $value) {$raw = trim($value->getRaw());if(!$isJson) {$isJson = strpos($raw, 'json');}}}if($isJson) {$utilMapper = UtilMapper::getInstance($this->adapter);$now = $utilMapper->getDatebaseNow();$currentUserPlugin = $this->plugin('currentUserPlugin');$currentUser = $currentUserPlugin->getUser();$userMapper = UserMapper::getInstance($this->adapter);$conversationMapper = ConversationMapper::getInstance($this->adapter);$messageMapper = MessageMapper::getInstance($this->adapter);$conversations = [];$selected_user_id = 0;$id = $this->params()->fromRoute('id');if($id) {$companyMapper = CompanyMapper::getInstance($this->adapter);$company = $companyMapper->fetchOneByUuid($id);if($company) {$companyUserMapper = CompanyUserMapper::getInstance($this->adapter);$companyUser = $companyUserMapper->fetchOwnerByCompanyId($company->id);$user = $userMapper->fetchOne($companyUser->user_id);$selected_user_id = $user->id;$conversation = $conversationMapper->fetchOneByUserId1AndUserId2($currentUser->id, $user->id);$timeElapsedString = '';if($conversation) {$unread = $messageMapper->fetchCountUnreadMessagesByConversationIdAndReceiverId($conversation->id, $currentUser->id);$lastMessage = $messageMapper->fetchLastUnreadMessagesByConversationIdAndReceiverId($conversation->id, $currentUser->id);if($lastMessage) {$timeElapsedString = $this->timeAgo($lastMessage, $now);}} else {$unread = 0;}array_push($conversations, ['uuid' => $company->uuid,'name' => $company->name,'image' => $this->url()->fromRoute('storage', ['type' => 'company', 'code' => $company->uuid, 'filename' => $company->image]),'profile' => $this->url()->fromRoute('company/view', ['id' => $company->uuid ] ),'last_message' => $timeElapsedString,'count_unread' => $unread,'messages_link' => $this->url()->fromRoute('inmail/message', ['id' => $user->uuid]),'send_link' => $this->url()->fromRoute('inmail/message/send', ['id' => $user->uuid]),'selected' => 1,]);} else {$user = $userMapper->fetchOneByUuid($id);if($user) {$timeElapsedString = '';$selected_user_id = $user->id;$conversation = $conversationMapper->fetchOneByUserId1AndUserId2($currentUser->id, $user->id);if($conversation) {$unread = $messageMapper->fetchCountUnreadMessagesByConversationIdAndReceiverId($conversation->id, $currentUser->id);$lastMessage = $messageMapper->fetchLastUnreadMessagesByConversationIdAndReceiverId($conversation->id, $currentUser->id);if($lastMessage) {$timeElapsedString = $this->timeAgo($lastMessage, $now);}} else {$unread = 0;}array_push($conversations, ['uuid' => $user->uuid,'name' => trim($user->first_name . ' ' . $user->last_name),'image' => $this->url()->fromRoute('storage', ['type' => 'user', 'code' => $user->uuid, 'filename' => $user->image]),'profile' => $this->url()->fromRoute('profile/view', ['id' => $user->uuid]),'last_message' => $timeElapsedString,'count_unread' => $unread,'messages_link' => $this->url()->fromRoute('inmail/message', ['id' => $user->uuid]),'send_link' => $this->url()->fromRoute('inmail/message/send', ['id' => $user->uuid]),'selected' => 1,]);}}}$records = $conversationMapper->fetchAllByUserId($currentUser->id);foreach($records as $record){if($selected_user_id) {if($record->sender_id == $currentUser->id && $record->receiver_id == $selected_user_id) {continue;}if($record->receiver_id == $currentUser->id && $record->sender_id == $selected_user_id) {continue;}}if($record->sender_id == $currentUser->id) {$user = $userMapper->fetchOne($record->receiver_id);}if($record->receiver_id == $currentUser->id) {$user = $userMapper->fetchOne($record->sender_id);}$timeElapsedString = '';$unread = $messageMapper->fetchCountUnreadMessagesByConversationIdAndReceiverId($record->id, $currentUser->id);$lastMessage = $messageMapper->fetchLastMessagesByConversationIdAndReceiverId($record->id, $currentUser->id);if($lastMessage) {$timeElapsedString = $this->timeAgo($lastMessage, $now);}array_push($conversations, ['uuid' => $user->uuid,'name' => trim($user->first_name . ' ' . $user->last_name),'image' => $this->url()->fromRoute('storage', ['type' => 'user', 'code' => $user->uuid, 'filename' => $user->image]),'profile' => $this->url()->fromRoute('profile/view', ['id' => $user->uuid]),'last_message' => $timeElapsedString,'count_unread' => $unread,'messages_link' => $this->url()->fromRoute('inmail/message', ['id' => $user->uuid]),'send_link' => $this->url()->fromRoute('inmail/message/send', ['id' => $user->uuid]),'selected' => 0,]);}usort($conversations, function($a, $b) {if ($a['selected'] == $b['selected']) {if($a['last_message'] == $b['last_message']) {return 0;} else {return $a['last_message'] < $b['last_message'] ? -1 : 1;}} else {return $a['selected'] < $b['selected'] ? -1 : 1;}});return new JsonModel(['success' => true,'data' => $conversations]);} else {$this->layout()->setTemplate('layout/layout.phtml');$viewModel = new ViewModel();$viewModel->setTemplate('leaders-linked/inmail/index.phtml');return $viewModel ;}} else {return new JsonModel(['success' => false,'data' => 'ERROR_METHOD_NOT_ALLOWED']);}}/*** Esta función remueve el usuario del grupo* Es una petición GET el url recuperado en /inmail* [ruta del servidor]/inmail/[uuid]/message* retorna un json en caso de ser positivo* [* success: true,* data: [* [* sender_name: nombre de quien que envia el mensaje,* sender_image: imagen de quien que recibe el mensaje,* sender_profile: url de profile de quien que envia el mensaje,* receiver_name: nombre de quien que recibe el mensaje,* receiver_image: url de la imagen de quien que recibe el mensaje,* receiver_profile: url del profile de quien recibe el mensaje,* side: left/righ de que lado de la pantalla se mostrara,* message: texto del mensaje,* type: text|image|video|document,* filename: url del archivo enviado,* date: cadena que describe hace cuanto se recibio el mensaje* ]* ]* ]* En caso de ser negativo puede haber 2 formatos* [* 'success' : false,* 'data' : mensaje de error* ]* @return \Laminas\View\Model\JsonModel*/public function messageAction(){$request = $this->getRequest();if($request->isGet()) {$utilMapper = UtilMapper::getInstance($this->adapter);$now = $utilMapper->getDatebaseNow();$page = intval($this->params()->fromQuery('page', 0), 10);$currentUserPlugin = $this->plugin('currentUserPlugin');$currentUser = $currentUserPlugin->getUser();$userMapper = UserMapper::getInstance($this->adapter);$conversationMapper = ConversationMapper::getInstance($this->adapter);$messageMapper = MessageMapper::getInstance($this->adapter);$id = $this->params()->fromRoute('id');if(!$id) {return new JsonModel(['success' => false,'data' => 'ERROR_PARAMETERS_ARE_INVALID']);}$user = $userMapper->fetchOneByUuid($id);if(!$user) {return new JsonModel(['success' => false,'data' => 'ERROR_REQUEST_IS_INVALID']);}$conversationMapper = ConversationMapper::getInstance($this->adapter);$conversation = $conversationMapper->fetchOneByUserId1AndUserId2($currentUser->id, $user->id);$messages = [];if($conversation) {$records = $messageMapper->getAllMessagesPaginatorByConversationId($conversation->id, $page);foreach($records as $record) {$timeElapsedString = $this->timeAgo($record->added_on, $now);if($record->sender_id == $currentUser->id) {array_push($messages, ['sender_name' => trim($currentUser->first_name . ' ' . $currentUser->last_name),'sender_image' => $this->url()->fromRoute('storage', ['type' => 'user', 'filename' => $currentUser->image, 'code' => $currentUser->uuid]),'sender_profile' => $this->url()->fromRoute('profile/view', ['id' => $currentUser->uuid]),'receiver_name' => trim($user->first_name . ' ' . $user->last_name),'receiver_image' => $this->url()->fromRoute('storage', ['type' => 'user', 'filename' => $user->image, 'code' => $user->uuid]),'receiver_profile' => $this->url()->fromRoute('profile/view', ['id' => $user->uuid]),'side' => 'left','message' => $record->message,'type' => $record->type,'filename' => $record->filename ? $this->url()->fromRoute('storage', ['type' => 'message', 'filename' => $record->filename, 'code' => $record->uuid]) : '','date' => $timeElapsedString]);} else {array_push($messages, ['sender_name' => trim($user->first_name . ' ' . $user->last_name),'sender_image' => $this->url()->fromRoute('storage', ['type' => 'user', 'filename' => $user->image, 'code' => $user->uuid]),'sender_profile' => $this->url()->fromRoute('profile/view', ['id' => $user->uuid]),'receiver_name' => trim($currentUser->first_name . ' ' . $currentUser->last_name),'receiver_image' => $this->url()->fromRoute('storage', ['type' => 'user', 'filename' => $currentUser->image, 'code' => $user->uuid]),'receiver_profile' => $this->url()->fromRoute('profile/view', ['id' => $currentUser->uuid]),'side' => 'right','message' => $record->message,'type' => $record->type,'filename' => $record->filename ? $this->url()->fromRoute('storage', ['type' => 'message', 'filename' => $record->filename, 'code' => $record->uuid]) : '','date' => $timeElapsedString]);$messageMapper->markAsRead($record->id);}}return new JsonModel(['success' => true,'data' => $messages,'pagination' => $records->getPages()]);}return new JsonModel(['success' => false,'data' => $messages]);} else {return new JsonModel(['success' => false,'data' => 'ERROR_METHOD_NOT_ALLOWED']);}}/*** Esta función envia un mensaje* Es una petición POST el url recuperado en /inmail* [ruta del servidor]/inmail/[uidd del usuario]/message/send* Lo párametros son* message: text plain requerido* file: no requerido puede jpg, png, jpeg, mp3, mp4, webm o pdf* o* [ruta del servidor]/inmail/[uidd del usuario]/message/send/encoding/base64 para el caso de react-native* Los párametros son* message: text plain requerido* fileBase64Name: nombre del archivo que se envia en base64 solo requerido si se envia un archivo* fileBase64Content: contenido en base 64 del archivo** retorna un json en caso de ser positivo* [* success: true,* data:{* sender_name: nombre de quien que envia el mensaje,* sender_image: imagen de quien que recibe el mensaje,* sender_profile: url de profile de quien que envia el mensaje,* receiver_name: nombre de quien que recibe el mensaje,* receiver_image: url de la imagen de quien que recibe el mensaje,* receiver_profile: url del profile de quien recibe el mensaje,* side: left/righ de que lado de la pantalla se mostrara,* message: texto del mensaje,* type: text|image|video|document,* filename: url del archivo enviado,* date: cadena que describe hace cuanto se recibio el mensaje* ]* ]* En caso de ser negativo puede haber 2 formatos* [* 'success' : false,* 'data' : mensaje de error* ]* @return \Laminas\View\Model\JsonModel*/public function sendMessageAction(){$request = $this->getRequest();if($request->isPost()) {$utilMapper = UtilMapper::getInstance($this->adapter);$now = $utilMapper->getDatebaseNow();$currentUserPlugin = $this->plugin('currentUserPlugin');$currentUser = $currentUserPlugin->getUser();$userMapper = UserMapper::getInstance($this->adapter);$id = $this->params()->fromRoute('id');if(!$id) {return new JsonModel(['success' => false,'data' => 'ERROR_PARAMETERS_ARE_INVALID']);}$user = $userMapper->fetchOneByUuid($id);if(!$user) {return new JsonModel(['success' => false,'data' => 'ERROR_REQUEST_IS_INVALID']);}$data = array_merge($request->getPost()->toArray(), $request->getFiles()->toArray());$form = new SendForm();$form->setData($data);if($form->isValid()) {$dataPost = (array) $form->getData();$conversationMapper = ConversationMapper::getInstance($this->adapter);$conversation = $conversationMapper->fetchOneByUserId1AndUserId2($currentUser->id, $user->id);if($conversation) {$conversation->receiver_status = Conversation::STATUS_NORMAL;$conversation->sender_status = Conversation::STATUS_NORMAL;if(!$conversationMapper->update($conversation)) {return new JsonModel(['success' => false,'data' => $conversationMapper->getError()]);}} else {$conversation = new Conversation();$conversation->sender_id = $currentUser->id;$conversation->sender_status = Conversation::STATUS_NORMAL;$conversation->receiver_id = $user->id;$conversation->receiver_status = Conversation::STATUS_NORMAL;if(!$conversationMapper->insert($conversation)) {return new JsonModel(['success' => false,'data' => $conversationMapper->getError()]);}}$files = $this->getRequest()->getFiles()->toArray();$type = Message::TYPE_TEXT;/*$encoding = $this->params()->fromRoute('encoding');if($encoding == 'base64') {$fileBase64Name = $this->params()->fromPost('file_base64_name');$fileBase64Content = $this->params()->fromPost('file_base64_content');if($fileBase64Name && $fileBase64Content) {try {$fileBase64Content = base64_decode($fileBase64Content);if($fileBase64Content) {$message_filename = $this->normalizeString($fileBase64Name);$message_tmp_filename = 'data' . DIRECTORY_SEPARATOR . 'tmp';if(!file_exists($message_tmp_filename)) {mkdir($message_tmp_filename, 0755, true);}$message_tmp_filename = 'data' . DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR . $message_filename;file_put_contents($message_tmp_filename, $fileBase64Content);$mime_type = mime_content_type($message_tmp_filename);//echo '$mime_type = '. $mime_type; exit;if($mime_type == 'image/jpg' || $mime_type == 'image/jpeg' || $mime_type == 'image/png') {$type = Message::TYPE_IMAGE;} else if($mime_type == 'video/webm' || $mime_type == 'video/mpeg' || $mime_type == 'video/mpg' || $mime_type == 'video/mp4') {$type = Message::FILE_TYPE_VIDEO;} else if($mime_type == 'application/pdf') {$type = Message::FILE_TYPE_DOCUMENT;}}} catch(\Exception $e) {}}} else {}*/if(isset($files['filename']) && empty($files['filename']['error'])) {$message_tmp_filename = $files['filename']['tmp_name'];$message_filename = $this->normalizeString($files['filename']['name']);$mime_type = mime_content_type($message_tmp_filename);if($mime_type == 'image/jpg' || $mime_type == 'image/jpeg' || $mime_type == 'image/png') {$type = Message::TYPE_IMAGE;} else if($mime_type == 'video/webm' || $mime_type == 'video/mpeg' || $mime_type == 'video/mpg' || $mime_type == 'video/mp4') {$type = Message::TYPE_VIDEO;} else if($mime_type == 'application/pdf') {$type = Message::TYPE_DOCUMENT;}}$message = new Message();$message->conversation_id = $conversation->id;$message->read = Message::NO;$message->message = $type == Message::TYPE_TEXT ? $dataPost['message'] : '';$message->receiver_id = $user->id;$message->receiver_status = Message::STATUS_NORMAL;$message->sender_id = $currentUser->id;$message->sender_status = Message::STATUS_NORMAL;$message->type = $type;$messageMapper = MessageMapper::getInstance($this->adapter);if($messageMapper->insert($message)) {$message = $messageMapper->fetchOne($message->id);if( $type == Message::TYPE_DOCUMENT) {try {$target_path = $this->config['leaderslinked.fullpath.message'] . $message->uuid;if(!file_exists($target_path)) {mkdir($target_path, 0755);}$full_filename = $target_path . DIRECTORY_SEPARATOR .$message_filename;/*if($encoding == 'base64') {$resultMoveOrRename = rename($message_tmp_filename , $full_filename);} else {$resultMoveOrRename = move_uploaded_file($message_tmp_filename , $full_filename);}*/$resultMoveOrRename = move_uploaded_file($message_tmp_filename , $full_filename);if($resultMoveOrRename) {$message->type = $type;$message->filename = basename($message_filename);$messageMapper->update($message);} else {error_log('no se pudo mover o renombrar el documento : ' . $message_tmp_filename . ' al directorio : ' . $full_filename );}} catch(\Throwable $e) {error_log($e->getTraceAsString());}}if( $type == Message::TYPE_IMAGE) {try {$target_path = $this->config['leaderslinked.fullpath.message'] . $message->uuid;if(!file_exists($target_path)) {mkdir($target_path, 0755);}list($target_width, $target_height) = explode('x', $this->config['leaderslinked.image_sizes.message_image_size']);$message_filename = substr($message_filename, 0, strrpos($message_filename, '.')) . '.png';//echo "target_path = $target_path message_tmp_filename = $message_tmp_filename message_filename = $message_filename"; exit;$crop_to_dimensions = false;if(Image::uploadImage($message_tmp_filename, $target_path, $message_filename, $target_width, $target_height, $crop_to_dimensions )) {$message->type = $type;$message->filename = basename($message_filename);$messageMapper->update($message);}} catch(\Throwable $e) {error_log($e->getTraceAsString());}}if( $type == Message::TYPE_VIDEO) {try {$target_path = $this->config['leaderslinked.fullpath.message'] . $message->uuid;if(!file_exists($target_path)) {mkdir($target_path, 0755);}$full_filename = $target_path . DIRECTORY_SEPARATOR . $message_filename;/*if($encoding == 'base64') {$resultMoveOrRename = rename($message_tmp_filename , $full_filename);} else {$resultMoveOrRename = move_uploaded_file($message_tmp_filename , $full_filename);}*/$resultMoveOrRename = move_uploaded_file($message_tmp_filename , $full_filename);if($resultMoveOrRename) {$size = $this->config['leaderslinked.image_sizes.message_image_size'];$getFromSecound = 2;//extracción del cover$generateFileName = substr($message_filename, 0, strrpos($message_filename, '.'));$generateFile = $target_path . DIRECTORY_SEPARATOR . $generateFileName . '.png';$cmd = "/usr/bin/ffmpeg -i $full_filename -an -ss $getFromSecound -s $size $generateFile";exec($cmd);$message->type = $type;$message->filename = basename($message_filename);$message->image_preview = basename($generateFile);$messageMapper->update($message);$videoConvert = new VideoConvert();$videoConvert->filename = $full_filename;$videoConvert->type = VideoConvert::TYPE_FEED;$videoConvertMapper = VideoConvertMapper::getInstance($this->adapter);$videoConvertMapper->insert($videoConvert);} else {error_log('no se pudo mover o renombrar el documento : ' . $message_tmp_filename . ' al directorio : ' . $full_filename );}} catch(\Throwable $e) {error_log($e->getTraceAsString());}}$message = $messageMapper->fetchOne($message->id);if($message->filename) {$filename = $this->url()->fromRoute('storage', ['type' => 'message', 'filename' => $message->filename, 'code' => $message->uuid]);} else {$filename = '';}$dt = \DateTime::createFromFormat('Y-m-d H:i:s', $message->added_on);$userMapper->updateLastActivity($currentUser->id);return new JsonModel(['success' => true,'data' => ['sender_name' => trim($currentUser->first_name . ' ' . $currentUser->last_name),'sender_image' => $this->url()->fromRoute('storage', ['type' => 'user', 'filename' => $currentUser->image, 'code' => $currentUser->uuid]),'sender_profile' => $this->url()->fromRoute('profile/view', ['id' => $currentUser->uuid]),'receiver_name' => trim($user->first_name . ' ' . $user->last_name),'receiver_image' => $this->url()->fromRoute('storage', ['type' => 'user', 'filename' => $user->image, 'code' => $user->uuid]),'receiver_profile' => $this->url()->fromRoute('profile/view', ['id' => $user->uuid]),'side' => 'left','message' => $message->message,'type' => $message->type,'filename' => $filename,'date' => $this->timeAgo($now, $now),]]);} else {return new JsonModel(['success' => false,'data' => $messageMapper->getError()]);}} else {$messages = [];$form_messages = (array) $form->getMessages();foreach($form_messages as $fieldname => $field_messages){$messages[$fieldname] = array_values($field_messages);}return new JsonModel(['success' => false,'data' => $messages]);}} else {return new JsonModel(['success' => false,'data' => 'ERROR_METHOD_NOT_ALLOWED']);}}private function normalizeString ($str = ''){$basename = substr($str, 0, strrpos($str, '.'));$basename = str_replace('.', '-', $basename);$extension = substr($str, strrpos($str, '.'));$str = $basename . $extension;$str = strip_tags($str);$str = preg_replace('/[\r\n\t ]+/', ' ', $str);$str = preg_replace('/[\"\*\/\:\<\>\?\'\|\,]+/', ' ', $str);$str = strtolower($str);$str = html_entity_decode( $str, ENT_QUOTES, "utf-8" );$str = htmlentities($str, ENT_QUOTES, "utf-8");$str = preg_replace("/(&)([a-z])([a-z]+;)/i", '$2', $str);$str = str_replace(' ', '-', $str);$str = rawurlencode($str);$str = str_replace('%', '-', $str);return trim(strtolower($str));}/**** @param string $timestamp* @param string $now* @return string*/private function timeAgo($timestamp, $now = ''){if($now) {$datetime1 = \DateTime::createFromFormat('Y-m-d H:i:s', $now);} else {$now = date('Y-m-d H:i:s');$datetime1 = date_create($now);}$datetime2 = date_create($timestamp);$diff = date_diff($datetime1, $datetime2);$timemsg = '';if ($diff->y > 0) {$timemsg = $diff->y . ' año' . ($diff->y > 1 ? "s" : '');} else if ($diff->m > 0) {$timemsg = $diff->m . ' mes' . ($diff->m > 1 ? "es" : '');} else if ($diff->d > 0) {$timemsg = $diff->d . ' dia' . ($diff->d > 1 ? "s" : '');} else if ($diff->h > 0) {$timemsg = $diff->h . ' hora' . ($diff->h > 1 ? "s" : '');} else if ($diff->i > 0) {$timemsg = $diff->i . ' minuto' . ($diff->i > 1 ? "s" : '');} else if ($diff->s > 0) {$timemsg = $diff->s . ' segundo' . ($diff->s > 1 ? "s" : '');}if (!$timemsg) {$timemsg = "Ahora";} else {$timemsg = $timemsg . '';}return $timemsg;}}