Eye4web/Eye4webZfcUserPm

View on GitHub
src/Eye4web/ZfcUser/Pm/Service/PmService.php

Summary

Maintainability
C
1 day
Test Coverage
<?php
/*
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * This software consists of voluntary contributions made by many individuals
 * and is licensed under the MIT license.
 */

namespace Eye4web\ZfcUser\Pm\Service;

use Eye4web\ZfcUser\Pm\Mapper\PmMapperInterface;
use Eye4web\ZfcUser\Pm\Entity\ConversationInterface;
use Eye4web\ZfcUser\Pm\Entity\ConversationReceiverInterface;
use Eye4web\ZfcUser\Pm\Entity\MessageInterface;
use Eye4web\ZfcUser\Pm\Options\ModuleOptionsInterface;
use ZfcUser\Entity\UserInterface;
use Zend\EventManager\EventManagerAwareInterface;
use Zend\EventManager\EventManagerAwareTrait;

class PmService implements PmServiceInterface, EventManagerAwareInterface
{
    use EventManagerAwareTrait;

    /**
     * @var PmMapperInterface
     */
    protected $pmMapper;

    /**
     * @var ModuleOptionsInterface
     */
    protected $options;

    /**
     * @var string
     */
    protected $conversationEntity;

    /**
     * @var string
     */
    protected $conversationReceiverEntity;

    /**
     * @var string
     */
    protected $messageEntity;

    /**
     * @param PmMapperInterface $pmMapper
     */
    public function __construct(PmMapperInterface $pmMapper, ModuleOptionsInterface $options)
    {
        $this->pmMapper = $pmMapper;
        $this->options = $options;
    }

    /**
     * @param  string $userId
     * @return ConversationInterface[]
     */
    public function getUserConversations($userId)
    {
        $userReceives = $this->pmMapper->getUserReceives($userId);

        $conversations = [];
        foreach ($userReceives as $receive) {
            $conversations[] = $receive->getConversation();
        }

        $this->getEventManager()->trigger(
            'getUserConversations',
            $this,
            [
            'conversations' => $conversations
            ]
        );

        return $conversations;
    }

    /**
     * @param  array         $conversationsIds
     * @param  UserInterface $user
     * @return void
     */
    public function deleteConversations(array $conversationsIds, UserInterface $user)
    {
        $this->getEventManager()->trigger(
            'deleteConversations.pre',
            $this,
            [
            'conversationsIds' => $conversationsIds,
            'user' => $user
            ]
        );

        foreach ($conversationsIds as $conversationsId) {
            $this->pmMapper->deleteConversation($conversationsId, $user);
        }


    }

    /**
     * @param  ConversationInterface $conversation
     * @return MessageInterface[]
     */
    public function getMessages(ConversationInterface $conversation)
    {
        $messages = $this->pmMapper->getMessages($conversation);

        $this->getEventManager()->trigger(
            'getMessages',
            $this,
            [
            'messages' => $messages
            ]
        );

        return $messages;
    }

    /**
     * @param  ConversationInterface $conversation
     * @param  UserInterface         $user
     * @return mixed|void
     */
    public function markRead(ConversationInterface $conversation, UserInterface $user)
    {
        $this->getEventManager()->trigger(
            'markRead.pre',
            $this,
            [
            'conversation' => $conversation,
            'user' => $user
            ]
        );

        $this->pmMapper->markRead($conversation, $user);
    }

    /**
     * @return array|UserInterface[]
     */
    public function getUsers()
    {
        $dbUsers = $this->pmMapper->getUsers();
        $users = [];
        foreach ($dbUsers as $user) {
            $users[] = [
                'id' => $user->getId(),
                'text' => $user->getDisplayName(),
            ];
        }

        $this->getEventManager()->trigger(
            'getUsers',
            $this,
            [
            'users' => $users
            ]
        );

        return $users;
    }

    /**
     * @param  string $conversationId
     * @return ConversationInterface
     */
    public function getConversation($conversationId)
    {
        $conversation = $this->pmMapper->getConversation($conversationId);

        $this->getEventManager()->trigger(
            'getConversation',
            $this,
            [
            'conversation' => $conversation
            ]
        );

        return $conversation;
    }

    /**
     * @param  ConversationInterface $conversation
     * @return UserInterface[]
     */
    public function getParticipants(ConversationInterface $conversation)
    {
        $receivers = $this->pmMapper->getReceiversByConversation($conversation);

        $participants = [];
        foreach ($receivers as $receiver) {
            $participants[] = $this->pmMapper->getUser($receiver->getTo());
        }

        $this->getEventManager()->trigger(
            'getParticipants',
            $this,
            [
            'participants' => $participants
            ]
        );

        return $participants;
    }

    /**
     * @param  ConversationInterface $conversation
     * @param  UserInterface         $user
     * @return bool
     */
    public function isUnread(ConversationInterface $conversation, UserInterface $user)
    {
        $this->getEventManager()->trigger(
            'isUnread.pre',
            $this,
            [
            'conversation' => $conversation,
            'user' => $user
            ]
        );

        $isUnread = $this->pmMapper->isUnread($conversation, $user);

        $this->getEventManager()->trigger(
            'isUnread',
            $this,
            [
            'isUnread' => $isUnread
            ]
        );

        return $isUnread;
    }

    /**
     * @param ConversationInterface $conversation
     */
    public function markUnread(ConversationInterface $conversation)
    {
        $this->getEventManager()->trigger(
            'markUnread.pre',
            $this,
            [
            'conversation' => $conversation
            ]
        );

        $receivers = $this->pmMapper->getReceiversByConversation($conversation);

        foreach ($receivers as $receiver) {
            $this->pmMapper->markUnread($receiver);
        }
    }

