diff --git a/src/Meritoo/LimeSurvey/ApiClient/Result/Collection/Participants.php b/src/Meritoo/LimeSurvey/ApiClient/Result/Collection/Participants.php new file mode 100644 index 0000000..dfa65c9 --- /dev/null +++ b/src/Meritoo/LimeSurvey/ApiClient/Result/Collection/Participants.php @@ -0,0 +1,143 @@ + + * @copyright Meritoo.pl + */ +class Participants extends Collection +{ + /** + * {@inheritdoc} + */ + public function add($element, $index = null) + { + throw new DisabledMethodException(__METHOD__, 'addParticipants'); + } + + /** + * {@inheritdoc} + */ + public function addMultiple($elements, $useIndexes = false) + { + throw new DisabledMethodException(__METHOD__, 'addParticipants'); + } + + /** + * Adds participants of given survey + * + * @param Collection $participants Participants to add. Collection of Participant classes. + * @param int $surveyId ID of survey + * @return $this + */ + public function addParticipants(Collection $participants, $surveyId) + { + /* + * No participants? + * Nothing to do + */ + if ($participants->isEmpty()) { + return $this; + } + + $this + ->getBySurvey($surveyId) + ->addMultiple($participants); + + return $this; + } + + /** + * Adds participant of given survey + * + * @param Participant $participant Participant to add + * @param int $surveyId ID of survey + * @return $this + */ + public function addParticipant(Participant $participant, $surveyId) + { + $this + ->getBySurvey($surveyId) + ->add($participant); + + return $this; + } + + /** + * Returns information if there are participants of given survey + * + * @param int $surveyId ID of survey + * @return bool + */ + public function hasParticipantsOfSurvey($surveyId) + { + return false === $this + ->getBySurvey($surveyId) + ->isEmpty(); + } + + /** + * Returns participants of given survey + * + * If there are no participants of given survey, adds an empty collection who will store participants. + * So, this method will return collection always. + * + * @param int $surveyId ID of survey + * @return Collection + */ + public function getBySurvey($surveyId) + { + /* + * There are no participants of given survey? + * Let's add an empty collection who will store participants + */ + if (!isset($this[$surveyId])) { + $this[$surveyId] = new Collection(); + } + + return $this[$surveyId]; + } + + /** + * Returns participant of given survey + * + * @param int $surveyId ID of survey + * @param string $participantEmail E-mail of searched participant + * @return Participant|null + */ + public function getParticipantOfSurvey($surveyId, $participantEmail) + { + /* @var Collection $participants */ + $participants = $this->getBySurvey($surveyId); + + if ($participants->isEmpty()) { + return null; + } + + /* @var Participant $participant */ + foreach ($participants as $participant) { + if ($participant->getEmail() == $participantEmail) { + return $participant; + } + } + + return null; + } +} diff --git a/src/Meritoo/LimeSurvey/ApiClient/Service/ParticipantService.php b/src/Meritoo/LimeSurvey/ApiClient/Service/ParticipantService.php new file mode 100644 index 0000000..be672fa --- /dev/null +++ b/src/Meritoo/LimeSurvey/ApiClient/Service/ParticipantService.php @@ -0,0 +1,142 @@ + + * @copyright Meritoo.pl + */ +class ParticipantService +{ + /** + * Client of the LimeSurvey's API + * + * @var Client + */ + private $client; + + /** + * Participants of survey. + * All participants grouped per survey. + * + * @var Participants + */ + private $allParticipants; + + /** + * Class constructor + * + * @param Client $client Client of the LimeSurvey's API + * @param Participants $allParticipants (optional) Participants of survey. All participants grouped per survey. + */ + public function __construct(Client $client, Participants $allParticipants = null) + { + if (null === $allParticipants) { + $allParticipants = new Participants(); + } + + $this->client = $client; + $this->allParticipants = $allParticipants; + } + + /** + * Returns participants of given survey + * + * @param int $surveyId ID of survey + * @return Collection + */ + public function getSurveyParticipants($surveyId) + { + $hasSurvey = $this + ->allParticipants + ->hasParticipantsOfSurvey($surveyId); + + if (!$hasSurvey) { + $arguments = [ + $surveyId, + ]; + + $participants = $this + ->client + ->run(MethodType::LIST_PARTICIPANTS, $arguments) + ->getData(); + + $this + ->allParticipants + ->addParticipants($participants, $surveyId); + } + + return $this + ->allParticipants + ->getBySurvey($surveyId); + } + + /** + * Returns information if given survey has participant with given e-mail + * + * @param int $surveyId ID of survey + * @param string $email E-mail address of the participant + * @return bool + */ + public function hasParticipant($surveyId, $email) + { + /* + * I have to get all participants of survey to avoid problem when participants exist but are not loaded + */ + $this->getSurveyParticipants($surveyId); + + return null !== $this + ->allParticipants + ->getParticipantOfSurvey($surveyId, $email); + } + + /** + * Adds participant with given data to survey with given ID + * + * @param int $surveyId ID of survey + * @param string $firstName First name of the participant to add + * @param string $lastName Last ame of the participant to add + * @param string $email E-mail address of the participant to add + * @return Participant + */ + public function addParticipant($surveyId, $firstName, $lastName, $email) + { + $participantsData = [ + [ + 'firstname' => $firstName, + 'lastname' => $lastName, + 'email' => $email, + ], + ]; + + $arguments = [ + $surveyId, + $participantsData, + ]; + + $participantCollection = $this + ->client + ->run(MethodType::ADD_PARTICIPANTS, $arguments) + ->getData(); + + $this + ->allParticipants + ->addParticipants($participantCollection, $surveyId); + + return $participantCollection->getFirst(); + } +} diff --git a/tests/Meritoo/LimeSurvey/Test/ApiClient/Result/Collection/ParticipantsTest.php b/tests/Meritoo/LimeSurvey/Test/ApiClient/Result/Collection/ParticipantsTest.php new file mode 100644 index 0000000..d93e049 --- /dev/null +++ b/tests/Meritoo/LimeSurvey/Test/ApiClient/Result/Collection/ParticipantsTest.php @@ -0,0 +1,143 @@ + + * @copyright Meritoo.pl + */ +class ParticipantsTest extends BaseTestCase +{ + /** + * An empty collection of participants + * + * @var Participants + */ + private $participantsEmpty; + + /** + * Participants of 1 survey + * + * @var Participants + */ + private $participantsOfOneSurvey; + + /** + * Participants of more than 1 survey + * + * @var Participants + */ + private $participantsOfManySurvey; + + public function testConstructorVisibilityAndArguments() + { + static::assertConstructorVisibilityAndArguments(Participants::class, OopVisibilityType::IS_PUBLIC, 1, 0); + } + + public function testAdd() + { + $this->expectException(DisabledMethodException::class); + (new Participants())->add(''); + } + + public function testAddMultiple() + { + $this->expectException(DisabledMethodException::class); + (new Participants())->addMultiple([]); + } + + public function testAddParticipantsWithoutParticipants() + { + $surveyId = 1; + + $participants = new Participants(); + $result = $participants->addParticipants(new Collection(), $surveyId); + + static::assertFalse($participants->hasParticipantsOfSurvey($surveyId)); + static::assertFalse($participants->hasParticipantsOfSurvey(2)); + + static::assertEquals($participants, $result); + static::assertCount(0, $participants->getBySurvey($surveyId)); + } + + public function testAddParticipantsFirstParticipants() + { + $surveyId = 1; + + $participantsData = new Collection([ + new Participant(), + new Participant(), + ]); + + $result = $this + ->participantsEmpty + ->addParticipants($participantsData, $surveyId); + + static::assertTrue($this->participantsEmpty->hasParticipantsOfSurvey($surveyId)); + static::assertFalse($this->participantsEmpty->hasParticipantsOfSurvey(2)); + + static::assertEquals($this->participantsEmpty, $result); + static::assertCount(2, $this->participantsEmpty->getBySurvey($surveyId)); + } + + public function testAddParticipantsMoreParticipants() + { + $surveyId = 2; + + $participantsData = new Collection([ + new Participant(), + new Participant(), + ]); + + $result = $this + ->participantsOfOneSurvey + ->addParticipants($participantsData, $surveyId); + + static::assertTrue($this->participantsOfOneSurvey->hasParticipantsOfSurvey($surveyId)); + static::assertFalse($this->participantsOfOneSurvey->hasParticipantsOfSurvey(3)); + + static::assertEquals($this->participantsOfOneSurvey, $result); + static::assertCount(2, $this->participantsOfOneSurvey->getBySurvey($surveyId)); + } + + /** + * {@inheritdoc} + */ + protected function setUp() + { + parent::setUp(); + + $this->participantsEmpty = new Participants(); + $this->participantsOfOneSurvey = new Participants(); + $this->participantsOfManySurvey = new Participants(); + + $participants1Survey = new Collection(); + $participants2Survey = new Collection(); + $participants3Survey = new Collection(); + + $this + ->participantsOfOneSurvey + ->addParticipants($participants1Survey, 1); + + $this + ->participantsOfManySurvey + ->addParticipants($participants1Survey, 2) + ->addParticipants($participants2Survey, 3) + ->addParticipants($participants3Survey, 4); + } +} diff --git a/tests/Meritoo/LimeSurvey/Test/ApiClient/Service/ParticipantServiceTest.php b/tests/Meritoo/LimeSurvey/Test/ApiClient/Service/ParticipantServiceTest.php new file mode 100644 index 0000000..6606c94 --- /dev/null +++ b/tests/Meritoo/LimeSurvey/Test/ApiClient/Service/ParticipantServiceTest.php @@ -0,0 +1,186 @@ + + * @copyright Meritoo.pl + */ +class ParticipantServiceTest extends BaseTestCase +{ + /** + * Serves participants. + * Service without participants. + * + * @var ParticipantService + */ + private $serviceWithoutParticipants; + + /** + * Serves participants. + * Service with participants. + * + * @var ParticipantService + */ + private $serviceWithParticipants; + + public function testConstructorVisibilityAndArguments() + { + static::assertConstructorVisibilityAndArguments(ParticipantService::class, OopVisibilityType::IS_PUBLIC, 2, 1); + } + + public function testGetSurveyParticipantsFromEmptyParticipants() + { + $rpcClientManager = $this->getJsonRpcClientManager(3); + $sessionManager = $this->getSessionManager(); + + $this->createServiceWithoutParticipants($rpcClientManager, $sessionManager); + $this->createServiceWithParticipants($rpcClientManager, $sessionManager); + + static::assertCount(0, $this->serviceWithoutParticipants->getSurveyParticipants(1)); + static::assertCount(0, $this->serviceWithoutParticipants->getSurveyParticipants(2)); + + static::assertCount(2, $this->serviceWithParticipants->getSurveyParticipants(1)); + static::assertCount(1, $this->serviceWithParticipants->getSurveyParticipants(2)); + static::assertCount(0, $this->serviceWithParticipants->getSurveyParticipants(3)); + } + + public function testHasParticipant() + { + $rpcClientManager = $this->getJsonRpcClientManager(3); + $sessionManager = $this->getSessionManager(); + + $this->createServiceWithoutParticipants($rpcClientManager, $sessionManager); + $this->createServiceWithParticipants($rpcClientManager, $sessionManager); + + static::assertFalse($this->serviceWithoutParticipants->hasParticipant(1, 'john@scott.com')); + static::assertFalse($this->serviceWithoutParticipants->hasParticipant(2, 'john@scott.com')); + + static::assertTrue($this->serviceWithParticipants->hasParticipant(1, 'john@scott.com')); + static::assertFalse($this->serviceWithParticipants->hasParticipant(2, 'john@scott.com')); + static::assertFalse($this->serviceWithParticipants->hasParticipant(3, 'john@scott.com')); + } + + public function testAddParticipant() + { + $firstName = 'John'; + $lastName = 'Scott'; + $email = 'john@scott.com'; + $runMethodCallCount = 1; + + $runMethodCallResults = [ + [ + 'firstname' => $firstName, + 'lastname' => $lastName, + 'email' => $email, + ], + ]; + + $rpcClientManager = $this->getJsonRpcClientManager($runMethodCallCount, $runMethodCallResults); + $sessionManager = $this->getSessionManager(); + $this->createServiceWithoutParticipants($rpcClientManager, $sessionManager); + + $result = $this->serviceWithoutParticipants->addParticipant(1, $firstName, $lastName, $email); + static::assertInstanceOf(Participant::class, $result); + } + + /** + * Returns configuration used while connecting to LimeSurvey's API + * + * @return ConnectionConfiguration + */ + private function getConnectionConfiguration() + { + return new ConnectionConfiguration('http://test.com', 'test', 'test'); + } + + /** + * Returns manager of session started while connecting to LimeSurvey's API + * + * @return PHPUnit_Framework_MockObject_MockObject + */ + private function getSessionManager() + { + return $this->createMock(SessionManager::class); + } + + /** + * Returns manager of the JsonRPC client used while connecting to LimeSurvey's API + * + * @param int $runMethodCallCount Count of calls of the runMethod() method (who is mocked) + * @param array $runMethodCallResults (optional) Results of calls of the runMethod() method (who is mocked) + * @return PHPUnit_Framework_MockObject_MockObject + */ + private function getJsonRpcClientManager($runMethodCallCount, array $runMethodCallResults = []) + { + $rpcClientManager = $this->createMock(JsonRpcClientManager::class); + + $rpcClientManager + ->expects(static::exactly($runMethodCallCount)) + ->method('runMethod') + ->will(static::returnValue($runMethodCallResults)); + + return $rpcClientManager; + } + + /** + * Creates instance of the tested service without participants + * + * @param PHPUnit_Framework_MockObject_MockObject $rpcClientManager Manager of the JsonRPC client used while connecting to LimeSurvey's API + * @param PHPUnit_Framework_MockObject_MockObject $sessionManager Manager of session started while connecting to LimeSurvey's API + */ + private function createServiceWithoutParticipants(PHPUnit_Framework_MockObject_MockObject $rpcClientManager, PHPUnit_Framework_MockObject_MockObject $sessionManager) + { + $configuration = $this->getConnectionConfiguration(); + $client = new Client($configuration, $rpcClientManager, $sessionManager); + $this->serviceWithoutParticipants = new ParticipantService($client); + } + + /** + * Creates instance of the tested service with participants + * + * @param PHPUnit_Framework_MockObject_MockObject $rpcClientManager Manager of the JsonRPC client used while connecting to LimeSurvey's API + * @param PHPUnit_Framework_MockObject_MockObject $sessionManager Manager of session started while connecting to LimeSurvey's API + */ + private function createServiceWithParticipants(PHPUnit_Framework_MockObject_MockObject $rpcClientManager, PHPUnit_Framework_MockObject_MockObject $sessionManager) + { + $configuration = $this->getConnectionConfiguration(); + $client = new Client($configuration, $rpcClientManager, $sessionManager); + + $allParticipants = new Participants([ + 1 => new Collection([ + (new Participant())->setValues([ + 'firstname' => 'John', + 'lastname' => 'Scott', + 'email' => 'john@scott.com', + ]), + new Participant(), + ]), + 2 => new Collection([ + new Participant(), + ]), + ]); + + $this->serviceWithParticipants = new ParticipantService($client, $allParticipants); + } +}