    /**
     * @param  array         $data
     * @param  UserInterface $user
     * @return ConversationInterface
     */
    public function newConversation(array $data, UserInterface $user)
    {
        $this->getEventManager()->trigger(
            'newConversation.pre',
            $this,
            [
            'data' => $data,
            'user' => $user,
            ]
        );

        /**
         * @var ConversationInterface $conversation
         */
        $conversation = clone $this->getConversationEntity();
        // Call __construct to generate a new id
        $conversation->__construct();
        $conversation->setHeadline($data['headline']);
        $this->pmMapper->newConversation($conversation);

        $receivers = explode(",", $data['to']);
        $receivers[] = $user->getId(); // we also want the sending user to be a receiver
        $this->addReceivers($conversation, $receivers, $user);
        $this->newMessage($conversation, $data['message'], $user);

        $this->getEventManager()->trigger(
            'newConversation',
            $this,
            [
            'data' => $data,
            'conversation' => $conversation,
            'user' => $user,
            ]
        );

        return $conversation;
    }

    /**
     * @param ConversationInterface $conversation
     * @param UserInterface|null $author
     * @param array $receivers
     * @return ConversationInterface|mixed
     */
    public function addReceivers(ConversationInterface $conversation, array $receivers, ?UserInterface $author = null)
    {
        $receivers = array_unique($receivers);
        
        $existingReceivers = $this->pmMapper->getReceiversByConversation($conversation);
        $existingReceiverUserIds = array_map(function(ConversationReceiverInterface $conversationReceiver) {
            return $conversationReceiver->getTo();
        }, $existingReceivers);
        
        foreach ($receivers as $receiver) {
            if (in_array($receiver, $existingReceiverUserIds)) {
                continue;
            }
            
            $conversationReceiver = clone $this->getConversationReceiverEntity();
            // Call __construct to generate a new id
            $conversationReceiver->__construct();
            $conversationReceiver->setTo($receiver);
            $conversationReceiver->setConversation($conversation);

            // The sending user should not have the message marked as unread
            if ($author && $receiver == $author->getId()) {
                $conversationReceiver->setUnread(false);
            }

            $this->pmMapper->addReceiver($conversationReceiver);
        }
        
        return $conversation;
    }

    /**
     * @param  ConversationInterface $conversation
     * @param  string                $messageText
     * @param  UserInterface         $user
     * @return MessageInterface
     */
    public function newMessage(ConversationInterface $conversation, $messageText, UserInterface $user)
    {
        $this->getEventManager()->trigger(
            'newMessage.pre',
            $this,
            [
            'conversation' => $conversation,
            'message' => $messageText,
            'user' => $user,
            ]
        );

        $message = clone $this->getMessageEntity();
        // Call __construct to generate a new id
        $message->__construct();
        $message->setMessage($messageText);
        $message->setFrom($user->getId());
        $message->setConversation($conversation);
        $message = $this->pmMapper->newMessage($message);

        $this->markUnread($conversation);
        // Mark it read for the sending user
        $this->markRead($conversation, $user);

        $this->getEventManager()->trigger(
            'newMessage',
            $this,
            [
            'conversation' => $conversation,
            'message' => $message,
            'user' => $user,
            ]
        );

        return $message;
    }

    /**
     * @param  ConversationInterface $conversation
     * @return MessageInterface
     */
    public function getLastReply(ConversationInterface $conversation)
    {
        $lastReply = $this->pmMapper->getLastReply($conversation);

        $this->getEventManager()->trigger(
            'getLastReply',
            $this,
            [
            'lastReply' => $lastReply,
            ]
        );

        return $lastReply;
    }

    /**
     * @param  UserInterface $user
     * @return ConversationInterface[]
     */
    public function getUnreadConversations(UserInterface $user)
    {
        $unreadConversationReceivers = $this->pmMapper->getUnreadConversationReceivers($user);

        $unreadConversations = [];
        foreach ($unreadConversationReceivers as $receive) {
            $unreadConversations[] = $receive->getConversation();
        }

        $this->getEventManager()->trigger(
            'getUnreadConversations',
            $this,
            [
            'unreadConversations' => $unreadConversations,
            ]
        );

        return $unreadConversations;
    }

    /**
     * @return ConversationInterface
     */
    public function getConversationEntity()
    {
        if (empty($this->conversationEntity)) {
            $conversationEntityClass = $this->options->getConversationEntity();
            $this->conversationEntity = new $conversationEntityClass;
        }

        return $this->conversationEntity;
    }

    /**
     * @param ConversationInterface $conversationEntity
     */
    public function setConversationEntity(ConversationInterface $conversationEntity)
    {
        $this->conversationEntity = $conversationEntity;
    }

    /**
     * @return ConversationReceiverInterface
     */
    public function getConversationReceiverEntity()
    {
        if (empty($this->conversationReceiverEntity)) {
            $conversationReceiverClass = $this->options->getConversationReceiverEntity();
            $this->conversationReceiverEntity = new $conversationReceiverClass;
        }

        return $this->conversationReceiverEntity;
    }

    /**
     * @param ConversationReceiverInterface $conversationReceiverEntity
     */
    public function setConversationReceiverEntity(ConversationReceiverInterface $conversationReceiverEntity)
    {
        $this->conversationReceiverEntity = $conversationReceiverEntity;
    }

    /**
     * @return MessageInterface
     */
    public function getMessageEntity()
    {
        if (empty($this->messageEntity)) {
            $messageEntityClass = $this->options->getMessageEntity();
            $this->messageEntity = new $messageEntityClass;
        }

        return $this->messageEntity;
    }

    /**
     * @param MessageInterface $messageEntity
     */
    public function setMessageEntity(MessageInterface $messageEntity)
    {
        $this->messageEntity = $messageEntity;
    }
}