15 Commits
0.0.8 ... php54

Author SHA1 Message Date
Meritoo
0d21214bc6 SurveyService - add method that allows to get the "start survey url" using participant's token (instead of whole participant's object) 2017-10-27 16:15:59 +02:00
Meritoo
6f6d4e9119 ParticipantService - fix type used in phpdoc 2017-10-27 12:07:09 +02:00
Meritoo
63e7ddf511 Tests - use common method to create/prepare date 2017-10-27 12:05:12 +02:00
Meritoo
782c31ccdc Fetch all participants of survey (instead of first 10 only - default behaviour) 2017-10-27 12:00:07 +02:00
Meritoo
fafb11633f Do not fetch all participants of given survey to get information if participant has filled the survey 2017-10-27 11:02:39 +02:00
Meritoo
cdbee2991c Minor refactoring 2017-10-27 10:49:10 +02:00
Meritoo
472807ee33 Participant & Survey - update creating instance od DateTime from string 2017-10-22 18:42:07 +02:00
Meritoo
ba9160cccf Participant has completed survey - fix getting proper information 2017-10-22 18:41:13 +02:00
Meritoo
7846cedba4 Remove unnecessary class 2017-10-20 00:13:43 +02:00
Meritoo
a09b0c72ae Tests - BaseTestCase - fix data providers 2017-10-20 00:11:00 +02:00
Meritoo
44f56bd50d Add required "className" constants with full names of classes 2017-10-19 23:39:16 +02:00
Meritoo
bdbaebb5c0 Support PHP 5.4 2017-10-19 22:10:26 +02:00
Meritoo
835c4325b8 Tests - missing description of method 2017-10-19 21:57:35 +02:00
Meritoo
24a3d478b5 Tests - use Docker (as environment guard) 2017-10-19 21:44:25 +02:00
Meritoo
e38df1a8f2 Start names of special directories with dot 2017-10-18 21:21:53 +02:00
101 changed files with 9397 additions and 979 deletions

67
.docker/config/Dockerfile Normal file
View File

@@ -0,0 +1,67 @@
FROM php:5.4-cli
#
# Tools & libraries
#
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
vim \
git \
zip \
unzip \
zlib1g-dev \
libicu-dev \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
#
# PHP extensions
#
RUN docker-php-ext-install \
zip \
intl \
mbstring
#
# PHP configuration:
# - default configuration
# - timezone
#
COPY php.ini /usr/local/etc/php/php.ini
ARG TIMEZONE
RUN echo "\n""date.timezone = $TIMEZONE""\n" >> /usr/local/etc/php/php.ini
#
# Disabled, because:
# PHP versions below 5.5 are not supported
#
# Xdebug
#
#RUN pecl install xdebug \
# && docker-php-ext-enable xdebug
#COPY xdebug.ini /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
#
# Phing
#
RUN pear channel-discover pear.phing.info \
&& pear install [--alldeps] phing/phing
#
# Composer + https://packagist.org/packages/hirak/prestissimo package
#
RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" \
&& php -r "if (hash_file('SHA384', 'composer-setup.php') === \
'544e09ee996cdf60ece3804abc52599c22b1f40f4323403c44d44fdfdd586475ca9813a858088ffbc1f233e9b180f061') { echo \
'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;" \
&& php composer-setup.php --install-dir=/usr/local/bin --filename=composer \
&& php -r "unlink('composer-setup.php');" \
&& composer global require --no-plugins --no-scripts hirak/prestissimo \
&& rm -rf /root/.composer/cache/*
#
# Bash
#
RUN sed -i 's/^# export/export/g' /root/.bashrc \
&& sed -i 's/^# alias/alias/g' /root/.bashrc \
&& echo "\n"'export PATH=/project/vendor/bin:$PATH'"\n" >> /root/.bashrc

3
.docker/config/php.ini Normal file
View File

@@ -0,0 +1,3 @@
display_errors = On
display_startup_errors = On
error_reporting = E_ALL

View File

@@ -0,0 +1,7 @@
[xdebug]
zend_extension='xdebug.so'
xdebug.remote_enable=1
xdebug.remote_connect_back=1
xdebug.idekey='PHPSTORM'
xdebug.remote_port=9001

1
.env Normal file
View File

@@ -0,0 +1 @@
TIMEZONE=Europe/Warsaw

10
.gitignore vendored
View File

@@ -17,7 +17,7 @@
# ----------------------------------------------------------------------------------------------------------------------
### Phing
# ----------------------------------------------------------------------------------------------------------------------
/phing/properties
/.phing/properties
# ----------------------------------------------------------------------------------------------------------------------
### PHPUnit
@@ -29,10 +29,16 @@
# ----------------------------------------------------------------------------------------------------------------------
/.php_cs.cache
# ----------------------------------------------------------------------------------------------------------------------
### Build files
# ----------------------------------------------------------------------------------------------------------------------
/.build/
# ----------------------------------------------------------------------------------------------------------------------
### Generated databases
# ----------------------------------------------------------------------------------------------------------------------
/data/tmp
/.data/tmp
*.sql
*.sqlite

View File

@@ -2,12 +2,12 @@
<project name="Meritoo Package" basedir="." default="build:main" phingVersion="2.14.0">
<!-- Properties -->
<if>
<available file="phing/properties" property="custom.properties.available"/>
<available file=".phing/properties" property="custom.properties.available"/>
<then>
<property file="phing/properties" />
<property file=".phing/properties" />
</then>
<else>
<property file="phing/properties.dist" />
<property file=".phing/properties.dist" />
</else>
</if>

View File

@@ -59,7 +59,7 @@ composer.validate = false
# System directories
#
dir.data = ${project.basedir}/data
dir.data = ${project.basedir}/.data
dir.src = ${project.basedir}/src
dir.tests = ${project.basedir}/tests
@@ -67,7 +67,7 @@ dir.tests = ${project.basedir}/tests
# Build directories
# --------------------------------------------------------------------------------
dir.build = ${project.basedir}/build
dir.build = ${project.basedir}/.build
dir.reports = ${dir.build}/logs
dir.reports.pdepend = ${dir.reports}/pdepend
dir.reports.coverage = ${dir.reports}/phpunit_coverage

View File

@@ -11,12 +11,12 @@
<!-- Properties -->
<if>
<available file="phing/properties" property="custom.properties.available"/>
<available file=".phing/properties" property="custom.properties.available"/>
<then>
<property file="phing/properties" />
<property file=".phing/properties" />
</then>
<else>
<property file="phing/properties.dist" />
<property file=".phing/properties.dist" />
</else>
</if>
@@ -146,13 +146,18 @@
2017-02-22
-->
<target name="check:cs" description="Checks coding standard">
<echo msg="Checking coding standard..." />
<echo msg="Checking coding standard... DISABLED for PHP 5.4" />
<!--
Disabled, because of error while running PHP 5.4.45:
This task requires the PHP_CodeSniffer package installed and available on the include path
<phpcodesniffer standard="PSR2" showWarnings="true">
<fileset refid="sourcecode" />
<formatter type="checkstyle" outfile="${dir.reports}/checkstyle.xml" />
<formatter type="csv" outfile="${dir.reports}/checkstyle.csv" />
<formatter type="summary" outfile="${dir.reports}/checkstyle_summary.txt" />
</phpcodesniffer>
-->
</target>
<!-- copy/paste detector -->

View File

@@ -2,12 +2,12 @@
<project name="Meritoo Package" basedir="." default="build:main" phingVersion="2.14.0">
<!-- Properties -->
<if>
<available file="phing/properties" property="custom.properties.available"/>
<available file=".phing/properties" property="custom.properties.available"/>
<then>
<property file="phing/properties" />
<property file=".phing/properties" />
</then>
<else>
<property file="phing/properties.dist" />
<property file=".phing/properties.dist" />
</else>
</if>
@@ -18,12 +18,12 @@
<!-- Build app -->
<target name="build:app" description="Prepares app to build and tests">
<phing phingfile="phing/app.xml" haltonfailure="true" />
<phing phingfile=".phing/app.xml" haltonfailure="true" />
</target>
<!-- Build tests -->
<target name="build:tests" description="Runs all tests, checks and creates docs">
<phing phingfile="phing/tests.xml" haltonfailure="true" />
<phing phingfile=".phing/tests.xml" haltonfailure="true" />
<!--
Conditional running of tests.
@@ -35,7 +35,7 @@
<if>
<equals arg1="${env}" arg2="test" />
<then>
<phing phingfile="phing/tests.xml" haltonfailure="true" />
<phing phingfile=".phing/tests.xml" haltonfailure="true" />
</then>
<else>
<echo message="[Skipped] Running tests, checks and creating docs, because it's a not 'test' environment..." />

View File

@@ -3,7 +3,7 @@
"description": "Client of LimeSurvey API",
"type": "library",
"license": "MIT",
"version": "0.0.8",
"version": "0.0.9",
"authors": [
{
"name": "Meritoo",
@@ -11,21 +11,24 @@
}
],
"require": {
"php": ">=5.4",
"fguillot/json-rpc": "^1.2",
"meritoo/common-library": "~0.0.1"
"gedmo/doctrine-extensions": "^2.4",
"symfony/http-foundation": "^2.8"
},
"require-dev": {
"phpunit/phpunit": "^5.7",
"squizlabs/php_codesniffer": "^2.9",
"phpunit/phpunit": "^4.8",
"squizlabs/php_codesniffer": "^3.1",
"phpmd/phpmd": "^2.6",
"sebastian/phpcpd": "^3.0",
"sebastian/phpcpd": "^2.0",
"pdepend/pdepend": "^2.5",
"phploc/phploc": "^4.0",
"friendsofphp/php-cs-fixer": "^2.6"
"phploc/phploc": "^2.1",
"friendsofphp/php-cs-fixer": "^2.2"
},
"autoload": {
"psr-4": {
"Meritoo\\LimeSurvey\\ApiClient\\": "src/"
"Meritoo\\Common\\": "src/Common/",
"Meritoo\\LimeSurvey\\ApiClient\\": "src/LimeSurvey/"
}
},
"autoload-dev": {

15
docker-compose.yml Normal file
View File

@@ -0,0 +1,15 @@
version: '3'
services:
php-cli:
image: meritoo/limesurvey-api-client
container_name: meritoo-limesurvey-api-client
working_dir: /project
entrypoint: php
command: -S 0.0.0.0:9999
build:
context: ./.docker/config
args:
- TIMEZONE=$TIMEZONE
volumes:
- .:/project

View File

@@ -30,6 +30,6 @@
</groups>
<logging>
<log type="coverage-html" target="./build/logs/phpunit_coverage/html" />
<log type="coverage-html" target="./.build/logs/phpunit_coverage/html" />
</logging>
</phpunit>

View File

@@ -0,0 +1,286 @@
<?php
/**
* (c) Meritoo.pl, http://www.meritoo.pl
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Meritoo\Common\Collection;
use ArrayAccess;
use ArrayIterator;
use Countable;
use IteratorAggregate;
use Meritoo\Common\Utilities\Arrays;
/**
* Collection of elements.
* It's a set of some elements, e.g. objects.
*
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl>
* @copyright Meritoo.pl
*/
class Collection implements Countable, ArrayAccess, IteratorAggregate
{
const className = 'Meritoo\Common\Collection\Collection';
/**
* The elements of collection
*
* @var array
*/
private $elements;
/**
* Class constructor
*
* @param array $elements (optional) The elements of collection
*/
public function __construct(array $elements = [])
{
$this->elements = $elements;
}
/**
* {@inheritdoc}
* Required by interface Countable
*/
public function count()
{
return count($this->elements);
}
/**
* {@inheritdoc}
* Required by interface ArrayAccess
*/
public function offsetExists($offset)
{
return $this->exists($offset);
}
/**
* {@inheritdoc}
* Required by interface ArrayAccess
*/
public function offsetGet($offset)
{
if ($this->exists($offset)) {
return $this->elements[$offset];
}
return null;
}
/**
* {@inheritdoc}
* Required by interface ArrayAccess
*/
public function offsetSet($offset, $value)
{
$this->elements[$offset] = $value;
}
/**
* {@inheritdoc}
* Required by interface ArrayAccess
*/
public function offsetUnset($offset)
{
if ($this->exists($offset)) {
unset($this->elements[$offset]);
}
}
/**
* {@inheritdoc}
* Required by interface IteratorAggregate
*/
public function getIterator()
{
return new ArrayIterator($this->elements);
}
/**
* Adds given element (at the end of collection)
*
* @param mixed $element The element to add
* @param mixed $index (optional) Index / key of the element
* @return $this
*/
public function add($element, $index = null)
{
if (null === $index) {
$this->elements[] = $element;
} else {
$this->elements[$index] = $element;
}
return $this;
}
/**
* Adds given elements (at the end of collection)
*
* @param array|Collection $elements The elements to add
* @param bool|false $useIndexes (optional) If is set to true, indexes of given elements will be used in
* this collection. Otherwise - not.
* @return $this
*/
public function addMultiple($elements, $useIndexes = false)
{
if (!empty($elements)) {
foreach ($elements as $index => $element) {
if (!$useIndexes) {
$index = null;
}
$this->add($element, $index);
}
}
return $this;
}
/**
* Prepends given element (adds given element at the beginning of collection)
*
* @param mixed $element The element to prepend
* @return $this
*/
public function prepend($element)
{
array_unshift($this->elements, $element);
return $this;
}
/**
* Removes given element
*
* @param mixed $element The element to remove
* @return $this
*/
public function remove($element)
{
if ($this->count() > 0) {
foreach ($this->elements as $index => $existing) {
if ($element === $existing) {
unset($this->elements[$index]);
break;
}
}
}
return $this;
}
/**
* Returns information if collection is empty
*
* @return bool
*/
public function isEmpty()
{
return empty($this->elements);
}
/**
* Returns information if given element is first in the collection
*
* @param mixed $element The element to verify
* @return bool
*/
public function isFirst($element)
{
return reset($this->elements) === $element;
}
/**
* Returns information if given element is last in the collection
*
* @param mixed $element The element to verify
* @return bool
*/
public function isLast($element)
{
return end($this->elements) === $element;
}
/**
* Returns information if the collection has given element, iow. if given element exists in the collection
*
* @param mixed $element The element to verify
* @return bool
*/
public function has($element)
{
$index = Arrays::getIndexOf($this->elements, $element);
return null !== $index && false !== $index;
}
/**
* Returns previous element for given element
*
* @param mixed $element The element to verify
* @return mixed|null
*/
public function getPrevious($element)
{
return Arrays::getPreviousElement($this->elements, $element);
}
/**
* Returns next element for given element
*
* @param mixed $element The element to verify
* @return mixed|null
*/
public function getNext($element)
{
return Arrays::getNextElement($this->elements, $element);
}
/**
* Returns the first element in the collection
*
* @return mixed
*/
public function getFirst()
{
return Arrays::getFirstElement($this->elements);
}
/**
* Returns the last element in the collection
*
* @return mixed
*/
public function getLast()
{
return Arrays::getLastElement($this->elements);
}
/**
* Returns an array representation of the collection
*
* @return array
*/
public function toArray()
{
return $this->elements;
}
/**
* Returns information if element with given index/key exists
*
* @param string|int $index The index/key of element
* @return bool
*/
private function exists($index)
{
return isset($this->elements[$index]) || array_key_exists($index, $this->elements);
}
}

View File

@@ -0,0 +1,41 @@
<?php
/**
* (c) Meritoo.pl, http://www.meritoo.pl
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Meritoo\Common\Exception\Base;
use Exception;
use Meritoo\Common\Type\Base\BaseType;
use Meritoo\Common\Utilities\Arrays;
/**
* An exception used while type of something is unknown
*
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl>
* @copyright Meritoo.pl
*/
abstract class UnknownTypeException extends Exception
{
/**
* Class constructor
*
* @param string|int $unknownType The unknown type of something (value of constant)
* @param BaseType $typeInstance An instance of class that contains type of the something
* @param string $typeName Name of the something
*/
public function __construct($unknownType, BaseType $typeInstance, $typeName)
{
$allTypes = $typeInstance->getAll();
$types = Arrays::values2string($allTypes, '', ', ');
$template = 'The \'%s\' type of %s is unknown. Probably doesn\'t exist or there is a typo. You should use one'
. ' of these types: %s.';
$message = sprintf(sprintf($template, $unknownType, $typeName, $types));
parent::__construct($message);
}
}

View File

@@ -0,0 +1,32 @@
<?php
/**
* (c) Meritoo.pl, http://www.meritoo.pl
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Meritoo\Common\Exception\Date;
use Meritoo\Common\Exception\Base\UnknownTypeException;
use Meritoo\Common\Type\DatePartType;
/**
* An exception used while type of date part, e.g. "year", is unknown
*
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl>
* @copyright Meritoo.pl
*/
class UnknownDatePartTypeException extends UnknownTypeException
{
/**
* Class constructor
*
* @param string $unknownDatePart Type of date part, e.g. "year". One of DatePartType class constants.
* @param string $value Incorrect value
*/
public function __construct($unknownDatePart, $value)
{
parent::__construct($unknownDatePart, new DatePartType(), sprintf('date part (with value %s)', $value));
}
}

View File

@@ -0,0 +1,33 @@
<?php
/**
* (c) Meritoo.pl, http://www.meritoo.pl
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Meritoo\Common\Exception\File;
/**
* An exception used while file with given path is empty (has no content)
*
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl>
* @copyright Meritoo.pl
*/
class EmptyFileException extends \Exception
{
const className = 'Meritoo\Common\Exception\File\EmptyFileException';
/**
* Class constructor
*
* @param string $emptyFilePath Path of the empty file
*/
public function __construct($emptyFilePath)
{
$template = 'File with path \'%s\' is empty (has no content). Did you provide path of proper file?';
$message = sprintf($template, $emptyFilePath);
parent::__construct($message);
}
}

View File

@@ -0,0 +1,28 @@
<?php
/**
* (c) Meritoo.pl, http://www.meritoo.pl
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Meritoo\Common\Exception\File;
/**
* An exception used while path of given file is empty
*
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl>
* @copyright Meritoo.pl
*/
class EmptyFilePathException extends \Exception
{
const className = 'Meritoo\Common\Exception\File\EmptyFilePathException';
/**
* Class constructor
*/
public function __construct()
{
parent::__construct('Path of the file is empty. Did you provide path of proper file?');
}
}

View File

@@ -0,0 +1,33 @@
<?php
/**
* (c) Meritoo.pl, http://www.meritoo.pl
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Meritoo\Common\Exception\File;
/**
* An exception used while file with given path does not exist
*
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl>
* @copyright Meritoo.pl
*/
class NotExistingFileException extends \Exception
{
const className = 'Meritoo\Common\Exception\File\NotExistingFileException';
/**
* Class constructor
*
* @param string $notExistingFilePath Path of not existing (or not readable) file
*/
public function __construct($notExistingFilePath)
{
$template = 'File with path \'%s\' does not exist (or is not readable). Did you provide path of proper file?';
$message = sprintf($template, $notExistingFilePath);
parent::__construct($message);
}
}

View File

@@ -0,0 +1,40 @@
<?php
/**
* (c) Meritoo.pl, http://www.meritoo.pl
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Meritoo\Common\Exception\Method;
use Exception;
/**
* An exception used while method cannot be called, because is disabled
*
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl>
* @copyright Meritoo.pl
*/
class DisabledMethodException extends Exception
{
const className = 'Meritoo\Common\Exception\Method\DisabledMethodException';
/**
* Class constructor
*
* @param string $disabledMethod Name of the disabled method
* @param string $alternativeMethod (optional) Name of the alternative method
*/
public function __construct($disabledMethod, $alternativeMethod = '')
{
$template = 'Method %s() cannot be called, because is disabled.';
if (!empty($alternativeMethod)) {
$template .= ' Use %s() instead.';
}
$message = sprintf($template, $disabledMethod, $alternativeMethod);
parent::__construct($message);
}
}

View File

@@ -0,0 +1,47 @@
<?php
/**
* (c) Meritoo.pl, http://www.meritoo.pl
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Meritoo\Common\Exception\Reflection;
use Exception;
/**
* An exception used while name of class or trait cannot be resolved
*
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl>
* @copyright Meritoo.pl
*/
class CannotResolveClassNameException extends Exception
{
/**
* Class constructor
*
* @param array|object|string $source Source of the class's / trait's name. It can be an array of objects,
* namespaces, object or namespace.
* @param bool $forClass (optional) If is set to true, message of this exception for class is
* prepared. Otherwise - for trait.
*/
public function __construct($source, $forClass = true)
{
$forWho = 'trait';
$value = '';
if ($forClass) {
$forWho = 'class';
}
if (is_scalar($source)) {
$value = sprintf(' %s', (string)$source);
}
$template = 'Name of %s from given \'%s\'%s cannot be resolved. Is there everything ok?';
$message = sprintf($template, $forWho, gettype($source), $value);
parent::__construct($message);
}
}

View File

@@ -0,0 +1,38 @@
<?php
/**
* (c) Meritoo.pl, http://www.meritoo.pl
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Meritoo\Common\Exception\Reflection;
use Exception;
use Meritoo\Common\Utilities\Reflection;
/**
* An exception used while given class has no child classes
*
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl>
* @copyright Meritoo.pl
*/
class MissingChildClassesException extends Exception
{
/**
* Class constructor
*
* @param array|object|string $parentClass Class that hasn't child classes, but it should. An array of objects,
* strings, object or string.
*/
public function __construct($parentClass)
{
$template = 'The \'%s\' class requires one child class at least who will extend her (maybe is an abstract'
. ' class), but the child classes are missing. Did you forget to extend this class?';
$parentClassName = Reflection::getClassName($parentClass);
$message = sprintf($template, $parentClassName);
parent::__construct($message);
}
}

View File

@@ -0,0 +1,39 @@
<?php
/**
* (c) Meritoo.pl, http://www.meritoo.pl
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Meritoo\Common\Exception\Reflection;
use Exception;
use Meritoo\Common\Utilities\Reflection;
/**
* An exception used while given class has more than one child class
*
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl>
* @copyright Meritoo.pl
*/
class TooManyChildClassesException extends Exception
{
/**
* Class constructor
*
* @param array|object|string $parentClass Class that has more than one child class, but it shouldn't. An array
* of objects, strings, object or string.
* @param array $childClasses Child classes
*/
public function __construct($parentClass, array $childClasses)
{
$template = "The '%s' class requires one child class at most who will extend her, but more than one child"
. " class was found:\n- %s\n\nWhy did you create more than one classes that extend '%s' class?";
$parentClassName = Reflection::getClassName($parentClass);
$message = sprintf($template, $parentClassName, implode("\n- ", $childClasses), $parentClassName);
parent::__construct($message);
}
}

View File

@@ -0,0 +1,32 @@
<?php
/**
* (c) Meritoo.pl, http://www.meritoo.pl
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Meritoo\Common\Exception\Regex;
/**
* An exception used while length of given hexadecimal value of color is incorrect
*
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl>
* @copyright Meritoo.pl
*/
class IncorrectColorHexLengthException extends \Exception
{
/**
* Class constructor
*
* @param string $color Incorrect hexadecimal value of color
*/
public function __construct($color)
{
$template = 'Length of hexadecimal value of color \'%s\' is incorrect. It\'s %d, but it should be 3 or 6.'
. ' Is there everything ok?';
$message = sprintf($template, $color, strlen($color));
parent::__construct($message);
}
}

View File

@@ -0,0 +1,29 @@
<?php
/**
* (c) Meritoo.pl, http://www.meritoo.pl
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Meritoo\Common\Exception\Regex;
/**
* An exception used while given hexadecimal value of color is invalid
*
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl>
* @copyright Meritoo.pl
*/
class InvalidColorHexValueException extends \Exception
{
/**
* Class constructor
*
* @param string $color Invalid hexadecimal value of color
*/
public function __construct($color)
{
$message = sprintf('Hexadecimal value of color \'%s\' is invalid. Is there everything ok?', $color);
parent::__construct($message);
}
}

View File

@@ -0,0 +1,25 @@
<?php
namespace Meritoo\Common\Exception\Regex;
/**
* An exception used while url is invalid
*
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl>
* @copyright Meritoo.pl
*/
class InvalidUrlException extends \Exception
{
const className = 'Meritoo\Common\Exception\Regex\InvalidUrlException';
/**
* Class constructor
*
* @param string $url Invalid url
*/
public function __construct($url)
{
$message = sprintf('Url \'%s\' is invalid. Is there everything ok?', $url);
parent::__construct($message);
}
}

View File

@@ -0,0 +1,23 @@
<?php
namespace Meritoo\Common\Exception\Type;
use Meritoo\Common\Exception\Base\UnknownTypeException;
use Meritoo\Common\Type\OopVisibilityType;
/**
* An exception used while the visibility of a property, a method or (as of PHP 7.1.0) a constant is unknown
*
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl>
* @copyright Meritoo.pl
*/
class UnknownOopVisibilityTypeException extends UnknownTypeException
{
/**
* {@inheritdoc}
*/
public function __construct($unknownType)
{
parent::__construct($unknownType, new OopVisibilityType(), 'OOP-related visibility');
}
}

View File

@@ -0,0 +1,309 @@
<?php
/**
* (c) Meritoo.pl, http://www.meritoo.pl
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Meritoo\Common\Test\Base;
use DateTime;
use Meritoo\Common\Exception\Type\UnknownOopVisibilityTypeException;
use Meritoo\Common\Type\OopVisibilityType;
use Meritoo\Common\Utilities\Miscellaneous;
use PHPUnit\Framework\TestCase;
use ReflectionClass;
use ReflectionMethod;
/**
* Base test case with common methods and data providers
*
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl>
* @copyright Meritoo.pl
*/
abstract class BaseTestCase extends TestCase
{
/**
* Path of directory with data used by test cases
*
* @var string
*/
private static $testsDataDirPath = '.data/tests';
/**
* Provides an empty value
*
* @return array
* //return Generator
*/
public function provideEmptyValue()
{
return [
[''],
[' '],
[null],
[0],
[false],
[[]],
];
/*
yield[''];
yield[' '];
yield[null];
yield[0];
yield[false];
yield[[]];
*/
}
/**
* Provides boolean value
*
* @return array
* //return Generator
*/
public function provideBooleanValue()
{
return [
[true],
[false],
];
/*
yield[false];
yield[true];
*/
}
/**
* Provides instance of DateTime class
*
* @return array
* //return Generator
*/
public function provideDateTimeInstance()
{
return [
[new DateTime()],
[new DateTime('yesterday')],
[new DateTime('now')],
[new DateTime('tomorrow')],
];
/*
yield[new DateTime()];
yield[new DateTime('yesterday')];
yield[new DateTime('now')];
yield[new DateTime('tomorrow')];
*/
}
/**
* Provides relative / compound format of DateTime
*
* @return array
* //return Generator
*/
public function provideDateTimeRelativeFormat()
{
return [
['now'],
['yesterday'],
['tomorrow'],
['back of 10'],
['front of 10'],
['last day of February'],
['first day of next month'],
['last day of previous month'],
['last day of next month'],
['Y-m-d'],
['Y-m-d 10:00'],
];
/*
yield['now'];
yield['yesterday'];
yield['tomorrow'];
yield['back of 10'];
yield['front of 10'];
yield['last day of February'];
yield['first day of next month'];
yield['last day of previous month'];
yield['last day of next month'];
yield['Y-m-d'];
yield['Y-m-d 10:00'];
*/
}
/**
* Provides path of not existing file, e.g. "lorem/ipsum.jpg"
*
* @return array
* //return Generator
*/
public function provideNotExistingFilePath()
{
return [
['lets-test.doc'],
['lorem/ipsum.jpg'],
['surprise/me/one/more/time.txt'],
];
/*
yield['lets-test.doc'];
yield['lorem/ipsum.jpg'];
yield['surprise/me/one/more/time.txt'];
*/
}
/**
* Returns path of file used by tests.
* It should be placed in /.data/tests directory of this project.
*
* @param string $fileName Name of file
* @param string $directoryPath (optional) Path of directory containing the file
* @return string
*/
public function getFilePathToTests($fileName, $directoryPath = '')
{
$rootPath = Miscellaneous::getProjectRootPath();
$paths = [
$rootPath,
self::$testsDataDirPath,
$directoryPath,
$fileName,
];
return Miscellaneous::concatenatePaths($paths);
}
/**
* Verifies visibility and arguments of method
*
* @param string $classNamespace Namespace of class that contains method to verify
* @param string|ReflectionMethod $method Name of method or just the method to verify
* @param string $visibilityType Expected visibility of verified method. One of
* OopVisibilityType class constants.
* @param int $argumentsCount (optional) Expected count/amount of arguments of the
* verified method
* @param int $requiredArgumentsCount (optional) Expected count/amount of required arguments
* of the verified method
* @throws UnknownOopVisibilityTypeException
*
* Attention. 2nd argument, the $method, may be:
* - string - name of the method
* - instance of ReflectionMethod - just the method (provided by ReflectionClass::getMethod() method)
*/
protected static function assertMethodVisibilityAndArguments(
$classNamespace,
$method,
$visibilityType,
$argumentsCount = 0,
$requiredArgumentsCount = 0
) {
/*
* Type of visibility is correct?
*/
if (!(new OopVisibilityType())->isCorrectType($visibilityType)) {
throw new UnknownOopVisibilityTypeException($visibilityType);
}
$reflection = new ReflectionClass($classNamespace);
/*
* Name of method provided only?
* Let's find instance of the method (based on reflection)
*/
if (!$method instanceof ReflectionMethod) {
$method = $reflection->getMethod($method);
}
switch ($visibilityType) {
case OopVisibilityType::IS_PUBLIC:
static::assertTrue($method->isPublic());
break;
case OopVisibilityType::IS_PROTECTED:
static::assertTrue($method->isProtected());
break;
case OopVisibilityType::IS_PRIVATE:
static::assertTrue($method->isPrivate());
break;
}
static::assertEquals($argumentsCount, $method->getNumberOfParameters());
static::assertEquals($requiredArgumentsCount, $method->getNumberOfRequiredParameters());
}
/**
* Verifies visibility and arguments of class constructor
*
* @param string $classNamespace Namespace of class that contains constructor to verify
* @param string $visibilityType Expected visibility of verified method. One of OopVisibilityType class
* constants.
* @param int $argumentsCount (optional) Expected count/amount of arguments of the verified method
* @param int $requiredArgumentsCount (optional) Expected count/amount of required arguments of the verified
* method
* @throws UnknownOopVisibilityTypeException
*/
protected static function assertConstructorVisibilityAndArguments(
$classNamespace,
$visibilityType,
$argumentsCount = 0,
$requiredArgumentsCount = 0
) {
/*
* Let's grab the constructor
*/
$reflection = new ReflectionClass($classNamespace);
$method = $reflection->getConstructor();
return static::assertMethodVisibilityAndArguments($classNamespace, $method, $visibilityType, $argumentsCount, $requiredArgumentsCount);
}
/**
* Asserts that class with given namespace has no constructor
*
* @param string $classNamespace Namespace of class that contains constructor to verify
*/
protected static function assertHasNoConstructor($classNamespace)
{
/*
* Let's grab the constructor
*/
$reflection = new ReflectionClass($classNamespace);
$constructor = $reflection->getConstructor();
static::assertNull($constructor);
}
/**
* Sets path of directory with data used by test cases
*
* @param string $testsDataDirPath Path of directory with data used by test cases
*/
protected static function setTestsDataDirPath($testsDataDirPath)
{
static::$testsDataDirPath = $testsDataDirPath;
}
/**
* Returns a mock object for the specified class
*
* @param string $originalClassName Name of the class to mock
* @return \PHPUnit_Framework_MockObject_MockObject
*/
protected function createMock($originalClassName)
{
$methods = [];
$arguments = [];
$mockClassName = '';
$callOriginalConstructor = false;
return $this->getMock($originalClassName, $methods, $arguments, $mockClassName, $callOriginalConstructor);
}
}

View File

@@ -0,0 +1,64 @@
<?php
namespace Meritoo\Common\Test\Base;
use Generator;
use Meritoo\Common\Type\Base\BaseType;
/**
* Base test case for the type of something
*
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl>
* @copyright Meritoo.pl
*/
abstract class BaseTypeTestCase extends BaseTestCase
{
/**
* Verifies availability of all types
*/
public function testAvailabilityOfAllTypes()
{
$available = $this->getTestedTypeInstance()->getAll();
$all = $this->getAllExpectedTypes();
if (isset($available['className'])) {
unset($available['className']);
}
static::assertEquals($all, $available);
}
/**
* Verifies whether given type is correct or not
*
* @param string $type Type to verify
* @param bool $expected Information if given type is correct or not
*
* @dataProvider provideTypeToVerify
*/
public function testIfGivenTypeIsCorrect($type, $expected)
{
static::assertEquals($expected, $this->getTestedTypeInstance()->isCorrectType($type));
}
/**
* Provides type to verify and information if it's correct
*
* @return Generator
*/
abstract public function provideTypeToVerify();
/**
* Returns instance of the tested type
*
* @return BaseType
*/
abstract protected function getTestedTypeInstance();
/**
* Returns all expected types of the tested type
*
* @return array
*/
abstract protected function getAllExpectedTypes();
}

View File

@@ -0,0 +1,53 @@
<?php
/**
* (c) Meritoo.pl, http://www.meritoo.pl
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Meritoo\Common\Type\Base;
use Meritoo\Common\Utilities\Reflection;
/**
* Base / abstract type of something, e.g. type of button, order, date etc.
* Child class should contain constants - each of them represent one type.
*
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl>
* @copyright Meritoo.pl
*/
abstract class BaseType
{
/**
* All types
*
* @var array
*/
private $all;
/**
* Returns all types
*
* @return array
*/
public function getAll()
{
if (null === $this->all) {
$this->all = Reflection::getConstants($this);
}
return $this->all;
}
/**
* Returns information if given type is correct
*
* @param string $type The type to check
* @return bool
*/
public function isCorrectType($type)
{
return in_array($type, $this->getAll(), true);
}
}

View File

@@ -0,0 +1,62 @@
<?php
/**
* (c) Meritoo.pl, http://www.meritoo.pl
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Meritoo\Common\Type;
use Meritoo\Common\Type\Base\BaseType;
/**
* Type of date part, e.g. "year"
*
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl>
* @copyright Meritoo.pl
*/
class DatePartType extends BaseType
{
/**
* The "day" date part
*
* @var string
*/
const DAY = 'day';
/**
* The "hour" date part
*
* @var string
*/
const HOUR = 'hour';
/**
* The "minute" date part
*
* @var string
*/
const MINUTE = 'minute';
/**
* The "month" date part
*
* @var string
*/
const MONTH = 'month';
/**
* The "second" date part
*
* @var string
*/
const SECOND = 'second';
/**
* The "year" date part
*
* @var string
*/
const YEAR = 'year';
}

View File

@@ -0,0 +1,37 @@
<?php
namespace Meritoo\Common\Type;
use Meritoo\Common\Type\Base\BaseType;
/**
* The visibility of a property, a method or (as of PHP 7.1.0) a constant
*
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl>
* @copyright Meritoo.pl
*
* @see http://php.net/manual/en/language.oop5.visibility.php
*/
class OopVisibilityType extends BaseType
{
/**
* The "private" visibility of OOP
*
* @var int
*/
const IS_PRIVATE = 3;
/**
* The "protected" visibility of OOP
*
* @var int
*/
const IS_PROTECTED = 2;
/**
* The "public" visibility of OOP
*
* @var int
*/
const IS_PUBLIC = 1;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,714 @@
<?php
/**
* (c) Meritoo.pl, http://www.meritoo.pl
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Meritoo\Common\Utilities;
use DateInterval;
use DateTime;
use Meritoo\Common\Exception\Date\UnknownDatePartTypeException;
use Meritoo\Common\Type\DatePartType;
/**
* Useful date methods
*
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl>
* @copyright Meritoo.pl
*/
class Date
{
/**
* The 'days' unit of date difference.
* Difference between dates in days.
*
* @var string
*/
const DATE_DIFFERENCE_UNIT_DAYS = 'days';
/**
* The 'hours' unit of date difference.
* Difference between dates in hours.
*
* @var string
*/
const DATE_DIFFERENCE_UNIT_HOURS = 'hours';
/**
* The 'minutes' unit of date difference.
* Difference between dates in minutes.
*
* @var string
*/
const DATE_DIFFERENCE_UNIT_MINUTES = 'minutes';
/**
* The 'months' unit of date difference.
* Difference between dates in months.
*
* @var string
*/
const DATE_DIFFERENCE_UNIT_MONTHS = 'months';
/**
* The 'years' unit of date difference.
* Difference between dates in years.
*
* @var string
*/
const DATE_DIFFERENCE_UNIT_YEARS = 'years';
/**
* Returns start and end date for given period.
* The dates are returned in an array with indexes 'start' and 'end'.
*
* @param int $period The period, type of period. One of DatePeriod class constants, e.g. DatePeriod::LAST_WEEK.
* @return DatePeriod
*/
public static function getDatesForPeriod($period)
{
$datePeriod = null;
if (DatePeriod::isCorrectPeriod($period)) {
$dateStart = null;
$dateEnd = null;
switch ($period) {
case DatePeriod::LAST_WEEK:
$thisWeekStart = new DateTime('this week');
$dateStart = clone $thisWeekStart;
$dateEnd = clone $thisWeekStart;
$dateStart->sub(new DateInterval('P7D'));
$dateEnd->sub(new DateInterval('P1D'));
break;
case DatePeriod::THIS_WEEK:
$dateStart = new DateTime('this week');
$dateEnd = clone $dateStart;
$dateEnd->add(new DateInterval('P6D'));
break;
case DatePeriod::NEXT_WEEK:
$dateStart = new DateTime('this week');
$dateStart->add(new DateInterval('P7D'));
$dateEnd = clone $dateStart;
$dateEnd->add(new DateInterval('P6D'));
break;
case DatePeriod::LAST_MONTH:
$dateStart = new DateTime('first day of last month');
$dateEnd = new DateTime('last day of last month');
break;
case DatePeriod::THIS_MONTH:
$lastMonth = self::getDatesForPeriod(DatePeriod::LAST_MONTH);
$nextMonth = self::getDatesForPeriod(DatePeriod::NEXT_MONTH);
$dateStart = $lastMonth->getEndDate();
$dateStart->add(new DateInterval('P1D'));
$dateEnd = $nextMonth->getStartDate();
$dateEnd->sub(new DateInterval('P1D'));
break;
case DatePeriod::NEXT_MONTH:
$dateStart = new DateTime('first day of next month');
$dateEnd = new DateTime('last day of next month');
break;
case DatePeriod::LAST_YEAR:
case DatePeriod::THIS_YEAR:
case DatePeriod::NEXT_YEAR:
$dateStart = new DateTime();
$dateEnd = new DateTime();
if (DatePeriod::LAST_YEAR == $period || DatePeriod::NEXT_YEAR == $period) {
$yearDifference = 1;
if (DatePeriod::LAST_YEAR == $period) {
$yearDifference *= -1;
}
$modifyString = sprintf('%s year', $yearDifference);
$dateStart->modify($modifyString);
$dateEnd->modify($modifyString);
}
$year = $dateStart->format('Y');
$dateStart->setDate($year, 1, 1);
$dateEnd->setDate($year, 12, 31);
break;
}
if (null !== $dateStart && null !== $dateEnd) {
$dateStart->setTime(0, 0, 0);
$dateEnd->setTime(23, 59, 59);
$datePeriod = new DatePeriod($dateStart, $dateEnd);
}
}
return $datePeriod;
}
/**
* Generates and returns random time (the hour, minute and second values)
*
* @param string $format (optional) Format of returned value. A string acceptable by the DateTime::format()
* method.
* @return string|null
*/
public static function generateRandomTime($format = 'H:i:s')
{
$dateTime = new DateTime();
/*
* Format si empty or is incorrect?
* Nothing to do
*/
if (empty($format) || $dateTime->format($format) === $format) {
return null;
}
$hours = [];
$minutes = [];
$seconds = [];
for ($i = 1; $i <= 23; ++$i) {
$hours[] = $i;
}
for ($i = 1; $i <= 59; ++$i) {
$minutes[] = $i;
}
for ($i = 1; $i <= 59; ++$i) {
$seconds[] = $i;
}
/*
* Prepare random time (hour, minute and second)
*/
$hour = $hours[array_rand($hours)];
$minute = $minutes[array_rand($minutes)];
$second = $seconds[array_rand($seconds)];
return $dateTime
->setTime($hour, $minute, $second)
->format($format);
}
/**
* Returns current day of week
*
* @return int
*/
public static function getCurrentDayOfWeek()
{
$now = new DateTime();
$year = $now->format('Y');
$month = $now->format('m');
$day = $now->format('d');
return self::getDayOfWeek($year, $month, $day);
}
/**
* Returns day of week (number 0 to 6, 0 - sunday, 6 - saturday).
* Based on the Zeller's algorithm (http://pl.wikipedia.org/wiki/Kalendarz_wieczny).
*
* @param int $year The year value
* @param int $month The month value
* @param int $day The day value
*
* @return int
* @throws UnknownDatePartTypeException
*/
public static function getDayOfWeek($year, $month, $day)
{
$year = (int)$year;
$month = (int)$month;
$day = (int)$day;
/*
* Oops, incorrect year
*/
if ($year <= 0) {
throw new UnknownDatePartTypeException(DatePartType::YEAR, $year);
}
/*
* Oops, incorrect month
*/
if ($month < 1 || $month > 12) {
throw new UnknownDatePartTypeException(DatePartType::MONTH, $month);
}
/*
* Oops, incorrect day
*/
if ($day < 1 || $day > 31) {
throw new UnknownDatePartTypeException(DatePartType::DAY, $day);
}
if ($month < 3) {
$count = 0;
$yearValue = $year - 1;
} else {
$count = 2;
$yearValue = $year;
}
$firstPart = floor(23 * $month / 9);
$secondPart = floor($yearValue / 4);
$thirdPart = floor($yearValue / 100);
$fourthPart = floor($yearValue / 400);
return ($firstPart + $day + 4 + $year + $secondPart - $thirdPart + $fourthPart - $count) % 7;
}
/**
* Returns based on locale name of current weekday
*
* @return string
*/
public static function getCurrentDayOfWeekName()
{
$now = new DateTime();
$year = $now->format('Y');
$month = $now->format('m');
$day = $now->format('d');
return self::getDayOfWeekName($year, $month, $day);
}
/**
* Returns name of weekday based on locale
*
* @param int $year The year value
* @param int $month The month value
* @param int $day The day value
* @return string
*/
public static function getDayOfWeekName($year, $month, $day)
{
$hour = 0;
$minute = 0;
$second = 0;
$time = mktime($hour, $minute, $second, $month, $day, $year);
$name = strftime('%A', $time);
$encoding = mb_detect_encoding($name);
if (false === $encoding) {
$name = mb_convert_encoding($name, 'UTF-8', 'ISO-8859-2');
}
return $name;
}
/**
* Returns difference between given dates.
*
* The difference is calculated in units based on the 3rd argument or all available unit of date difference
* (defined as DATE_DIFFERENCE_UNIT_* constants of this class).
*
* The difference is also whole / complete value for given unit instead of relative value as may be received by
* DateTime::diff() method, e.g.:
* - 2 days, 50 hours
* instead of
* - 2 days, 2 hours
*
* If the unit of date difference is null, all units are returned in array (units are keys of the array).
* Otherwise - one, integer value is returned.
*
* @param string|DateTime $dateStart The start date
* @param string|DateTime $dateEnd The end date
* @param int $differenceUnit (optional) Unit of date difference. One of this class
* DATE_DIFFERENCE_UNIT_* constants. If is set to null all units are
* returned in the array.
* @return array|int
*/
public static function getDateDifference($dateStart, $dateEnd, $differenceUnit = null)
{
$validDateStart = self::isValidDate($dateStart, true);
$validDateEnd = self::isValidDate($dateEnd, true);
/*
* The start or end date is unknown?
* or
* The start or end date is not valid date?
*
* Nothing to do
*/
if (empty($dateStart) || empty($dateEnd) || !$validDateStart || !$validDateEnd) {
return null;
}
$dateStart = self::getDateTime($dateStart, true);
$dateEnd = self::getDateTime($dateEnd, true);
$difference = [];
$dateDiff = $dateEnd->getTimestamp() - $dateStart->getTimestamp();
$daysInSeconds = 0;
$hoursInSeconds = 0;
$hourSeconds = 60 * 60;
$daySeconds = $hourSeconds * 24;
/*
* These units are related, because while calculating difference in the lowest unit, difference in the
* highest unit is required, e.g. while calculating hours I have to know difference in days
*/
$relatedUnits = [
self::DATE_DIFFERENCE_UNIT_DAYS,
self::DATE_DIFFERENCE_UNIT_HOURS,
self::DATE_DIFFERENCE_UNIT_MINUTES,
];
if (null === $differenceUnit || self::DATE_DIFFERENCE_UNIT_YEARS == $differenceUnit) {
$diff = $dateEnd->diff($dateStart);
/*
* Difference between dates in years should be returned only?
*/
if (self::DATE_DIFFERENCE_UNIT_YEARS == $differenceUnit) {
return $diff->y;
}
$difference[self::DATE_DIFFERENCE_UNIT_YEARS] = $diff->y;
}
if (null === $differenceUnit || self::DATE_DIFFERENCE_UNIT_MONTHS == $differenceUnit) {
$diff = $dateEnd->diff($dateStart);
/*
* Difference between dates in months should be returned only?
*/
if (self::DATE_DIFFERENCE_UNIT_MONTHS == $differenceUnit) {
return $diff->m;
}
$difference[self::DATE_DIFFERENCE_UNIT_MONTHS] = $diff->m;
}
if (null === $differenceUnit || in_array($differenceUnit, $relatedUnits)) {
$days = (int)floor($dateDiff / $daySeconds);
/*
* Difference between dates in days should be returned only?
*/
if (self::DATE_DIFFERENCE_UNIT_DAYS == $differenceUnit) {
return $days;
}
/*
* All units should be returned?
*/
if (null === $differenceUnit) {
$difference[self::DATE_DIFFERENCE_UNIT_DAYS] = $days;
}
/*
* Calculation for later usage
*/
$daysInSeconds = $days * $daySeconds;
}
if (null === $differenceUnit || in_array($differenceUnit, $relatedUnits)) {
$hours = (int)floor(($dateDiff - $daysInSeconds) / $hourSeconds);
/*
* Difference between dates in hours should be returned only?
*/
if (self::DATE_DIFFERENCE_UNIT_HOURS == $differenceUnit) {
return $hours;
}
/*
* All units should be returned?
*/
if (null === $differenceUnit) {
$difference[self::DATE_DIFFERENCE_UNIT_HOURS] = $hours;
}
/*
* Calculation for later usage
*/
$hoursInSeconds = $hours * $hourSeconds;
}
if (null === $differenceUnit || self::DATE_DIFFERENCE_UNIT_MINUTES == $differenceUnit) {
$minutes = (int)floor(($dateDiff - $daysInSeconds - $hoursInSeconds) / 60);
/*
* Difference between dates in minutes should be returned only?
*/
if (self::DATE_DIFFERENCE_UNIT_MINUTES == $differenceUnit) {
return $minutes;
}
$difference[self::DATE_DIFFERENCE_UNIT_MINUTES] = $minutes;
}
return $difference;
}
/**
* Returns collection / set of dates for given start date and count of dates.
* Start from given date, add next, iterated value to given date interval and returns requested count of dates.
*
* @param DateTime $startDate The start date. Start of the collection / set.
* @param int $datesCount Count of dates in resulting collection / set
* @param string $intervalTemplate (optional) Template used to build date interval. It should contain "%d" as the
* placeholder which is replaced with a number that represents each iteration.
* Default: interval for days.
* @return array
*/
public static function getDatesCollection(DateTime $startDate, $datesCount, $intervalTemplate = 'P%dD')
{
$dates = [];
/*
* The template used to build date interval have to be string.
* Otherwise cannot run preg_match() function and an error occurs.
*/
if (is_string($intervalTemplate)) {
/*
* Let's verify the interval template. It should contains the "%d" placeholder and something before and
* after it.
*
* Examples:
* - P%dD
* - P%dM
* - P1Y%dMT1H
*/
$intervalPattern = '/^(\w*)\%d(\w*)$/';
$matches = [];
$matchCount = preg_match($intervalPattern, $intervalTemplate, $matches);
if ($matchCount > 0 && (!empty($matches[1]) || !empty($matches[2]))) {
$datesCount = (int)$datesCount;
for ($index = 1; $index <= $datesCount; ++$index) {
$date = clone $startDate;
$dates[$index] = $date->add(new DateInterval(sprintf($intervalTemplate, $index)));
}
}
}
return $dates;
}
/**
* Returns random date based on given start date
*
* @param DateTime $startDate The start date. Start of the random date.
* @param int $start (optional) Start of random partition
* @param int $end (optional) End of random partition
* @param string $intervalTemplate (optional) Template used to build date interval. The placeholder is replaced
* with next, iterated value.
* @return DateTime
*/
public static function getRandomDate(DateTime $startDate = null, $start = 1, $end = 100, $intervalTemplate = 'P%sD')
{
if (null === $startDate) {
$startDate = new DateTime();
}
$start = (int)$start;
$end = (int)$end;
/*
* Incorrect end of random partition?
* Use start as the end of random partition
*/
if ($end < $start) {
$end = $start;
}
$randomDate = clone $startDate;
$randomInterval = new DateInterval(sprintf($intervalTemplate, rand($start, $end)));
return $randomDate->add($randomInterval);
}
/**
* Returns the DateTime object for given value.
* If the DateTime object cannot be created, false is returned.
*
* @param mixed $value The value which maybe is a date
* @param bool $allowCompoundFormats (optional) If is set to true, the compound formats used to create an
* instance of DateTime class are allowed (e.g. "now", "last day of next
* month", "yyyy"). Otherwise - not and every incorrect value is refused.
* @param string $dateFormat (optional) Format of date used to verify if given value is actually a date.
* It should be format matched to the given value, e.g. "Y-m-d H:i" for
* "2015-01-01 10:00" value.
* @return DateTime|bool
*/
public static function getDateTime($value, $allowCompoundFormats = false, $dateFormat = 'Y-m-d')
{
/*
* Empty value?
* Nothing to do :)
*/
if (empty($value)) {
return false;
}
/*
* Instance of DateTime class?
* Nothing to do :)
*/
if ($value instanceof DateTime) {
return $value;
}
try {
try {
/*
* Pass the value to the constructor. Maybe it's one of the allowed relative formats.
* Examples: "now", "last day of next month"
*/
$date = new DateTime($value);
/*
* Instance of the DateTime class was created.
* Let's verify if given value is really proper date.
*/
$dateFromFormat = DateTime::createFromFormat($dateFormat, $value);
if (false === $dateFromFormat) {
/*
* Nothing to do more, because:
* a) instance of the DateTime was created
* and
* b) if createFromFormat() method failed, given value is one of the allowed relative formats
* ("now", "last day of next month")
* and...
*/
if ($allowCompoundFormats) {
/*
* ...and
* c) it's not an integer, e.g. not 10 or 100 or 1000
*/
if (!is_numeric($value)) {
return $date;
}
} else {
$specialFormats = [
'now',
];
/*
* ...and
* c) it's special compound format that contains characters that each may be used by
* DateTime::format() method and it raises problem while trying to verify the value at the end
* of this method:
*
* (new DateTime())->format($value);
*
* So, I have to refuse those special compound formats if they are not explicitly declared as
* compound (2nd argument of this method, set to false by default)
*/
if (in_array($value, $specialFormats)) {
return false;
}
}
} /*
* Verify instance of the DateTime created by constructor and by createFromFormat() method.
* After formatting, these dates should be the same.
*/
else {
if ($dateFromFormat->format($dateFormat) === $value) {
return $date;
}
}
} catch (\Exception $exception) {
if (!$allowCompoundFormats) {
return false;
}
}
/*
* Does the value is a string that may be used to format date?
* Example: "Y-m-d"
*/
$dateString = (new DateTime())->format($value);
if ($dateString != $value) {
return new DateTime($dateString);
}
} catch (\Exception $exception) {
}
return false;
}
/**
* Returns information if given value is valid date
*
* @param mixed $value The value which maybe is a date
* @param bool $allowCompoundFormats (optional) If is set to true, the compound formats used to create an
* instance of DateTime class are allowed (e.g. "now", "last day of next
* month", "yyyy"). Otherwise - not and every incorrect value is refused.
* @return bool
*/
public static function isValidDate($value, $allowCompoundFormats = false)
{
return self::getDateTime($value, $allowCompoundFormats) instanceof DateTime;
}
/**
* Returns information if given format of date is valid
*
* @param string $format The validated format of date
* @return bool
*/
public static function isValidDateFormat($format)
{
if (empty($format) || !is_string($format)) {
return false;
}
/*
* Datetime to string
*/
$formatted = (new DateTime())->format($format);
/*
* Formatted date it's the format who is validated?
* The format is invalid
*/
if ($formatted == $format) {
return false;
}
/*
* Validate the format used to create the datetime
*/
$fromFormat = DateTime::createFromFormat($format, $formatted);
/*
* It's instance of DateTime?
* The format is valid
*/
if ($fromFormat instanceof DateTime) {
return true;
}
return $fromFormat instanceof DateTime;
}
}

View File

@@ -0,0 +1,195 @@
<?php
/**
* (c) Meritoo.pl, http://www.meritoo.pl
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Meritoo\Common\Utilities;
use DateTime;
/**
* A date's period.
* Contains start and end date of the period.
*
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl>
* @copyright Meritoo.pl
*/
class DatePeriod
{
/**
* The period constant: last month
*
* @var int
*/
const LAST_MONTH = 4;
/**
* The period constant: last week
*
* @var int
*/
const LAST_WEEK = 1;
/**
* The period constant: last year
*
* @var int
*/
const LAST_YEAR = 7;
/**
* The period constant: next month
*
* @var int
*/
const NEXT_MONTH = 6;
/**
* The period constant: next week
*
* @var int
*/
const NEXT_WEEK = 3;
/**
* The period constant: next year
*
* @var int
*/
const NEXT_YEAR = 9;
/**
* The period constant: this month
*
* @var int
*/
const THIS_MONTH = 5;
/**
* The period constant: this week
*
* @var int
*/
const THIS_WEEK = 2;
/**
* The period constant: this year
*
* @var int
*/
const THIS_YEAR = 8;
/**
* The start date of period
*
* @var DateTime
*/
private $startDate;
/**
* The end date of period
*
* @var DateTime
*/
private $endDate;
/**
* Class constructor
*
* @param DateTime $startDate (optional) The start date of period
* @param DateTime $endDate (optional) The end date of period
*/
public function __construct(DateTime $startDate = null, DateTime $endDate = null)
{
$this->startDate = $startDate;
$this->endDate = $endDate;
}
/**
* Returns information if given period is correct
*
* @param int $period The period to verify
* @return bool
*/
public static function isCorrectPeriod($period)
{
return in_array($period, Reflection::getConstants(__CLASS__));
}
/**
* Returns formatted one of the period's date: start date or end date
*
* @param string $format Format used to format the date
* @param bool $startDate (optional) If is set to true, start date is formatted. Otherwise - end date.
* @return string
*/
public function getFormattedDate($format, $startDate = true)
{
$date = $this->getEndDate();
/*
* Start date should be formatted?
*/
if ($startDate) {
$date = $this->getStartDate();
}
/*
* Unknown date or format is invalid?
*/
if (null === $date || !Date::isValidDateFormat($format)) {
return '';
}
return $date->format($format);
}
/**
* Returns the end date of period
*
* @return DateTime
*/
public function getEndDate()
{
return $this->endDate;
}
/**
* Sets the end date of period
*
* @param DateTime $endDate (optional) The end date of period
* @return $this
*/
public function setEndDate(DateTime $endDate = null)
{
$this->endDate = $endDate;
return $this;
}
/**
* Returns the start date of period
*
* @return DateTime
*/
public function getStartDate()
{
return $this->startDate;
}
/**
* Sets the start date of period
*
* @param DateTime $startDate (optional) The start date of period
* @return $this
*/
public function setStartDate(DateTime $startDate = null)
{
$this->startDate = $startDate;
return $this;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,668 @@
<?php
/**
* (c) Meritoo.pl, http://www.meritoo.pl
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Meritoo\Common\Utilities;
use Doctrine\Common\Util\ClassUtils;
use Doctrine\Common\Util\Inflector;
use Meritoo\Common\Collection\Collection;
use Meritoo\Common\Exception\Reflection\CannotResolveClassNameException;
use Meritoo\Common\Exception\Reflection\MissingChildClassesException;
use Meritoo\Common\Exception\Reflection\TooManyChildClassesException;
use ReflectionClass;
use ReflectionException;
use ReflectionMethod;
use ReflectionObject;
use ReflectionProperty;
/**
* Useful reflection methods
*
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl>
* @copyright Meritoo.pl
*/
class Reflection
{
/**
* Returns names of methods for given class / object
*
* @param object|string $class The object or name of object's class
* @param bool $withoutInheritance (optional) If is set to true, only methods for given class are returned.
* Otherwise - all methods, with inherited methods too.
* @return array
*/
public static function getMethods($class, $withoutInheritance = false)
{
$effect = [];
$reflection = new ReflectionClass($class);
$methods = $reflection->getMethods();
if (!empty($methods)) {
$className = self::getClassName($class);
foreach ($methods as $method) {
if ($method instanceof ReflectionMethod) {
if ($withoutInheritance && $className !== $method->class) {
continue;
}
$effect[] = $method->name;
}
}
}
return $effect;
}
/**
* Returns constants of given class / object
*
* @param object|string $class The object or name of object's class
* @return array
*/
public static function getConstants($class)
{
$reflection = new ReflectionClass($class);
return $reflection->getConstants();
}
/**
* Returns maximum constant from all constants of given class / object.
* Values of constants should be integers.
*
* @param object|string $class The object or name of object's class
* @return int|null
*/
public static function getMaxNumberConstant($class)
{
$constants = self::getConstants($class);
if (empty($constants)) {
return null;
}
$maxNumber = 0;
foreach ($constants as $constant) {
if (is_numeric($constant) && $constant > $maxNumber) {
$maxNumber = $constant;
}
}
return $maxNumber;
}
/**
* Returns information if given class / object has given method
*
* @param object|string $class The object or name of object's class
* @param string $method Name of the method to find
* @return bool
*/
public static function hasMethod($class, $method)
{
$reflection = new ReflectionClass($class);
return $reflection->hasMethod($method);
}
/**
* Returns information if given class / object has given property
*
* @param object|string $class The object or name of object's class
* @param string $property Name of the property to find
* @return bool
*/
public static function hasProperty($class, $property)
{
$reflection = new ReflectionClass($class);
return $reflection->hasProperty($property);
}
/**
* Returns information if given class / object has given constant
*
* @param object|string $class The object or name of object's class
* @param string $constant Name of the constant to find
* @return bool
*/
public static function hasConstant($class, $constant)
{
$reflection = new ReflectionClass($class);
return $reflection->hasConstant($constant);
}
/**
* Returns value of given constant
*
* @param object|string $class The object or name of object's class
* @param string $constant Name of the constant that contains a value
* @return mixed
*/
public static function getConstantValue($class, $constant)
{
$reflection = new ReflectionClass($class);
if (self::hasConstant($class, $constant)) {
return $reflection->getConstant($constant);
}
return null;
}
/**
* Returns value of given property.
* Looks for proper getter for the property.
*
* @param mixed $object Object that should contains given property
* @param string $property Name of the property that contains a value. It may be also multiple properties
* dot-separated, e.g. "invoice.user.email".
* @param bool $force (optional) If is set to true, try to retrieve value even if the object doesn't have
* property. Otherwise - not.
* @return mixed
*/
public static function getPropertyValue($object, $property, $force = false)
{
$value = null;
/*
* Property is a dot-separated string?
* Let's find all values of the chain, of the dot-separated properties
*/
if (Regex::contains($property, '.')) {
$exploded = explode('.', $property);
$property = $exploded[0];
$object = self::getPropertyValue($object, $property, $force);
/*
* Value of processed property from the chain is not null?
* Let's dig more and get proper value
*
* Required to avoid bug:
* ReflectionObject::__construct() expects parameter 1 to be object, null given
* (...)
* 4. at ReflectionObject->__construct (null)
* 5. at Reflection ::getPropertyValue (null, 'name', true)
* 6. at ListService->getItemValue (object(Deal), 'project.name', '0')
*
* while using "project.name" as property - $project has $name property ($project exists in the Deal class)
* and the $project equals null
*
* Krzysztof Niziol <krzysztof.niziol@meritoo.pl>
* 2016-11-07
*/
if (null !== $object) {
unset($exploded[0]);
$property = implode('.', $exploded);
$value = self::getPropertyValue($object, $property, $force);
}
} else {
$className = self::getClassName($object);
$reflectionProperty = null;
/*
* 1st try:
* Use \ReflectionObject class
*/
try {
$reflectionProperty = new ReflectionProperty($className, $property);
$value = $reflectionProperty->getValue($object);
} catch (ReflectionException $exception) {
/*
* 2nd try:
* Look for the get / has / is methods
*/
$class = new ReflectionObject($object);
$valueFound = false;
if ($class->hasProperty($property) || $force) {
$property = Inflector::classify($property);
$getterPrefixes = [
'get',
'has',
'is',
];
foreach ($getterPrefixes as $prefix) {
$getterName = sprintf('%s%s', $prefix, $property);
if ($class->hasMethod($getterName)) {
$method = new ReflectionMethod($object, $getterName);
/*
* Getter is not accessible publicly?
* I have to skip it, to avoid an error like this:
*
* Call to protected method My\ExtraClass::getExtraProperty() from context 'My\ExtraClass'
*/
if ($method->isProtected() || $method->isPrivate()) {
continue;
}
$value = $object->{$getterName}();
$valueFound = true;
break;
}
}
}
if (!$valueFound && null !== $reflectionProperty) {
/*
* Oops, value of the property is still unknown
*
* 3rd try:
* Let's modify accessibility of the property and try again to get value
*/
$reflectionProperty->setAccessible(true);
$value = $reflectionProperty->getValue($object);
$reflectionProperty->setAccessible(false);
}
}
}
return $value;
}
/**
* Returns values of given property for given objects.
* Looks for proper getter for the property.
*
* @param Collection|object|array $objects The objects that should contain given property. It may be also one
* object.
* @param string $property Name of the property that contains a value
* @param bool $force (optional) If is set to true, try to retrieve value even if the
* object does not have property. Otherwise - not.
* @return array
*/
public static function getPropertyValues($objects, $property, $force = false)
{
/*
* No objects?
* Nothing to do
*/
if (empty($objects)) {
return [];
}
if ($objects instanceof Collection) {
$objects = $objects->toArray();
}
$values = [];
$objects = Arrays::makeArray($objects);
foreach ($objects as $entity) {
$value = self::getPropertyValue($entity, $property, $force);
if (null !== $value) {
$values[] = $value;
}
}
return $values;
}
/**
* Returns a class name for given source
*
* @param array|object|string $source An array of objects, namespaces, object or namespace
* @param bool $withoutNamespace (optional) If is set to true, namespace is omitted. Otherwise -
* not, full name of class is returned, with namespace.
* @return string|null
*/
public static function getClassName($source, $withoutNamespace = false)
{
/*
* First argument is not proper source of class?
* Nothing to do
*/
if (empty($source) || (!is_array($source) && !is_object($source) && !is_string($source))) {
return null;
}
$name = '';
/*
* An array of objects was provided?
* Let's use first of them
*/
if (is_array($source)) {
$source = Arrays::getFirstElement($source);
}
/*
* Let's prepare name of class
*/
if (is_object($source)) {
$name = get_class($source);
} elseif (is_string($source) && (class_exists($source) || trait_exists($source))) {
$name = $source;
}
/*
* Name of class is still unknown?
* Nothing to do
*/
if (empty($name)) {
return null;
}
/*
* Namespace is not required?
* Let's return name of class only
*/
if ($withoutNamespace) {
$classOnly = Miscellaneous::getLastElementOfString($name, '\\');
if (null !== $classOnly) {
$name = $classOnly;
}
return $name;
}
return ClassUtils::getRealClass($name);
}
/**
* Returns namespace of class for given source
*
* @param array|object|string $source An array of objects, namespaces, object or namespace
* @return string
*/
public static function getClassNamespace($source)
{
$fullClassName = self::getClassName($source);
if (empty($fullClassName)) {
return '';
}
$className = self::getClassName($source, true);
if ($className == $fullClassName) {
return $className;
}
return Miscellaneous::getStringWithoutLastElement($fullClassName, '\\');
}
/**
* Returns information if given interface is implemented by given class / object
*
* @param array|object|string $source An array of objects, namespaces, object or namespace
* @param string $interface The interface that should be implemented
* @return bool
*/
public static function isInterfaceImplemented($source, $interface)
{
$className = self::getClassName($source);
$interfaces = class_implements($className);
return in_array($interface, $interfaces);
}
/**
* Returns information if given child class is a subclass of given parent class
*
* @param array|object|string $childClass The child class. An array of objects, namespaces, object or namespace.
* @param array|object|string $parentClass The parent class. An array of objects, namespaces, object or namespace.
* @return bool
*/
public static function isChildOfClass($childClass, $parentClass)
{
$childClassName = self::getClassName($childClass);
$parentClassName = self::getClassName($parentClass);
$parents = class_parents($childClassName);
if (is_array($parents)) {
return in_array($parentClassName, $parents);
}
return false;
}
/**
* Returns given object properties
*
* @param array|object|string $source An array of objects, namespaces, object or namespace
* @param int $filter (optional) Filter of properties. Uses ReflectionProperty class
* constants. By default all properties are returned.
* @param bool $includeParents (optional) If is set to true, properties of parent classes are
* included (recursively). Otherwise - not.
* @return array|ReflectionProperty
*/
public static function getProperties($source, $filter = null, $includeParents = false)
{
$className = self::getClassName($source);
$reflection = new ReflectionClass($className);
if (null === $filter) {
$filter = ReflectionProperty::IS_PRIVATE
+ ReflectionProperty::IS_PROTECTED
+ ReflectionProperty::IS_PUBLIC
+ ReflectionProperty::IS_STATIC;
}
$properties = $reflection->getProperties($filter);
$parentProperties = [];
if ($includeParents) {
$parent = self::getParentClass($source);
if (false !== $parent) {
$parentClass = $parent->getName();
$parentProperties = self::getProperties($parentClass, $filter, $includeParents);
}
}
return array_merge($properties, $parentProperties);
}
/**
* Returns a parent class or false if there is no parent class
*
* @param array|object|string $source An array of objects, namespaces, object or namespace
* @return ReflectionClass|bool
*/
public static function getParentClass($source)
{
$className = self::getClassName($source);
$reflection = new ReflectionClass($className);
return $reflection->getParentClass();
}
/**
* Returns child classes of given class.
* It's an array of namespaces of the child classes or null (if given class has not child classes).
*
* @param array|object|string $class Class who child classes should be returned. An array of objects, strings,
* object or string.
* @return array|null
* @throws CannotResolveClassNameException
*/
public static function getChildClasses($class)
{
$allClasses = get_declared_classes();
/*
* No classes?
* Nothing to do
*/
if (empty($allClasses)) {
return null;
}
$className = self::getClassName($class);
/*
* Oops, cannot resolve class
*/
if (null === $className) {
throw new CannotResolveClassNameException($class);
}
$childClasses = [];
foreach ($allClasses as $oneClass) {
if (self::isChildOfClass($oneClass, $className)) {
/*
* Attention. I have to use ClassUtils::getRealClass() method to avoid problem with the proxy / cache
* classes. Example:
* - My\ExtraBundle\Entity\MyEntity
* - Proxies\__CG__\My\ExtraBundle\Entity\MyEntity
*
* It's actually the same class, so I have to skip it.
*/
$realClass = ClassUtils::getRealClass($oneClass);
if (in_array($realClass, $childClasses)) {
continue;
}
$childClasses[] = $realClass;
}
}
return $childClasses;
}
/**
* Returns namespace of one child class which extends given class.
* Extended class should has only one child class.
*
* @param array|object|string $parentClass Class who child class should be returned. An array of objects,
* namespaces, object or namespace.
* @return mixed
*
* @throws MissingChildClassesException
* @throws TooManyChildClassesException
*/
public static function getOneChildClass($parentClass)
{
$childClasses = self::getChildClasses($parentClass);
/*
* No child classes?
* Oops, the base / parent class hasn't child class
*/
if (empty($childClasses)) {
throw new MissingChildClassesException($parentClass);
}
/*
* More than 1 child class?
* Oops, the base / parent class has too many child classes
*/
if (count($childClasses) > 1) {
throw new TooManyChildClassesException($parentClass, $childClasses);
}
return trim($childClasses[0]);
}
/**
* Returns property, the ReflectionProperty instance, of given object
*
* @param array|object|string $class An array of objects, namespaces, object or namespace
* @param string $property Name of the property
* @param int $filter (optional) Filter of properties. Uses ReflectionProperty class constants.
* By default all properties are allowed / processed.
* @return null|ReflectionProperty
*/
public static function getProperty($class, $property, $filter = null)
{
$className = self::getClassName($class);
$properties = self::getProperties($className, $filter);
if (!empty($properties)) {
/* @var $reflectionProperty ReflectionProperty */
foreach ($properties as $reflectionProperty) {
if ($reflectionProperty->getName() == $property) {
return $reflectionProperty;
}
}
}
return null;
}
/**
* Returns information if given class / object uses / implements given trait
*
* @param array|object|string $class An array of objects, namespaces, object or namespace
* @param array|string $trait An array of strings or string
* @param bool $verifyParents If is set to true, parent classes are verified if they use given
* trait. Otherwise - not.
* @return bool|null
* @throws CannotResolveClassNameException
*/
public static function usesTrait($class, $trait, $verifyParents = false)
{
$className = self::getClassName($class);
$traitName = self::getClassName($trait);
/*
* Oops, cannot resolve class
*/
if (empty($className)) {
throw new CannotResolveClassNameException($class);
}
/*
* Oops, cannot resolve trait
*/
if (empty($traitName)) {
throw new CannotResolveClassNameException($class, false);
}
$reflection = new ReflectionClass($className);
$traitsNames = $reflection->getTraitNames();
$uses = in_array($traitName, $traitsNames);
if (!$uses && $verifyParents) {
$parentClassName = self::getParentClassName($className);
if (null !== $parentClassName) {
return self::usesTrait($parentClassName, $trait, true);
}
}
return $uses;
}
/**
* Returns name of the parent class.
* If given class does not extend another, returns null.
*
* @param array|object|string $class An array of objects, namespaces, object or namespace
* @return string|null
*/
public static function getParentClassName($class)
{
$className = self::getClassName($class);
$reflection = new ReflectionClass($className);
$parentClass = $reflection->getParentClass();
if (null === $parentClass || false === $parentClass) {
return null;
}
return $parentClass->getName();
}
}

View File

@@ -0,0 +1,726 @@
<?php
/**
* (c) Meritoo.pl, http://www.meritoo.pl
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Meritoo\Common\Utilities;
use Meritoo\Common\Exception\Regex\IncorrectColorHexLengthException;
use Meritoo\Common\Exception\Regex\InvalidColorHexValueException;
/**
* Useful regular expressions methods
*
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl>
* @copyright Meritoo.pl
*/
class Regex
{
/**
* Patterns used to validate / verify values
*
* @var array
*/
private static $patterns = [
'email' => '/[\w-]{2,}@[\w-]+\.[\w]{2,}+/',
'phone' => '/^\+?[0-9 ]+$/',
'camelCasePart' => '/([a-z]|[A-Z]){1}[a-z]*/',
'urlProtocol' => '/^([a-z]+:\/\/)',
'urlDomain' => '([\da-z\.-]+)\.([a-z\.]{2,6})(\/)?([\w\.\-]*)?(\?)?([\w \.\-\/=&]*)\/?$/i',
'letterOrDigit' => '/[a-zA-Z0-9]+/',
'htmlEntity' => '/&[a-z0-9]+;/',
'fileName' => '/.+\.\w+$/',
'isQuoted' => '/^[\'"]{1}.+[\'"]{1}$/',
'windowsBasedPath' => '/^[A-Z]{1}:\\\.*$/',
'money' => '/^[-+]?\d+([\.,]{1}\d*)?$/',
'color' => '/^[a-f0-9]{6}$/i',
];
/**
* Returns information if given e-mail address is valid
*
* @param string $email E-mail address to validate / verify
* @return bool
*
* Examples:
* a) valid e-mails:
* - ni@g-m.pl
* - ni@gm.pl
* - ni@g_m.pl
* b) invalid e-mails:
* - ni@g-m.p
* - n@g-m.pl
*/
public static function isValidEmail($email)
{
$pattern = self::getEmailPattern();
return (bool)preg_match($pattern, $email);
}
/**
* Returns information if given tax ID (in polish: NIP) is valid
*
* @param string $taxidString Tax ID (NIP) string
* @return bool
*/
public static function isValidTaxid($taxidString)
{
if (!empty($taxidString)) {
$weights = [
6,
5,
7,
2,
3,
4,
5,
6,
7,
];
$taxid = preg_replace('/[\s-]/', '', $taxidString);
$sum = 0;
if (10 == strlen($taxid) && is_numeric($taxid)) {
for ($x = 0; $x <= 8; ++$x) {
$sum += $taxid[$x] * $weights[$x];
}
if ((($sum % 11) % 10) == $taxid[9]) {
return true;
}
}
}
return false;
}
/**
* Returns information if given url address is valid
*
* @param string $url The url to validate / verify
* @param bool $requireProtocol (optional) If is set to true, the protocol is required to be passed in the url.
* Otherwise - not.
* @return bool
*/
public static function isValidUrl($url, $requireProtocol = false)
{
$pattern = self::getUrlPattern($requireProtocol);
return (bool)preg_match($pattern, $url);
}
/**
* Returns information if given phone number is valid
*
* @param string $phoneNumber The phone number to validate / verify
* @return bool
*/
public static function isValidPhoneNumber($phoneNumber)
{
$pattern = self::getPhoneNumberPattern();
return (bool)preg_match($pattern, $phoneNumber);
}
/**
* Returns array values that matches given pattern (or values that keys matches)
*
* @param string $pattern Pattern to match
* @param array $dataArray The array
* @param bool $itsKeyPattern (optional) If is set to true, keys are checks if they match pattern. Otherwise -
* values are checks.
* @return array
*/
public static function getArrayValuesByPattern($pattern, $dataArray, $itsKeyPattern = false)
{
if ($itsKeyPattern) {
$effect = [];
if (!empty($dataArray)) {
$matches = [];
foreach ($dataArray as $key => $value) {
if (preg_match($pattern, $key, $matches)) {
$effect[$key] = $value;
}
}
}
return $effect;
}
return preg_grep($pattern, $dataArray);
}
/**
* Filters array by given expression and column
*
* Expression can be simple compare expression, like ' == 2', or regular expression.
* Returns filtered array.
*
* @param array $array The array that should be filtered
* @param string $arrayColumnKey Column name
* @param string $filterExpression Filter expression, e.g. '== 2' or '!= \'home\''
* @param bool $itsRegularExpression (optional) If is set to true, means that filter expression is a
* regular expression
* @return array
*/
public static function arrayFilter($array, $arrayColumnKey, $filterExpression, $itsRegularExpression = false)
{
$effect = [];
if (!empty($array)) {
$effect = $array;
foreach ($effect as $key => &$item) {
if (isset($item[$arrayColumnKey])) {
$value = $item[$arrayColumnKey];
if ($itsRegularExpression) {
$matches = [];
$pattern = '|' . $filterExpression . '|';
$matchesCount = preg_match($pattern, $value, $matches);
$remove = 0 == $matchesCount;
} else {
if ('' == $value) {
$value = '\'\'';
} elseif (is_string($value)) {
$value = '\'' . $value . '\'';
}
eval('$isTrue = ' . $value . $filterExpression . ';');
/* @var bool $isTrue */
$remove = !$isTrue;
}
if ($remove) {
unset($effect[$key]);
}
}
}
}
return $effect;
}
/**
* Perform regular expression match with many given patterns.
* Returns information if given $subject matches one or all given $patterns.
*
* @param array|string $patterns The patterns to match
* @param string $subject The string to check
* @param bool $mustAllMatch (optional) If is set to true, $subject must match all $patterns. Otherwise -
* not.
* @return bool
*/
public static function pregMultiMatch($patterns, $subject, $mustAllMatch = false)
{
$effect = false;
$patterns = Arrays::makeArray($patterns);
if (!empty($patterns)) {
if ($mustAllMatch) {
$effect = true;
}
foreach ($patterns as $pattern) {
$matches = [];
$matched = (bool)preg_match_all($pattern, $subject, $matches);
if ($mustAllMatch) {
$effect = $effect && $matched;
} else {
if ($matched) {
$effect = $matched;
break;
}
}
}
}
return $effect;
}
/**
* Returns string in human readable style generated from given camel case string / text
*
* @param string $string The string / text to convert
* @param bool $applyUpperCaseFirst (optional) If is set to true, first word / element from the converted
* string is uppercased. Otherwise - not.
* @return string
*/
public static function camelCase2humanReadable($string, $applyUpperCaseFirst = false)
{
$parts = self::getCamelCaseParts($string);
if (!empty($parts)) {
$elements = [];
foreach ($parts as $part) {
$elements[] = strtolower($part);
}
$string = implode(' ', $elements);
if ($applyUpperCaseFirst) {
$string = ucfirst($string);
}
}
return $string;
}
/**
* Returns parts of given camel case string / text
*
* @param string $string The string / text to retrieve parts
* @return array
*/
public static function getCamelCaseParts($string)
{
$pattern = self::getCamelCasePartPattern();
$matches = [];
preg_match_all($pattern, $string, $matches);
return $matches[0];
}
/**
* Returns simple, lowercase string generated from given camel case string / text
*
* @param string $string The string / text to convert
* @param string $separator (optional) Separator used to concatenate parts of the string, e.g. '-' or '_'
* @param bool $applyLowercase (optional) If is set to true, returned string will be lowercased. Otherwise - not.
* @return string
*/
public static function camelCase2simpleLowercase($string, $separator = '', $applyLowercase = true)
{
$parts = self::getCamelCaseParts($string);
if (!empty($parts)) {
$string = implode($separator, $parts);
if ($applyLowercase) {
$string = strtolower($string);
}
}
return $string;
}
/**
* Returns pattern used to validate / verify or get e-mail address
*
* @return string
*/
public static function getEmailPattern()
{
return self::$patterns['email'];
}
/**
* Returns pattern used to validate / verify or get phone number
*
* @return string
*/
public static function getPhoneNumberPattern()
{
return self::$patterns['phone'];
}
/**
* Returns pattern used to validate / verify or get camel case parts of string
*
* @return string
*/
public static function getCamelCasePartPattern()
{
return self::$patterns['camelCasePart'];
}
/**
* Returns pattern used to validate / verify or get url address
*
* @param bool $requireProtocol (optional) If is set to true, the protocol is required to be passed in the url.
* Otherwise - not.
* @return string
*/
public static function getUrlPattern($requireProtocol = false)
{
$urlProtocol = self::$patterns['urlProtocol'];
$urlDomain = self::$patterns['urlDomain'];
$protocolPatternPart = '?';
if ($requireProtocol) {
$protocolPatternPart = '';
}
return sprintf('%s%s%s', $urlProtocol, $protocolPatternPart, $urlDomain);
}
/**
* Returns information if given path is sub-path of another path, e.g. path file is owned by path of directory
*
* @param string $subPath Path to verify, probably sub-path
* @param string $path Main / parent path
* @return bool
*/
public static function isSubPathOf($subPath, $path)
{
/*
* Empty path?
* Nothing to do
*/
if (empty($path) || empty($subPath)) {
return false;
}
/*
* I have to escape all slashes (directory separators): "/" -> "\/"
*/
$prepared = preg_quote($path, '/');
/*
* Slash at the ending is optional
*/
if (self::endsWith($path, '/')) {
$prepared .= '?';
}
$pattern = sprintf('/^%s.*/', $prepared);
return (bool)preg_match($pattern, $subPath);
}
/**
* Returns pattern used to validate / verify letter or digit
*
* @return string
*/
public static function getLetterOrDigitPattern()
{
return self::$patterns['letterOrDigit'];
}
/**
* Returns information if given character is a letter or digit
*
* @param string $char Character to check
* @return bool
*/
public static function isLetterOrDigit($char)
{
$pattern = self::getLetterOrDigitPattern();
return is_scalar($char) && (bool)preg_match($pattern, $char);
}
/**
* Returns information if the string starts with given beginning / characters
*
* @param string $string String to check
* @param string $beginning The beginning of string, one or more characters
* @return bool
*/
public static function startsWith($string, $beginning)
{
if (!empty($string) && !empty($beginning)) {
if (1 == strlen($beginning) && !self::isLetterOrDigit($beginning)) {
$beginning = '\\' . $beginning;
}
$pattern = sprintf('|^%s|', $beginning);
return (bool)preg_match($pattern, $string);
}
return false;
}
/**
* Returns information if the string ends with given ending / characters
*
* @param string $string String to check
* @param string $ending The ending of string, one or more characters
* @return bool
*/
public static function endsWith($string, $ending)
{
if (1 == strlen($ending) && !self::isLetterOrDigit($ending)) {
$ending = '\\' . $ending;
}
return (bool)preg_match('|' . $ending . '$|', $string);
}
/**
* Returns information if the string starts with directory's separator
*
* @param string $string String that may contain a directory's separator at the start / beginning
* @param string $separator (optional) The directory's separator, e.g. "/". If is empty (not provided), system's
* separator is used.
* @return bool
*/
public static function startsWithDirectorySeparator($string, $separator = '')
{
if (empty($separator)) {
$separator = DIRECTORY_SEPARATOR;
}
return self::startsWith($string, $separator);
}
/**
* Returns information if the string ends with directory's separator
*
* @param string $text String that may contain a directory's separator at the end
* @param string $separator (optional) The directory's separator, e.g. "/". If is empty (not provided), system's
* separator is used.
* @return string
*/
public static function endsWithDirectorySeparator($text, $separator = '')
{
if (empty($separator)) {
$separator = DIRECTORY_SEPARATOR;
}
return self::endsWith($text, $separator);
}
/**
* Returns information if uri contains parameter
*
* @param string $uri Uri string (e.g. $_SERVER['REQUEST_URI'])
* @param string $parameterName Uri parameter name
* @return bool
*/
public static function isSetUriParameter($uri, $parameterName)
{
return (bool)preg_match('|[?&]{1}' . $parameterName . '=|', $uri); // e.g. ?name=phil&type=4 -> '$type='
}
/**
* Returns pattern used to validate / verify html entity
*
* @return string
*/
public static function getHtmlEntityPattern()
{
return self::$patterns['htmlEntity'];
}
/**
* Returns information if the string contains html entities
*
* @param string $string String to check
* @return bool
*/
public static function containsEntities($string)
{
$pattern = self::getHtmlEntityPattern();
return (bool)preg_match_all($pattern, $string);
}
/**
* Returns information if one string contains another string
*
* @param string $haystack The string to search in
* @param string $needle The string to be search for
* @return bool
*/
public static function contains($haystack, $needle)
{
if (1 == strlen($needle) && !self::isLetterOrDigit($needle)) {
$needle = '\\' . $needle;
}
return (bool)preg_match('|.*' . $needle . '.*|', $haystack);
}
/**
* Returns pattern used to validate / verify name of file
*
* @return string
*/
public static function getFileNamePattern()
{
return self::$patterns['fileName'];
}
/**
* Returns information if given name of file is a really name of file.
* Verifies if given name contains a dot and an extension, e.g. "My File 001.jpg".
*
* @param string $fileName Name of file to check. It may be path of file also.
* @return bool
*/
public static function isFileName($fileName)
{
$pattern = self::getFileNamePattern();
return (bool)preg_match($pattern, $fileName);
}
/**
* Returns pattern used to validate / verify if value is quoted (by apostrophes or quotation marks)
*
* @return string
*/
public static function getIsQuotedPattern()
{
return self::$patterns['isQuoted'];
}
/**
* Returns information if given value is quoted (by apostrophes or quotation marks)
*
* @param mixed $value The value to check
* @return bool
*/
public static function isQuoted($value)
{
$pattern = self::getIsQuotedPattern();
return is_scalar($value) && (bool)preg_match($pattern, $value);
}
/**
* Returns pattern used to validate / verify if given path is a Windows-based path, e.g. "C:\path\to\file.jpg"
*
* @return string
*/
public static function getWindowsBasedPathPattern()
{
return self::$patterns['windowsBasedPath'];
}
/**
* Returns information if given path is a Windows-based path, e.g. "C:\path\to\file.jpg"
*
* @param string $path The path to verify
* @return bool
*/
public static function isWindowsBasedPath($path)
{
$pattern = self::getWindowsBasedPathPattern();
return (bool)preg_match($pattern, $path);
}
/**
* Returns information if given NIP number is valid
*
* @param string $nip A given NIP number
* @return bool
*
* @see https://pl.wikipedia.org/wiki/NIP#Znaczenie_numeru
*/
public static function isValidNip($nip)
{
$nip = preg_replace('/[^0-9]/', '', $nip);
$invalidNips = [
'1234567890',
'0000000000',
];
if (!preg_match('/^[0-9]{10}$/', $nip) || in_array($nip, $invalidNips)) {
return false;
}
$sum = 0;
$weights = [
6,
5,
7,
2,
3,
4,
5,
6,
7,
];
for ($i = 0; $i < 9; ++$i) {
$sum += $weights[$i] * $nip[$i];
}
$modulo = $sum % 11;
$numberControl = (10 == $modulo) ? 0 : $modulo;
return $numberControl == $nip[9];
}
/**
* Returns pattern used to validate / verify if given value is money-related value
*
* @return string
*/
public static function getMoneyPattern()
{
return self::$patterns['money'];
}
/**
* Returns information if given value is valid money-related value
*
* @param mixed $value Value to verify
* @return bool
*/
public static function isValidMoneyValue($value)
{
$pattern = self::getMoneyPattern();
return (bool)preg_match($pattern, $value);
}
/**
* Returns valid given hexadecimal value of color.
* If the value is invalid, throws an exception or returns false.
*
* @param string $color Color to verify
* @param bool $throwException (optional) If is set to true, throws an exception if given color is invalid
* (default behaviour). Otherwise - not.
* @return string|bool
*
* @throws IncorrectColorHexLengthException
* @throws InvalidColorHexValueException
*/
public static function getValidColorHexValue($color, $throwException = true)
{
$color = Miscellaneous::replace($color, '/#/', '');
$length = strlen($color);
if (3 === $length) {
$color = Miscellaneous::replace($color, '/(.)(.)(.)/', '$1$1$2$2$3$3');
} else {
if (6 !== $length) {
if ($throwException) {
throw new IncorrectColorHexLengthException($color);
}
return false;
}
}
$pattern = self::$patterns['color'];
$match = (bool)preg_match($pattern, $color);
if (!$match) {
if ($throwException) {
throw new InvalidColorHexValueException($color);
}
return false;
}
return strtolower($color);
}
}

View File

@@ -16,6 +16,8 @@ namespace Meritoo\LimeSurvey\ApiClient\Base\Result;
*/
abstract class BaseItem
{
const className = 'Meritoo\LimeSurvey\ApiClient\Base\Result\BaseItem';
/**
* Class constructor
*

View File

@@ -0,0 +1,81 @@
<?php
namespace Meritoo\LimeSurvey\ApiClient\Base\Result;
/**
* Base class for participant of survey.
* Used as a foundation for short or full participant's data.
*
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl>
* @copyright Meritoo.pl
*/
abstract class BaseParticipant extends BaseItem
{
/**
* ID of the participant
*
* @var int
*/
protected $id;
/**
* First name of the participant
*
* @var string
*/
protected $firstName;
/**
* Last name of the participant
*
* @var string
*/
protected $lastName;
/**
* E-mail of the participant
*
* @var string
*/
protected $email;
/**
* Returns ID of the participant
*
* @return int
*/
public function getId()
{
return $this->id;
}
/**
* Returns first name of the participant
*
* @return string
*/
public function getFirstName()
{
return $this->firstName;
}
/**
* Returns last name of the participant
*
* @return string
*/
public function getLastName()
{
return $this->lastName;
}
/**
* Returns e-mail of the participant
*
* @return string
*/
public function getEmail()
{
return $this->email;
}
}

View File

@@ -1,35 +1,24 @@
<?php
/**
* (c) Meritoo.pl, http://www.meritoo.pl
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Meritoo\LimeSurvey\ApiClient\Result\Collection;
namespace Meritoo\LimeSurvey\ApiClient\Base\Result;
use Meritoo\Common\Collection\Collection;
use Meritoo\Common\Exception\Method\DisabledMethodException;
use Meritoo\LimeSurvey\ApiClient\Result\Item\ParticipantShort;
/**
* Collection of participants (of surveys).
* All participants grouped per survey.
*
* It's a collection of participants' collections.
* The survey ID is used as an index per each collection of participants, so they are grouped by survey.
* Base class for participants' collection
*
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl>
* @copyright Meritoo.pl
*/
class Participants extends Collection
abstract class BaseParticipantsCollection extends Collection
{
/**
* {@inheritdoc}
*/
public function add($element, $index = null)
{
throw new DisabledMethodException(__METHOD__, 'addParticipants');
throw new DisabledMethodException(__METHOD__, 'addParticipant');
}
/**
@@ -51,7 +40,7 @@ class Participants extends Collection
/**
* Adds participants of given survey
*
* @param Collection $participants Participants to add. Collection of ParticipantShort classes.
* @param Collection $participants Participants to add. Collection of ParticipantShort or Participant instances.
* @param int $surveyId ID of survey
* @return $this
*/
@@ -72,35 +61,6 @@ class Participants extends Collection
return $this;
}
/**
* Adds participant of given survey
*
* @param ParticipantShort $participant Participant to add
* @param int $surveyId ID of survey
* @return $this
*/
public function addParticipant(ParticipantShort $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
*
@@ -123,23 +83,54 @@ class Participants extends Collection
return $this[$surveyId];
}
/**
* 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();
}
/**
* Adds participant of given survey
*
* @param BaseParticipant $participant Participant to add
* @param int $surveyId ID of survey
* @return $this
*/
public function addParticipant(BaseParticipant $participant, $surveyId)
{
$this
->getBySurvey($surveyId)
->add($participant);
return $this;
}
/**
* Returns participant of given survey
*
* @param int $surveyId ID of survey
* @param string $participantEmail E-mail of searched participant
* @return ParticipantShort|null
* @return BaseParticipant|null
*/
public function getParticipantOfSurvey($surveyId, $participantEmail)
{
/* @var Collection $participants */
$participants = $this->getBySurvey($surveyId);
/*
* No participants?
* Nothing to do
*/
if ($participants->isEmpty()) {
return null;
}
/* @var ParticipantShort $participant */
foreach ($participants as $participant) {
if ($participant->getEmail() == $participantEmail) {
return $participant;

View File

@@ -24,6 +24,8 @@ use Meritoo\LimeSurvey\ApiClient\Type\MethodType;
*/
class Client
{
const className = 'Meritoo\LimeSurvey\ApiClient\Client\Client';
/**
* Configuration used while connecting to LimeSurvey's API
*

View File

@@ -19,6 +19,8 @@ use Meritoo\Common\Utilities\Regex;
*/
class ConnectionConfiguration
{
const className = 'Meritoo\LimeSurvey\ApiClient\Configuration\ConnectionConfiguration';
/**
* Base url.
* Protocol & domain.

View File

@@ -16,6 +16,8 @@ namespace Meritoo\LimeSurvey\ApiClient\Exception;
*/
class CannotProcessDataException extends \Exception
{
const className = 'Meritoo\LimeSurvey\ApiClient\Exception\CannotProcessDataException';
/**
* Reason why data cannot be processed, e.g. "Invalid user name or password"
*

View File

@@ -18,6 +18,8 @@ use Exception;
*/
class CreateSessionKeyFailedException extends Exception
{
const className = 'Meritoo\LimeSurvey\ApiClient\Exception\CreateSessionKeyFailedException';
/**
* Class constructor
*

View File

@@ -19,6 +19,8 @@ use Meritoo\LimeSurvey\ApiClient\Base\Result\BaseItem;
*/
class IncorrectClassOfResultItemException extends \Exception
{
const className = 'Meritoo\LimeSurvey\ApiClient\Exception\IncorrectClassOfResultItemException';
/**
* Class constructor
*
@@ -29,7 +31,7 @@ class IncorrectClassOfResultItemException extends \Exception
$template = 'Class %s used to create instance of one item of the result should extend %s, but it does not. Did'
. ' you forget to use proper base class?';
$message = sprintf($template, $className, BaseItem::class);
$message = sprintf($template, $className, BaseItem::className);
parent::__construct($message);
}
}

View File

@@ -19,6 +19,8 @@ use Meritoo\Common\Utilities\Arrays;
*/
class InvalidResultOfMethodRunException extends Exception
{
const className = 'Meritoo\LimeSurvey\ApiClient\Exception\InvalidResultOfMethodRunException';
/**
* Class constructor
*

View File

@@ -16,6 +16,8 @@ namespace Meritoo\LimeSurvey\ApiClient\Exception;
*/
class MissingParticipantOfSurveyException extends \Exception
{
const className = 'Meritoo\LimeSurvey\ApiClient\Exception\MissingParticipantOfSurveyException';
/**
* Class constructor
*

View File

@@ -0,0 +1,33 @@
<?php
/**
* (c) Meritoo.pl, http://www.meritoo.pl
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Meritoo\LimeSurvey\ApiClient\Exception;
/**
* An exception used when survey's summary is missing
*
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl>
* @copyright Meritoo.pl
*/
class MissingSurveySummaryException extends \Exception
{
const className = 'Meritoo\LimeSurvey\ApiClient\Exception\MissingSurveySummaryException';
/**
* Class constructor
*
* @param int $surveyId ID of survey
*/
public function __construct($surveyId)
{
$template = 'Summary of survey with ID %d is missing. Does the survey exist?';
$message = sprintf($template, $surveyId);
parent::__construct($message);
}
}

View File

@@ -20,6 +20,8 @@ use Meritoo\LimeSurvey\ApiClient\Result\Processor\ResultProcessor;
*/
class UnknownInstanceOfResultItem extends Exception
{
const className = 'Meritoo\LimeSurvey\ApiClient\Exception\UnknownInstanceOfResultItem';
/**
* Class constructor
*
@@ -31,7 +33,7 @@ class UnknownInstanceOfResultItem extends Exception
$template = 'Class name used to create instance of one item used by result the of \'%s\' LimeSurvey API\'s'
. ' method is unknown. Proper class is not mapped in %s::%s() method. Did you forget about this?';
$message = sprintf($template, $method, ResultProcessor::class, 'getItemClassName');
$message = sprintf($template, $method, ResultProcessor::className, 'getItemClassName');
parent::__construct($message);
}
}

View File

@@ -19,6 +19,8 @@ use Meritoo\LimeSurvey\ApiClient\Type\MethodType;
*/
class UnknownMethodException extends UnknownTypeException
{
const className = 'Meritoo\LimeSurvey\ApiClient\Exception\UnknownMethodException';
/**
* {@inheritdoc}
*/

View File

@@ -17,6 +17,8 @@ use Meritoo\LimeSurvey\ApiClient\Type\MethodType;
*/
class JsonRpcClientManager
{
const className = 'Meritoo\LimeSurvey\ApiClient\Manager\JsonRpcClientManager';
/**
* Configuration used while connecting to LimeSurvey's API
*

View File

@@ -13,6 +13,8 @@ use Meritoo\LimeSurvey\ApiClient\Type\SystemMethodType;
*/
class SessionManager
{
const className = 'Meritoo\LimeSurvey\ApiClient\Manager\SessionManager';
/**
* The session key.
* Used to authenticate user while connecting to LimeSurvey's API.

View File

@@ -0,0 +1,26 @@
<?php
/**
* (c) Meritoo.pl, http://www.meritoo.pl
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Meritoo\LimeSurvey\ApiClient\Result\Collection;
use Meritoo\LimeSurvey\ApiClient\Base\Result\BaseParticipantsCollection;
/**
* Collection of participants' short data.
* All participants grouped per survey.
*
* It's a collection of participants' collections.
* The survey ID is used as an index per each collection of participants, so they are grouped by survey.
*
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl>
* @copyright Meritoo.pl
*/
class Participants extends BaseParticipantsCollection
{
const className = 'Meritoo\LimeSurvey\ApiClient\Result\Collection\Participants';
}

View File

@@ -0,0 +1,36 @@
<?php
/**
* (c) Meritoo.pl, http://www.meritoo.pl
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Meritoo\LimeSurvey\ApiClient\Result\Collection;
use Meritoo\LimeSurvey\ApiClient\Base\Result\BaseParticipantsCollection;
/**
* Collection of participants' full data.
* All participants grouped per survey.
*
* It's a collection of participants' collections.
* The survey ID is used as an index per each collection of participants, so they are grouped by survey.
*
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl>
* @copyright Meritoo.pl
*/
class ParticipantsDetails extends BaseParticipantsCollection
{
/**
* Returns information if survey with given ID has participant with given e-mail address
*
* @param int $surveyId ID of survey
* @param string $participantEmail E-mail of searched participant
* @return bool
*/
public function hasParticipantOfSurvey($surveyId, $participantEmail)
{
return null !== $this->getParticipantOfSurvey($surveyId, $participantEmail);
}
}

View File

@@ -19,6 +19,8 @@ use Meritoo\LimeSurvey\ApiClient\Result\Item\Survey;
*/
class Surveys extends Collection
{
const className = 'Meritoo\LimeSurvey\ApiClient\Result\Collection\Surveys';
/**
* {@inheritdoc}
*/

View File

@@ -0,0 +1,118 @@
<?php
/**
* (c) Meritoo.pl, http://www.meritoo.pl
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Meritoo\LimeSurvey\ApiClient\Result\Collection;
use Meritoo\Common\Collection\Collection;
use Meritoo\Common\Exception\Method\DisabledMethodException;
use Meritoo\LimeSurvey\ApiClient\Result\Item\SurveySummary;
/**
* Collection of surveys' summaries (the SurveySummary class instances)
*
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl>
* @copyright Meritoo.pl
*/
class SurveysSummaries extends Collection
{
const className = 'Meritoo\LimeSurvey\ApiClient\Result\Collection\SurveysSummaries';
/**
* {@inheritdoc}
*/
public function add($element, $index = null)
{
throw new DisabledMethodException(__METHOD__, 'addSurveySummary');
}
/**
* {@inheritdoc}
*/
public function addMultiple($elements, $useIndexes = false)
{
throw new DisabledMethodException(__METHOD__, 'addSurveysSummaries');
}
/**
* {@inheritdoc}
*/
public function has($element)
{
throw new DisabledMethodException(__METHOD__, 'hasSurveySummary');
}
/**
* Adds survey's summary
*
* @param SurveySummary $summary Survey's summary
* @param int $surveyId ID of survey
* @return $this
*/
public function addSurveySummary(SurveySummary $summary, $surveyId)
{
$this[$surveyId] = $summary;
return $this;
}
/**
* Adds surveys' summaries
*
* @param array $summaries Surveys' summaries to add
* @return $this
*/
public function addSurveysSummaries(array $summaries)
{
/*
* No summaries?
* Nothing to do
*/
if (empty($summaries)) {
return $this;
}
foreach ($summaries as $surveyId => $summary) {
$this->addSurveySummary($summary, $surveyId);
}
return $this;
}
/**
* Returns information if there is summary of survey with given ID
*
* @param int $surveyId ID of survey
* @return bool
*/
public function hasSurveySummary($surveyId)
{
/*
* There are no surveys' summaries or there is no summary of survey with given ID?
*/
if ($this->isEmpty() || !isset($this[$surveyId])) {
return false;
}
return true;
}
/**
* Returns summary of survey with given ID
*
* @param int $surveyId ID of survey
* @return SurveySummary|null
*/
public function getSurveySummary($surveyId)
{
if ($this->hasSurveySummary($surveyId)) {
return $this[$surveyId];
}
return null;
}
}

View File

@@ -10,7 +10,7 @@ namespace Meritoo\LimeSurvey\ApiClient\Result\Item;
use DateTime;
use Meritoo\Common\Utilities\Date;
use Meritoo\LimeSurvey\ApiClient\Base\Result\BaseItem;
use Meritoo\LimeSurvey\ApiClient\Base\Result\BaseParticipant;
/**
* One item of the result/data: full data of one participant
@@ -18,14 +18,9 @@ use Meritoo\LimeSurvey\ApiClient\Base\Result\BaseItem;
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl>
* @copyright Meritoo.pl
*/
class Participant extends BaseItem
class Participant extends BaseParticipant
{
/**
* ID of the participant
*
* @var int
*/
private $id;
const className = 'Meritoo\LimeSurvey\ApiClient\Result\Item\Participant';
/**
* Another ID of the participant?
@@ -42,27 +37,6 @@ class Participant extends BaseItem
*/
private $mpId;
/**
* First name of the participant
*
* @var string
*/
private $firstName;
/**
* Last name of the participant
*
* @var string
*/
private $lastName;
/**
* E-mail of the participant
*
* @var string
*/
private $email;
/**
* Status of the e-mail
*
@@ -199,7 +173,12 @@ class Participant extends BaseItem
break;
case 'completed':
$this->completed = 'Y' === trim(strtoupper($value));
if ('N' === trim(strtoupper($value))) {
$this->completed = false;
break;
}
$this->completed = Date::isValidDate($value, true);
break;
case 'usesleft':
@@ -211,7 +190,7 @@ class Participant extends BaseItem
break;
}
$this->validFrom = Date::getDateTime($value, false, 'Y-m-d H:i:s');
$this->validFrom = Date::getDateTime($value, true);
break;
case 'validuntil':
@@ -219,21 +198,11 @@ class Participant extends BaseItem
break;
}
$this->validUntil = Date::getDateTime($value, false, 'Y-m-d H:i:s');
$this->validUntil = Date::getDateTime($value, true);
break;
}
}
/**
* Returns ID of the participant
*
* @return int
*/
public function getId()
{
return $this->id;
}
/**
* Returns another ID of the participant?
* Don't know where it is used.
@@ -255,36 +224,6 @@ class Participant extends BaseItem
return $this->mpId;
}
/**
* Returns first name of the participant
*
* @return string
*/
public function getFirstName()
{
return $this->firstName;
}
/**
* Returns last name of the participant
*
* @return string
*/
public function getLastName()
{
return $this->lastName;
}
/**
* Returns e-mail of the participant
*
* @return string
*/
public function getEmail()
{
return $this->email;
}
/**
* Returns status of the e-mail
*

View File

@@ -8,7 +8,7 @@
namespace Meritoo\LimeSurvey\ApiClient\Result\Item;
use Meritoo\LimeSurvey\ApiClient\Base\Result\BaseItem;
use Meritoo\LimeSurvey\ApiClient\Base\Result\BaseParticipant;
/**
* One item of the result/data: short data of one participant
@@ -16,35 +16,9 @@ use Meritoo\LimeSurvey\ApiClient\Base\Result\BaseItem;
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl>
* @copyright Meritoo.pl
*/
class ParticipantShort extends BaseItem
class ParticipantShort extends BaseParticipant
{
/**
* ID of the participant
*
* @var int
*/
private $id;
/**
* First name of the participant
*
* @var string
*/
private $firstName;
/**
* Last name of the participant
*
* @var string
*/
private $lastName;
/**
* E-mail of the participant
*
* @var string
*/
private $email;
const className = 'Meritoo\LimeSurvey\ApiClient\Result\Item\ParticipantShort';
/**
* {@inheritdoc}
@@ -64,46 +38,6 @@ class ParticipantShort extends BaseItem
}
}
/**
* Returns ID of the participant
*
* @return int
*/
public function getId()
{
return $this->id;
}
/**
* Returns first name of the participant
*
* @return string
*/
public function getFirstName()
{
return $this->firstName;
}
/**
* Returns last name of the participant
*
* @return string
*/
public function getLastName()
{
return $this->lastName;
}
/**
* Returns e-mail of the participant
*
* @return string
*/
public function getEmail()
{
return $this->email;
}
/**
* Returns short data of participant created from full data of participant
*

View File

@@ -16,6 +16,8 @@ namespace Meritoo\LimeSurvey\ApiClient\Result\Item;
*/
class Question extends QuestionShort
{
const className = 'Meritoo\LimeSurvey\ApiClient\Result\Item\Question';
/**
* Available answers
*

View File

@@ -18,6 +18,8 @@ use Meritoo\LimeSurvey\ApiClient\Base\Result\BaseItem;
*/
class QuestionShort extends BaseItem
{
const className = 'Meritoo\LimeSurvey\ApiClient\Result\Item\QuestionShort';
/**
* ID of the question
*

View File

@@ -20,6 +20,8 @@ use Meritoo\LimeSurvey\ApiClient\Base\Result\BaseItem;
*/
class Survey extends BaseItem
{
const className = 'Meritoo\LimeSurvey\ApiClient\Result\Item\Survey';
/**
* ID of the survey
*
@@ -74,7 +76,7 @@ class Survey extends BaseItem
break;
}
$this->startsAt = Date::getDateTime($value, false, 'Y-m-d H:i:s');
$this->startsAt = Date::getDateTime($value, true);
break;
case 'expires':
@@ -82,7 +84,7 @@ class Survey extends BaseItem
break;
}
$this->expiresAt = Date::getDateTime($value, false, 'Y-m-d H:i:s');
$this->expiresAt = Date::getDateTime($value, true);
break;
case 'active':

View File

@@ -0,0 +1,198 @@
<?php
/**
* (c) Meritoo.pl, http://www.meritoo.pl
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Meritoo\LimeSurvey\ApiClient\Result\Item;
use Meritoo\LimeSurvey\ApiClient\Base\Result\BaseItem;
/**
* One item of the result/data: survey's summary (contains aggregated data)
*
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl>
* @copyright Meritoo.pl
*/
class SurveySummary extends BaseItem
{
const className = 'Meritoo\LimeSurvey\ApiClient\Result\Item\SurveySummary';
/**
* Count/Amount of tokens
*
* @var int
*/
private $tokenCount;
/**
* Count/Amount of invalid tokens
*
* @var int
*/
private $tokenInvalidCount;
/**
* Count/Amount of sent tokens
*
* @var int
*/
private $tokenSentCount;
/**
* Count/Amount of opted out tokens
*
* @var int
*/
private $tokenOptedOutCount;
/**
* Count/Amount of completed tokens
*
* @var int
*/
private $tokenCompletedCount;
/**
* Count/Amount of complete responses
*
* @var int
*/
private $completeResponsesCount;
/**
* Count/Amount of incomplete responses
*
* @var int
*/
private $incompleteResponsesCount;
/**
* Count/Amount of full responses
*
* @var int
*/
private $fullResponsesCount;
/**
* {@inheritdoc}
*/
public function setValue($property, $value)
{
switch ($property) {
case 'token_count':
$this->tokenCount = (int)$value;
break;
case 'token_invalid':
$this->tokenInvalidCount = (int)$value;
break;
case 'token_sent':
$this->tokenSentCount = (int)$value;
break;
case 'token_opted_out':
$this->tokenOptedOutCount = (int)$value;
break;
case 'token_completed':
$this->tokenCompletedCount = (int)$value;
break;
case 'completed_responses':
$this->completeResponsesCount = (int)$value;
break;
case 'incomplete_responses':
$this->incompleteResponsesCount = (int)$value;
break;
case 'full_responses':
$this->fullResponsesCount = (int)$value;
break;
}
}
/**
* Returns count/amount of tokens
*
* @return int
*/
public function getTokenCount()
{
return $this->tokenCount;
}
/**
* Returns count/amount of invalid tokens
*
* @return int
*/
public function getTokenInvalidCount()
{
return $this->tokenInvalidCount;
}
/**
* Returns count/amount of sent tokens
*
* @return int
*/
public function getTokenSentCount()
{
return $this->tokenSentCount;
}
/**
* Returns count/amount of opted out tokens
*
* @return int
*/
public function getTokenOptedOutCount()
{
return $this->tokenOptedOutCount;
}
/**
* Returns count/amount of completed tokens
*
* @return int
*/
public function getTokenCompletedCount()
{
return $this->tokenCompletedCount;
}
/**
* Returns count/amount of complete responses
*
* @return int
*/
public function getCompleteResponsesCount()
{
return $this->completeResponsesCount;
}
/**
* Returns count/amount of incomplete responses
*
* @return int
*/
public function getIncompleteResponsesCount()
{
return $this->incompleteResponsesCount;
}
/**
* Returns count/amount of full responses
*
* @return int
*/
public function getFullResponsesCount()
{
return $this->fullResponsesCount;
}
}

View File

@@ -17,6 +17,7 @@ use Meritoo\LimeSurvey\ApiClient\Result\Item\ParticipantShort;
use Meritoo\LimeSurvey\ApiClient\Result\Item\Question;
use Meritoo\LimeSurvey\ApiClient\Result\Item\QuestionShort;
use Meritoo\LimeSurvey\ApiClient\Result\Item\Survey;
use Meritoo\LimeSurvey\ApiClient\Result\Item\SurveySummary;
use Meritoo\LimeSurvey\ApiClient\Type\MethodType;
/**
@@ -27,6 +28,8 @@ use Meritoo\LimeSurvey\ApiClient\Type\MethodType;
*/
class ResultProcessor
{
const className = 'Meritoo\LimeSurvey\ApiClient\Result\Processor\ResultProcessor';
/**
* Returns processed data based on the raw data returned by the LimeSurvey's API
*
@@ -88,23 +91,27 @@ class ResultProcessor
switch ($method) {
case MethodType::ADD_PARTICIPANTS:
case MethodType::GET_PARTICIPANT_PROPERTIES:
$className = Participant::class;
$className = Participant::className;
break;
case MethodType::GET_QUESTION_PROPERTIES:
$className = Question::class;
$className = Question::className;
break;
case MethodType::GET_SUMMARY:
$className = SurveySummary::className;
break;
case MethodType::LIST_PARTICIPANTS:
$className = ParticipantShort::class;
$className = ParticipantShort::className;
break;
case MethodType::LIST_QUESTIONS:
$className = QuestionShort::class;
$className = QuestionShort::className;
break;
case MethodType::LIST_SURVEYS:
$className = Survey::class;
$className = Survey::className;
break;
/*
@@ -119,7 +126,7 @@ class ResultProcessor
throw new UnknownInstanceOfResultItem($method);
}
if (Reflection::isChildOfClass($className, BaseItem::class)) {
if (Reflection::isChildOfClass($className, BaseItem::className)) {
return $className;
}

View File

@@ -22,6 +22,8 @@ use Meritoo\LimeSurvey\ApiClient\Type\MethodType;
*/
class Result
{
const className = 'Meritoo\LimeSurvey\ApiClient\Result\Result';
/**
* Name of called method while talking to the LimeSurvey's API. One of the MethodType class constants.
*

View File

@@ -0,0 +1,152 @@
<?php
/**
* (c) Meritoo.pl, http://www.meritoo.pl
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Meritoo\LimeSurvey\ApiClient\Service;
use Meritoo\LimeSurvey\ApiClient\Client\Client;
use Meritoo\LimeSurvey\ApiClient\Exception\CannotProcessDataException;
use Meritoo\LimeSurvey\ApiClient\Exception\MissingParticipantOfSurveyException;
use Meritoo\LimeSurvey\ApiClient\Result\Collection\ParticipantsDetails;
use Meritoo\LimeSurvey\ApiClient\Result\Item\Participant;
use Meritoo\LimeSurvey\ApiClient\Type\MethodType;
use Meritoo\LimeSurvey\ApiClient\Type\ReasonType;
/**
* Service that serves participants
*
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl>
* @copyright Meritoo.pl
*/
class ParticipantService
{
const className = 'Meritoo\LimeSurvey\ApiClient\Service\ParticipantService';
/**
* Client of the LimeSurvey's API
*
* @var Client
*/
private $client;
/**
* Collection of participants' full data.
* All participants grouped per survey.
*
* @var ParticipantsDetails
*/
private $participantsDetails;
/**
* Class constructor
*
* @param Client $client Client of the LimeSurvey's API
* @param ParticipantsDetails $participantsDetails (optional) Collection of participants' full data. All
* participants grouped per survey.
*/
public function __construct(
Client $client,
ParticipantsDetails $participantsDetails = null
) {
if (null === $participantsDetails) {
$participantsDetails = new ParticipantsDetails();
}
$this->client = $client;
$this->participantsDetails = $participantsDetails;
}
/**
* Returns client of the LimeSurvey's API
*
* @return Client
*/
public function getClient()
{
return $this->client;
}
/**
* 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)
{
return null !== $this->getParticipantDetails($surveyId, $email);
}
/**
* Returns full data of participant with given e-mail (participant of given survey)
*
* @param int $surveyId ID of survey
* @param string $email E-mail address of the participant
* @return Participant|null
*
* @throws CannotProcessDataException
*/
public function getParticipantDetails($surveyId, $email)
{
if (!$this->participantsDetails->hasParticipantOfSurvey($surveyId, $email)) {
$participant = null;
$arguments = [
$surveyId,
[
'email' => $email,
],
];
try {
/* @var Participant $participant */
$participant = $this
->client
->run(MethodType::GET_PARTICIPANT_PROPERTIES, $arguments)
->getData();
} catch (CannotProcessDataException $exception) {
/*
* Oops, something is broken, because the reason is different than "participant was not found"
*/
if (ReasonType::NO_PARTICIPANT_PROPERTIES !== $exception->getReason()) {
throw $exception;
}
}
if (null !== $participant) {
$this->participantsDetails->addParticipant($participant, $surveyId);
}
}
$participant = $this
->participantsDetails
->getParticipantOfSurvey($surveyId, $email);
return $participant;
}
/**
* Returns information if participant with given e-mail has filled given survey
*
* @param int $surveyId ID of survey
* @param string $email E-mail address of the participant
* @return bool
*
* @throws MissingParticipantOfSurveyException
*/
public function hasParticipantFilledSurvey($surveyId, $email)
{
if ($this->hasParticipant($surveyId, $email)) {
return true === $this
->getParticipantDetails($surveyId, $email)
->isCompleted();
}
throw new MissingParticipantOfSurveyException($surveyId, $email);
}
}

View File

@@ -0,0 +1,400 @@
<?php
/**
* (c) Meritoo.pl, http://www.meritoo.pl
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Meritoo\LimeSurvey\ApiClient\Service;
use Meritoo\Common\Collection\Collection;
use Meritoo\LimeSurvey\ApiClient\Client\Client;
use Meritoo\LimeSurvey\ApiClient\Exception\CannotProcessDataException;
use Meritoo\LimeSurvey\ApiClient\Exception\MissingSurveySummaryException;
use Meritoo\LimeSurvey\ApiClient\Result\Collection\Participants;
use Meritoo\LimeSurvey\ApiClient\Result\Collection\Surveys;
use Meritoo\LimeSurvey\ApiClient\Result\Collection\SurveysSummaries;
use Meritoo\LimeSurvey\ApiClient\Result\Item\Participant;
use Meritoo\LimeSurvey\ApiClient\Result\Item\ParticipantShort;
use Meritoo\LimeSurvey\ApiClient\Result\Item\Survey;
use Meritoo\LimeSurvey\ApiClient\Result\Item\SurveySummary;
use Meritoo\LimeSurvey\ApiClient\Type\MethodType;
use Meritoo\LimeSurvey\ApiClient\Type\ReasonType;
/**
* Service that serves surveys and participants of surveys
*
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl>
* @copyright Meritoo.pl
*/
class SurveyService
{
const className = 'Meritoo\LimeSurvey\ApiClient\Service\SurveyService';
/**
* Client of the LimeSurvey's API
*
* @var Client
*/
private $client;
/**
* All surveys.
* Collection of surveys (the Survey class instances).
*
* @var Surveys
*/
private $allSurveys;
/**
* Collection of participants' short data.
* All participants grouped per survey.
*
* @var Participants
*/
private $allParticipants;
/**
* Collection of surveys' summaries (the SurveySummary class instances)
*
* @var SurveysSummaries
*/
private $surveySummaries;
/**
* Template of the url used to start survey
*
* Example:
* - url: https://your.limesurvey.instance/12345?token=q1w2e3r4t5y6
* - LimeSurvey frontend: https://your.limesurvey.instance
* - survey ID: 12345
* - token: q1w2e3r4t5y6
*
* @var string
*/
private $startSurveyUrlTemplate = '%s/%d?token=%s';
/**
* Class constructor
*
* @param Client $client Client of the LimeSurvey's API
* @param Surveys $allSurveys (optional) All surveys. Collection of surveys (the Survey class
* instances).
* @param Participants $allParticipants (optional) Collection of participants' short data. All participants
* grouped per survey.
* @param SurveysSummaries $surveysSummaries (optional) Collection of surveys' summaries (the SurveySummary class
* instances)
*/
public function __construct(
Client $client,
Surveys $allSurveys = null,
Participants $allParticipants = null,
SurveysSummaries $surveysSummaries = null
) {
if (null === $allSurveys) {
$allSurveys = new Surveys();
}
if (null === $allParticipants) {
$allParticipants = new Participants();
}
if (null === $surveysSummaries) {
$surveysSummaries = new SurveysSummaries();
}
$this->client = $client;
$this->allSurveys = $allSurveys;
$this->allParticipants = $allParticipants;
$this->surveySummaries = $surveysSummaries;
}
/**
* Returns client of the LimeSurvey's API
*
* @return Client
*/
public function getClient()
{
return $this->client;
}
/**
* Returns all surveys
*
* @param bool $onlyActive (optional) If is set to true, active surveys are returned only. Otherwise - all (default
* behaviour).
* @return Surveys
*
* @throws CannotProcessDataException
*/
public function getAllSurveys($onlyActive = false)
{
if ($this->allSurveys->isEmpty()) {
$surveys = new Surveys();
try {
$surveys = $this
->client
->run(MethodType::LIST_SURVEYS)
->getData();
} catch (CannotProcessDataException $exception) {
$reason = $exception->getReason();
/*
* Reason of the exception is different than "Oops, there is no surveys. Everything else is fine."?
* Let's throw the exception
*/
if (ReasonType::NO_SURVEYS_FOUND !== $reason) {
throw $exception;
}
}
if (null !== $surveys && $surveys instanceof Collection) {
$this->allSurveys = new Surveys($surveys->toArray());
}
}
return $this->allSurveys->getAll($onlyActive);
}
/**
* Returns information if survey with given ID exists
*
* @param int $surveyId ID of survey to verify
* @param bool $shouldBeActive (optional) If is set to true, survey should be active. If it's not, it shouldn't
* be returned, even if exists. Otherwise - it doesn't matter (default behaviour).
* @return bool
*/
public function isExistingSurvey($surveyId, $shouldBeActive = false)
{
$allSurveys = $this->getAllSurveys($shouldBeActive);
/*
* No surveys?
* Nothing to do
*/
if ($allSurveys->isEmpty()) {
return false;
}
$surveyId = (int)$surveyId;
/* @var Survey $survey */
foreach ($allSurveys as $survey) {
if ($survey->getId() == $surveyId) {
return true;
}
}
return false;
}
/**
* Returns url used to start survey for given survey and participant's token
*
* @param int $surveyId ID of survey to start
* @param string $participantToken Token of participant who would like to start survey
* @return string
*/
public function getStartSurveyUrlByToken($surveyId, $participantToken)
{
$baseUrl = $this
->client
->getConfiguration()
->getBaseUrl();
return sprintf($this->startSurveyUrlTemplate, $baseUrl, $surveyId, $participantToken);
}
/**
* Returns url used to start survey for given survey and participant
*
* @param int $surveyId ID of survey to start
* @param Participant $participant Participant who would like to start survey
* @return string
*/
public function getStartSurveyUrl($surveyId, Participant $participant)
{
return $this->getStartSurveyUrlByToken($surveyId, $participant->getToken());
}
/**
* Returns participants of given survey
*
* @param int $surveyId ID of survey
* @param bool $onlyCompleted (optional) If is set to true, participants who completed survey are returned only.
* Otherwise - all (default behaviour).
* @return Collection
*
* @throws CannotProcessDataException
*/
public function getSurveyParticipants($surveyId, $onlyCompleted = false)
{
$hasSurvey = $this
->allParticipants
->hasParticipantsOfSurvey($surveyId);
if (!$hasSurvey) {
$offset = 0;
$limit = $this->getSurveyTokenCount($surveyId);
$includeUnused = !$onlyCompleted;
$arguments = [
$surveyId,
$offset,
$limit,
$includeUnused,
];
try {
$participants = $this
->client
->run(MethodType::LIST_PARTICIPANTS, $arguments)
->getData();
} catch (CannotProcessDataException $exception) {
/*
* Oops, something is broken, because the reason is different than "there are no participants"
*/
if (ReasonType::NO_PARTICIPANTS_FOUND !== $exception->getReason()) {
throw $exception;
}
$participants = new Collection();
}
$this
->allParticipants
->addParticipants($participants, $surveyId);
}
return $this
->allParticipants
->getBySurvey($surveyId);
}
/**
* 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();
/* @var Participant $addedParticipant */
$addedParticipant = $participantCollection->getFirst();
$participants = new Collection([
ParticipantShort::fromParticipant($addedParticipant),
]);
$this
->allParticipants
->addParticipants($participants, $surveyId);
return $participantCollection->getFirst();
}
/**
* Returns short data of one participant with given e-mail (participant of given survey)
*
* @param int $surveyId ID of survey
* @param string $email E-mail address of the participant
* @return ParticipantShort|null
*/
public function getParticipant($surveyId, $email)
{
/*
* I have to get all participants of survey to avoid problem when participants exist but are not loaded
*/
$this->getSurveyParticipants($surveyId);
$participant = $this
->allParticipants
->getParticipantOfSurvey($surveyId, $email);
/* @var ParticipantShort $participant */
return $participant;
}
/**
* Returns count/amount of tokens of survey with given ID
*
* @param int $surveyId ID of survey
* @return int
*
* @throws MissingSurveySummaryException
*/
public function getSurveyTokenCount($surveyId)
{
$surveySummary = $this
->surveySummaries
->getSurveySummary($surveyId);
/*
* Unknown survey's summary?
* Let's fetch it
*/
if (null === $surveySummary) {
$surveySummary = $this->getSurveySummary($surveyId);
}
/*
* Oops, survey's summary is missing
*/
if (null === $surveySummary) {
throw new MissingSurveySummaryException($surveyId);
}
return $surveySummary->getTokenCount();
}
/**
* Returns summary of survey with given ID
*
* @param int $surveyId ID of survey
* @return SurveySummary|null
*/
private function getSurveySummary($surveyId)
{
$arguments = [
$surveyId,
];
/* @var SurveySummary $surveySummary */
$surveySummary = $this
->client
->run(MethodType::GET_SUMMARY, $arguments)
->getData();
if (null !== $surveySummary) {
$this
->surveySummaries
->addSurveySummary($surveySummary, $surveyId);
}
return $surveySummary;
}
}

View File

@@ -19,6 +19,8 @@ use Meritoo\LimeSurvey\ApiClient\Exception\UnknownMethodException;
*/
class MethodType extends BaseType
{
const className = 'Meritoo\LimeSurvey\ApiClient\Type\MethodType';
/**
* Add participants to the tokens collection of the survey
*
@@ -58,6 +60,13 @@ class MethodType extends BaseType
*/
const GET_QUESTION_PROPERTIES = 'get_question_properties';
/**
* Get survey summary, regarding token usage and survey participation
*
* @var string
*/
const GET_SUMMARY = 'get_summary';
/**
* Return the IDs and properties of token/participants of a survey
*

View File

@@ -12,6 +12,8 @@ use Meritoo\Common\Type\Base\BaseType;
*/
class ReasonType extends BaseType
{
const className = 'Meritoo\LimeSurvey\ApiClient\Type\ReasonType';
/**
* Reason of exception when there is no survey with given ID
*
@@ -26,6 +28,13 @@ class ReasonType extends BaseType
*/
const NO_PARTICIPANTS_FOUND = 'No survey participants found.';
/**
* Reason of exception when there is no participant's properties/details
*
* @var string
*/
const NO_PARTICIPANT_PROPERTIES = 'Error: No results were found based on your attributes.';
/**
* Reason of exception when there is no surveys
*

View File

@@ -18,6 +18,8 @@ use Meritoo\Common\Type\Base\BaseType;
*/
class SystemMethodType extends BaseType
{
const className = 'Meritoo\LimeSurvey\ApiClient\Type\SystemMethodType';
/**
* Create and return a session key
*

View File

@@ -1,255 +0,0 @@
<?php
/**
* (c) Meritoo.pl, http://www.meritoo.pl
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Meritoo\LimeSurvey\ApiClient\Service;
use Meritoo\Common\Collection\Collection;
use Meritoo\LimeSurvey\ApiClient\Client\Client;
use Meritoo\LimeSurvey\ApiClient\Exception\CannotProcessDataException;
use Meritoo\LimeSurvey\ApiClient\Exception\MissingParticipantOfSurveyException;
use Meritoo\LimeSurvey\ApiClient\Result\Collection\Participants;
use Meritoo\LimeSurvey\ApiClient\Result\Item\Participant;
use Meritoo\LimeSurvey\ApiClient\Result\Item\ParticipantShort;
use Meritoo\LimeSurvey\ApiClient\Type\MethodType;
use Meritoo\LimeSurvey\ApiClient\Type\ReasonType;
/**
* Service that serves participants
*
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl>
* @copyright Meritoo.pl
*/
class ParticipantService
{
/**
* Client of the LimeSurvey's API
*
* @var Client
*/
private $client;
/**
* Collection of participants (of surveys).
* All participants grouped per survey.
*
* @var Participants
*/
private $allParticipants;
/**
* Class constructor
*
* @param Client $client Client of the LimeSurvey's API
* @param Participants $allParticipants (optional) Collection of participants (of surveys). 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 client of the LimeSurvey's API
*
* @return Client
*/
public function getClient()
{
return $this->client;
}
/**
* Returns participants of given survey
*
* @param int $surveyId ID of survey
* @return Collection
*
* @throws CannotProcessDataException
*/
public function getSurveyParticipants($surveyId)
{
$hasSurvey = $this
->allParticipants
->hasParticipantsOfSurvey($surveyId);
if (!$hasSurvey) {
$arguments = [
$surveyId,
];
try {
$participants = $this
->client
->run(MethodType::LIST_PARTICIPANTS, $arguments)
->getData();
} catch (CannotProcessDataException $exception) {
$reason = $exception->getReason();
/*
* Reason of the exception is different than "Oops, there is no participants. Everything else is fine."?
* Let's throw the exception
*/
if (ReasonType::NO_PARTICIPANTS_FOUND !== $reason) {
throw $exception;
}
$participants = new Collection();
}
$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();
/* @var Participant $addedParticipant */
$addedParticipant = $participantCollection->getFirst();
$participants = new Collection([
ParticipantShort::fromParticipant($addedParticipant),
]);
$this
->allParticipants
->addParticipants($participants, $surveyId);
return $participantCollection->getFirst();
}
/**
* Returns short data of one participant with given e-mail of given survey
*
* @param int $surveyId ID of survey
* @param string $email E-mail address of the participant
* @return ParticipantShort|null
*/
public function getParticipant($surveyId, $email)
{
/*
* I have to get all participants of survey to avoid problem when participants exist but are not loaded
*/
$this->getSurveyParticipants($surveyId);
return $this
->allParticipants
->getParticipantOfSurvey($surveyId, $email);
}
/**
* Returns full data of participant with given e-mail of given survey
*
* @param int $surveyId ID of survey
* @param string $email E-mail address of the participant
* @return Participant|null
*/
public function getParticipantDetails($surveyId, $email)
{
$arguments = [
$surveyId,
[
'email' => $email,
],
];
$participant = $this
->client
->run(MethodType::GET_PARTICIPANT_PROPERTIES, $arguments)
->getData();
/* @var Participant $participant */
return $participant;
}
/**
* Returns information if participant with given e-mail has filled given survey
*
* @param int $surveyId ID of survey
* @param string $email E-mail address of the participant
* @return bool
*
* @throws MissingParticipantOfSurveyException
*/
public function hasParticipantFilledSurvey($surveyId, $email)
{
if ($this->hasParticipant($surveyId, $email)) {
$arguments = [
$surveyId,
[
'email' => $email,
],
];
/* @var Participant $participant */
$participant = $this
->client
->run(MethodType::GET_PARTICIPANT_PROPERTIES, $arguments)
->getData();
return true === $participant->isCompleted();
}
throw new MissingParticipantOfSurveyException($surveyId, $email);
}
}

View File

@@ -1,168 +0,0 @@
<?php
/**
* (c) Meritoo.pl, http://www.meritoo.pl
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Meritoo\LimeSurvey\ApiClient\Service;
use Meritoo\Common\Collection\Collection;
use Meritoo\LimeSurvey\ApiClient\Client\Client;
use Meritoo\LimeSurvey\ApiClient\Exception\CannotProcessDataException;
use Meritoo\LimeSurvey\ApiClient\Result\Collection\Surveys;
use Meritoo\LimeSurvey\ApiClient\Result\Item\Participant;
use Meritoo\LimeSurvey\ApiClient\Result\Item\Survey;
use Meritoo\LimeSurvey\ApiClient\Type\MethodType;
use Meritoo\LimeSurvey\ApiClient\Type\ReasonType;
/**
* Service that serves surveys
*
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl>
* @copyright Meritoo.pl
*/
class SurveyService
{
/**
* Client of the LimeSurvey's API
*
* @var Client
*/
private $client;
/**
* All surveys.
* Collection of surveys (the Survey class instances).
*
* @var Surveys
*/
private $allSurveys;
/**
* Template of the url used to start survey
*
* Example:
* - url: https://your.limesurvey.instance/12345?token=q1w2e3r4t5y6
* - LimeSurvey frontend: https://your.limesurvey.instance
* - survey ID: 12345
* - token: q1w2e3r4t5y6
*
* @var string
*/
private $startSurveyUrlTemplate = '%s/%d?token=%s';
/**
* Class constructor
*
* @param Client $client Client of the LimeSurvey's API
* @param Surveys $allSurveys (optional) All surveys. Collection of surveys (the Survey class instances).
*/
public function __construct(Client $client, Surveys $allSurveys = null)
{
if (null === $allSurveys) {
$allSurveys = new Surveys();
}
$this->client = $client;
$this->allSurveys = $allSurveys;
}
/**
* Returns client of the LimeSurvey's API
*
* @return Client
*/
public function getClient()
{
return $this->client;
}
/**
* Returns all surveys
*
* @param bool $onlyActive (optional) If is set to true, active surveys are returned only. Otherwise - all.
* @return Surveys
*
* @throws CannotProcessDataException
*/
public function getAllSurveys($onlyActive = false)
{
if ($this->allSurveys->isEmpty()) {
$surveys = new Surveys();
try {
$surveys = $this
->client
->run(MethodType::LIST_SURVEYS)
->getData();
} catch (CannotProcessDataException $exception) {
$reason = $exception->getReason();
/*
* Reason of the exception is different than "Oops, there is no surveys. Everything else is fine."?
* Let's throw the exception
*/
if (ReasonType::NO_SURVEYS_FOUND !== $reason) {
throw $exception;
}
}
if (null !== $surveys && $surveys instanceof Collection) {
$this->allSurveys = new Surveys($surveys->toArray());
}
}
return $this->allSurveys->getAll($onlyActive);
}
/**
* Returns information if survey with given ID exists
*
* @param int $surveyId ID of survey to verify
* @param bool $shouldBeActive (optional) If is set to true, survey should be active. If it's not, it shouldn't
* be returned, even if exists. Otherwise - it doesn't matter.
* @return bool
*/
public function isExistingSurvey($surveyId, $shouldBeActive = false)
{
$allSurveys = $this->getAllSurveys($shouldBeActive);
/*
* No surveys?
* Nothing to do
*/
if ($allSurveys->isEmpty()) {
return false;
}
$surveyId = (int)$surveyId;
/* @var Survey $survey */
foreach ($allSurveys as $survey) {
if ($survey->getId() == $surveyId) {
return true;
}
}
return false;
}
/**
* Returns url used to start survey for given survey and participant
*
* @param int $surveyId ID of survey to start
* @param Participant $participant Participant who would like to start survey
* @return string
*/
public function getStartSurveyUrl($surveyId, Participant $participant)
{
$baseUrl = $this
->client
->getConfiguration()
->getBaseUrl();
return sprintf($this->startSurveyUrlTemplate, $baseUrl, $surveyId, $participant->getToken());
}
}

View File

@@ -22,11 +22,11 @@ class BaseItemTest extends BaseTestCase
{
public function testConstructorVisibilityAndArguments()
{
static::assertConstructorVisibilityAndArguments(BaseItem::class, OopVisibilityType::IS_PUBLIC, 1, 0);
static::assertConstructorVisibilityAndArguments(BaseItem::className, OopVisibilityType::IS_PUBLIC, 1, 0);
}
public function testSetValuesVisibilityAndArguments()
{
static::assertMethodVisibilityAndArguments(BaseItem::class, 'setValues', OopVisibilityType::IS_PRIVATE, 1, 1);
static::assertMethodVisibilityAndArguments(BaseItem::className, 'setValues', OopVisibilityType::IS_PRIVATE, 1, 1);
}
}

View File

@@ -8,15 +8,12 @@
namespace Meritoo\LimeSurvey\Test\ApiClient\Client;
use Generator;
use Meritoo\Common\Test\Base\BaseTestCase;
use Meritoo\Common\Type\OopVisibilityType;
use Meritoo\LimeSurvey\ApiClient\Client\Client;
use Meritoo\LimeSurvey\ApiClient\Configuration\ConnectionConfiguration;
use Meritoo\LimeSurvey\ApiClient\Exception\UnknownMethodException;
use Meritoo\LimeSurvey\ApiClient\Manager\JsonRpcClientManager;
use Meritoo\LimeSurvey\ApiClient\Manager\SessionManager;
use Meritoo\LimeSurvey\ApiClient\Result\Result;
use Meritoo\LimeSurvey\ApiClient\Type\MethodType;
/**
@@ -36,7 +33,7 @@ class ClientTest extends BaseTestCase
public function testConstructorVisibilityAndArguments()
{
static::assertConstructorVisibilityAndArguments(Client::class, OopVisibilityType::IS_PUBLIC, 3, 1);
static::assertConstructorVisibilityAndArguments(Client::className, OopVisibilityType::IS_PUBLIC, 3, 1);
}
/**
@@ -45,7 +42,7 @@ class ClientTest extends BaseTestCase
*/
public function testRunWithIncorrectMethod($incorrectMethod)
{
$this->expectException(UnknownMethodException::class);
$this->setExpectedException('Meritoo\LimeSurvey\ApiClient\Exception\UnknownMethodException');
$client = new Client($this->configuration);
$client->run($incorrectMethod);
@@ -61,8 +58,8 @@ class ClientTest extends BaseTestCase
*/
public function testRun($method, $arguments, $debugMode, $expectedRawData)
{
$sessionManager = $this->createMock(SessionManager::class);
$rpcClientManager = $this->createMock(JsonRpcClientManager::class);
$sessionManager = $this->createMock(SessionManager::className);
$rpcClientManager = $this->createMock(JsonRpcClientManager::className);
$rpcClientManager
->expects(static::any())
@@ -78,7 +75,7 @@ class ClientTest extends BaseTestCase
);
$client = new Client($configuration, $rpcClientManager, $sessionManager);
static::assertInstanceOf(Result::class, $client->run($method, $arguments));
static::assertInstanceOf('Meritoo\LimeSurvey\ApiClient\Result\Result', $client->run($method, $arguments));
}
public function testGetConfiguration()
@@ -89,21 +86,29 @@ class ClientTest extends BaseTestCase
public function testGetRpcClientManagerVisibilityAndArguments()
{
static::assertMethodVisibilityAndArguments(Client::class, 'getRpcClientManager', OopVisibilityType::IS_PRIVATE);
static::assertMethodVisibilityAndArguments(Client::className, 'getRpcClientManager', OopVisibilityType::IS_PRIVATE);
}
public function testGetSessionManagerVisibilityAndArguments()
{
static::assertMethodVisibilityAndArguments(Client::class, 'getRpcClientManager', OopVisibilityType::IS_PRIVATE);
static::assertMethodVisibilityAndArguments(Client::className, 'getRpcClientManager', OopVisibilityType::IS_PRIVATE);
}
/**
* Provides incorrect name of method
*
* @return Generator
* @return array
* //return Generator
*/
public function provideIncorrectMethod()
{
return [
['lorem'],
['ipsum'],
[''],
];
/*
yield[
'lorem',
];
@@ -115,15 +120,39 @@ class ClientTest extends BaseTestCase
yield[
'',
];
*/
}
/**
* Provides correct name of method
*
* @return Generator
* @return array
* //return Generator
*/
public function provideMethod()
{
return [
[
MethodType::GET_PARTICIPANT_PROPERTIES,
[],
true,
[],
],
[
MethodType::LIST_SURVEYS,
[],
false,
[],
],
[
MethodType::LIST_PARTICIPANTS,
[],
false,
null,
],
];
/*
yield[
MethodType::GET_PARTICIPANT_PROPERTIES,
[],
@@ -144,6 +173,7 @@ class ClientTest extends BaseTestCase
false,
null,
];
*/
/*
* todo: Use/Verify other types of methods

View File

@@ -8,7 +8,6 @@
namespace Meritoo\LimeSurvey\Test\ApiClient\Configuration;
use Generator;
use Meritoo\Common\Exception\Regex\InvalidUrlException;
use Meritoo\Common\Test\Base\BaseTestCase;
use Meritoo\Common\Type\OopVisibilityType;
@@ -38,7 +37,7 @@ class ConnectionConfigurationTest extends BaseTestCase
public function testConstructorVisibilityAndArguments()
{
static::assertConstructorVisibilityAndArguments(ConnectionConfiguration::class, OopVisibilityType::IS_PUBLIC, 5, 3);
static::assertConstructorVisibilityAndArguments(ConnectionConfiguration::className, OopVisibilityType::IS_PUBLIC, 5, 3);
}
/**
@@ -47,7 +46,7 @@ class ConnectionConfigurationTest extends BaseTestCase
*/
public function testConstructorWithEmptyBaseUrl($emptyBaseUrl)
{
$this->expectException(InvalidUrlException::class);
$this->setExpectedException(InvalidUrlException::className);
new ConnectionConfiguration($emptyBaseUrl, '', '');
}
@@ -57,7 +56,7 @@ class ConnectionConfigurationTest extends BaseTestCase
*/
public function testConstructorWithInvalidBaseUrl($invalidBaseUrl)
{
$this->expectException(InvalidUrlException::class);
$this->setExpectedException(InvalidUrlException::className);
new ConnectionConfiguration($invalidBaseUrl, '', '');
}
@@ -94,10 +93,17 @@ class ConnectionConfigurationTest extends BaseTestCase
/**
* Provides empty base url
*
* @return Generator
* @return array
* //return Generator
*/
public function provideEmptyBaseUrl()
{
return [
[''],
[null],
];
/*
yield[
'',
];
@@ -105,15 +111,24 @@ class ConnectionConfigurationTest extends BaseTestCase
yield[
null,
];
*/
}
/**
* Provides invalid base url
*
* @return Generator
* @return array
* //return Generator
*/
public function provideInvalidBaseUrl()
{
return [
['lorem'],
['ipsum'],
['htp:/dolor.com'],
];
/*
yield[
'lorem',
];
@@ -125,6 +140,7 @@ class ConnectionConfigurationTest extends BaseTestCase
yield[
'htp:/dolor.com',
];
*/
}
/**

View File

@@ -8,7 +8,6 @@
namespace Meritoo\LimeSurvey\Test\ApiClient\Exception;
use Generator;
use Meritoo\Common\Test\Base\BaseTestCase;
use Meritoo\Common\Type\OopVisibilityType;
use Meritoo\LimeSurvey\ApiClient\Exception\CannotProcessDataException;
@@ -23,7 +22,7 @@ class CannotProcessDataExceptionTest extends BaseTestCase
{
public function testConstructorVisibilityAndArguments()
{
static::assertConstructorVisibilityAndArguments(CannotProcessDataException::class, OopVisibilityType::IS_PUBLIC, 1, 1);
static::assertConstructorVisibilityAndArguments(CannotProcessDataException::className, OopVisibilityType::IS_PUBLIC, 1, 1);
}
/**
@@ -41,12 +40,25 @@ class CannotProcessDataExceptionTest extends BaseTestCase
/**
* Provides reason why data cannot be processed
*
* @return Generator
* @return array
* //return Generator
*/
public function provideReason()
{
$template = 'Raw data returned by the LimeSurvey\'s API cannot be processed. Reason: \'%s\'.';
return [
[
'unknown',
sprintf($template, 'unknown'),
],
[
'Invalid user name or password',
sprintf($template, 'Invalid user name or password'),
],
];
/*
yield[
'unknown',
sprintf($template, 'unknown'),
@@ -56,5 +68,6 @@ class CannotProcessDataExceptionTest extends BaseTestCase
'Invalid user name or password',
sprintf($template, 'Invalid user name or password'),
];
*/
}
}

View File

@@ -8,7 +8,6 @@
namespace Meritoo\LimeSurvey\Test\ApiClient\Exception;
use Generator;
use Meritoo\Common\Test\Base\BaseTestCase;
use Meritoo\Common\Type\OopVisibilityType;
use Meritoo\LimeSurvey\ApiClient\Exception\CreateSessionKeyFailedException;
@@ -23,7 +22,7 @@ class CreateSessionKeyFailedExceptionTest extends BaseTestCase
{
public function testConstructorVisibilityAndArguments()
{
static::assertConstructorVisibilityAndArguments(CreateSessionKeyFailedException::class, OopVisibilityType::IS_PUBLIC, 1, 0);
static::assertConstructorVisibilityAndArguments(CreateSessionKeyFailedException::className, OopVisibilityType::IS_PUBLIC, 1, 0);
}
/**
@@ -41,13 +40,26 @@ class CreateSessionKeyFailedExceptionTest extends BaseTestCase
/**
* Provides reason of failure
*
* @return Generator
* @return array
* //return Generator
*/
public function provideReason()
{
$shortMessage = 'Create of the session key has failed';
$longMessageTemplate = sprintf('%s. Reason: \'%s\'.', $shortMessage, '%s');
return [
[
'',
$shortMessage,
],
[
'Invalid user name or password',
sprintf($longMessageTemplate, 'Invalid user name or password'),
],
];
/*
yield[
'',
$shortMessage,
@@ -57,5 +69,6 @@ class CreateSessionKeyFailedExceptionTest extends BaseTestCase
'Invalid user name or password',
sprintf($longMessageTemplate, 'Invalid user name or password'),
];
*/
}
}

View File

@@ -8,12 +8,9 @@
namespace Meritoo\LimeSurvey\Test\ApiClient\Exception;
use Generator;
use Meritoo\Common\Test\Base\BaseTestCase;
use Meritoo\Common\Type\OopVisibilityType;
use Meritoo\LimeSurvey\ApiClient\Base\Result\BaseItem;
use Meritoo\LimeSurvey\ApiClient\Exception\IncorrectClassOfResultItemException;
use stdClass;
/**
* Test case of an exception used while class used to create instance of one item of the result is incorrect
@@ -25,7 +22,7 @@ class IncorrectClassOfResultItemExceptionTest extends BaseTestCase
{
public function testConstructorVisibilityAndArguments()
{
static::assertConstructorVisibilityAndArguments(IncorrectClassOfResultItemException::class, OopVisibilityType::IS_PUBLIC, 1, 1);
static::assertConstructorVisibilityAndArguments(IncorrectClassOfResultItemException::className, OopVisibilityType::IS_PUBLIC, 1, 1);
}
/**
@@ -43,16 +40,26 @@ class IncorrectClassOfResultItemExceptionTest extends BaseTestCase
/**
* Provides incorrect class name used to create instance of one item
*
* @return Generator
* @return array
* //return Generator
*/
public function provideIncorrectClassName()
{
$template = 'Class %s used to create instance of one item of the result should extend %s, but it does not. Did'
. ' you forget to use proper base class?';
return [
[
'\stdClass',
sprintf($template, '\stdClass', 'Meritoo\LimeSurvey\ApiClient\Base\Result\BaseItem'),
],
];
/*
yield[
stdClass::class,
sprintf($template, stdClass::class, BaseItem::class),
];
*/
}
}

View File

@@ -9,7 +9,6 @@
namespace Meritoo\LimeSurvey\Test\ApiClient\Exception;
use Exception;
use Generator;
use Meritoo\Common\Test\Base\BaseTestCase;
use Meritoo\Common\Type\OopVisibilityType;
use Meritoo\LimeSurvey\ApiClient\Exception\InvalidResultOfMethodRunException;
@@ -25,7 +24,7 @@ class InvalidResultOfMethodRunExceptionTest extends BaseTestCase
{
public function testConstructorVisibilityAndArguments()
{
static::assertConstructorVisibilityAndArguments(InvalidResultOfMethodRunException::class, OopVisibilityType::IS_PUBLIC, 3, 2);
static::assertConstructorVisibilityAndArguments(InvalidResultOfMethodRunException::className, OopVisibilityType::IS_PUBLIC, 3, 2);
}
/**
@@ -45,7 +44,8 @@ class InvalidResultOfMethodRunExceptionTest extends BaseTestCase
/**
* Provides previous exception, name and arguments of called method
*
* @return Generator
* @return array
* //return Generator
*/
public function providePreviousExceptionAndMethod()
{
@@ -54,6 +54,26 @@ class InvalidResultOfMethodRunExceptionTest extends BaseTestCase
. "- method: %s,\n"
. '- arguments: %s.';
return [
[
new Exception('Lorem ipsum'),
MethodType::ADD_RESPONSE,
[],
sprintf($template, 'Lorem ipsum', MethodType::ADD_RESPONSE, '(no arguments)'),
],
[
new Exception('Dolor sit amet'),
MethodType::LIST_SURVEYS,
[
'fist_name' => 'John',
'last_name' => 'Scott',
'email' => 'john@scott.com',
],
sprintf($template, 'Dolor sit amet', MethodType::LIST_SURVEYS, 'fist_name="John", last_name="Scott", email="john@scott.com"'),
],
];
/*
yield[
new Exception('Lorem ipsum'),
MethodType::ADD_RESPONSE,
@@ -71,5 +91,6 @@ class InvalidResultOfMethodRunExceptionTest extends BaseTestCase
],
sprintf($template, 'Dolor sit amet', MethodType::LIST_SURVEYS, 'fist_name="John", last_name="Scott", email="john@scott.com"'),
];
*/
}
}

View File

@@ -22,7 +22,7 @@ class MissingParticipantOfSurveyExceptionTest extends BaseTestCase
{
public function testConstructorVisibilityAndArguments()
{
static::assertConstructorVisibilityAndArguments(MissingParticipantOfSurveyException::class, OopVisibilityType::IS_PUBLIC, 2, 2);
static::assertConstructorVisibilityAndArguments(MissingParticipantOfSurveyException::className, OopVisibilityType::IS_PUBLIC, 2, 2);
}
/**
@@ -38,10 +38,30 @@ class MissingParticipantOfSurveyExceptionTest extends BaseTestCase
static::assertEquals($expectedMessage, $exception->getMessage());
}
/**
* Provides ID of survey and e-mail address of the participant
*
* @return array
* //return Generator
*/
public function provideSurveyIdAndEmail()
{
$template = 'Participant with e-mail %s of survey with ID %s is missing. Maybe was not added to the survey?';
return [
[
1,
'lorem@ipsum.com',
sprintf($template, 'lorem@ipsum.com', 1),
],
[
1234,
'another@email.comm',
sprintf($template, 'another@email.comm', 1234),
],
];
/*
yield[
1,
'lorem@ipsum.com',
@@ -53,5 +73,6 @@ class MissingParticipantOfSurveyExceptionTest extends BaseTestCase
'another@email.comm',
sprintf($template, 'another@email.comm', 1234),
];
*/
}
}

View File

@@ -0,0 +1,73 @@
<?php
/**
* (c) Meritoo.pl, http://www.meritoo.pl
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Meritoo\LimeSurvey\Test\ApiClient\Exception;
use Meritoo\Common\Test\Base\BaseTestCase;
use Meritoo\Common\Type\OopVisibilityType;
use Meritoo\LimeSurvey\ApiClient\Exception\MissingSurveySummaryException;
/**
* Test case of an exception used when survey's summary is missing
*
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl>
* @copyright Meritoo.pl
*/
class MissingSurveySummaryExceptionTest extends BaseTestCase
{
public function testConstructorVisibilityAndArguments()
{
static::assertConstructorVisibilityAndArguments(MissingSurveySummaryException::className, OopVisibilityType::IS_PUBLIC, 1, 1);
}
/**
* @param int $surveyId ID of survey
* @param string $expectedMessage Expected exception's message
*
* @dataProvider provideSurveyId
*/
public function testConstructorMessage($surveyId, $expectedMessage)
{
$exception = new MissingSurveySummaryException($surveyId);
static::assertEquals($expectedMessage, $exception->getMessage());
}
/**
* Provides ID of survey
*
* @return array
* //return Generator
*/
public function provideSurveyId()
{
$template = 'Summary of survey with ID %d is missing. Does the survey exist?';
return [
[
1,
sprintf($template, 1),
],
[
'123',
sprintf($template, '123'),
],
];
/*
yield[
1,
sprintf($template, 1),
];
yield[
'123',
sprintf($template, '123'),
];
*/
}
}

View File

@@ -8,11 +8,9 @@
namespace Meritoo\LimeSurvey\Test\ApiClient\Exception;
use Generator;
use Meritoo\Common\Test\Base\BaseTestCase;
use Meritoo\Common\Type\OopVisibilityType;
use Meritoo\LimeSurvey\ApiClient\Exception\UnknownInstanceOfResultItem;
use Meritoo\LimeSurvey\ApiClient\Result\Processor\ResultProcessor;
use Meritoo\LimeSurvey\ApiClient\Type\MethodType;
/**
@@ -26,7 +24,7 @@ class UnknownInstanceOfResultItemTest extends BaseTestCase
{
public function testConstructorVisibilityAndArguments()
{
static::assertConstructorVisibilityAndArguments(UnknownInstanceOfResultItem::class, OopVisibilityType::IS_PUBLIC, 1, 1);
static::assertConstructorVisibilityAndArguments(UnknownInstanceOfResultItem::className, OopVisibilityType::IS_PUBLIC, 1, 1);
}
/**
@@ -45,13 +43,26 @@ class UnknownInstanceOfResultItemTest extends BaseTestCase
/**
* Provides name of called method
*
* @return Generator
* @return array
* //return Generator
*/
public function provideMethodName()
{
$template = 'Class name used to create instance of one item used by result the of \'%s\' LimeSurvey API\'s'
. ' method is unknown. Proper class is not mapped in %s::%s() method. Did you forget about this?';
return [
[
MethodType::LIST_SURVEYS,
sprintf($template, MethodType::LIST_SURVEYS, 'Meritoo\LimeSurvey\ApiClient\Result\Processor\ResultProcessor', 'getItemClassName'),
],
[
MethodType::ADD_PARTICIPANTS,
sprintf($template, MethodType::ADD_PARTICIPANTS, 'Meritoo\LimeSurvey\ApiClient\Result\Processor\ResultProcessor', 'getItemClassName'),
],
];
/*
yield[
MethodType::LIST_SURVEYS,
sprintf($template, MethodType::LIST_SURVEYS, ResultProcessor::class, 'getItemClassName'),
@@ -61,5 +72,6 @@ class UnknownInstanceOfResultItemTest extends BaseTestCase
MethodType::ADD_PARTICIPANTS,
sprintf($template, MethodType::ADD_PARTICIPANTS, ResultProcessor::class, 'getItemClassName'),
];
*/
}
}

View File

@@ -8,7 +8,6 @@
namespace Meritoo\LimeSurvey\Test\ApiClient\Exception;
use Generator;
use Meritoo\Common\Test\Base\BaseTestCase;
use Meritoo\Common\Type\OopVisibilityType;
use Meritoo\LimeSurvey\ApiClient\Exception\UnknownMethodException;
@@ -24,7 +23,7 @@ class UnknownMethodExceptionTest extends BaseTestCase
{
public function testConstructorVisibilityAndArguments()
{
static::assertConstructorVisibilityAndArguments(UnknownMethodException::class, OopVisibilityType::IS_PUBLIC, 1, 1);
static::assertConstructorVisibilityAndArguments(UnknownMethodException::className, OopVisibilityType::IS_PUBLIC, 1, 1);
}
/**
@@ -42,7 +41,8 @@ class UnknownMethodExceptionTest extends BaseTestCase
/**
* Provides name of called method
*
* @return Generator
* @return array
* //return Generator
*/
public function provideUnknownType()
{
@@ -51,6 +51,18 @@ class UnknownMethodExceptionTest extends BaseTestCase
$template = 'The \'%s\' type of name of method used while talking to the LimeSurvey\'s API is unknown. Probably'
. ' doesn\'t exist or there is a typo. You should use one of these types: %s.';
return [
[
MethodType::ADD_PARTICIPANTS,
sprintf($template, MethodType::ADD_PARTICIPANTS, $allMethods),
],
[
MethodType::ADD_PARTICIPANTS,
sprintf($template, MethodType::ADD_PARTICIPANTS, $allMethods),
],
];
/*
yield[
MethodType::ADD_PARTICIPANTS,
sprintf($template, MethodType::ADD_PARTICIPANTS, $allMethods),
@@ -60,5 +72,6 @@ class UnknownMethodExceptionTest extends BaseTestCase
MethodType::ADD_PARTICIPANTS,
sprintf($template, MethodType::ADD_PARTICIPANTS, $allMethods),
];
*/
}
}

View File

@@ -8,7 +8,6 @@
namespace Meritoo\LimeSurvey\Test\ApiClient\Manager;
use JsonRPC\Client as RpcClient;
use JsonRPC\Exception\InvalidJsonFormatException;
use Meritoo\Common\Test\Base\BaseTestCase;
use Meritoo\Common\Type\OopVisibilityType;
@@ -35,15 +34,15 @@ class JsonRpcClientManagerTest extends BaseTestCase
public function testConstructorVisibilityAndArguments()
{
static::assertConstructorVisibilityAndArguments(JsonRpcClientManager::class, OopVisibilityType::IS_PUBLIC, 1, 1);
static::assertConstructorVisibilityAndArguments(JsonRpcClientManager::className, OopVisibilityType::IS_PUBLIC, 1, 1);
}
public function testRunMethodWithEmptyArrayReturned()
{
$rpcClient = $this->createMock(RpcClient::class);
$rpcClient = $this->createMock('\JsonRPC\Client');
$manager = $this
->getMockBuilder(JsonRpcClientManager::class)
->getMockBuilder(JsonRpcClientManager::className)
->setConstructorArgs([
$this->configuration,
])
@@ -68,8 +67,8 @@ class JsonRpcClientManagerTest extends BaseTestCase
public function testRunMethodWithRawDataReturned()
{
$rpcClient = $this->createMock(RpcClient::class);
$manager = $this->createPartialMock(JsonRpcClientManager::class, ['getRpcClient']);
$rpcClient = $this->createMock('\JsonRPC\Client');
$manager = $this->getMock(JsonRpcClientManager::className, ['getRpcClient'], [], '', false);
$rpcClient
->expects(static::once())
@@ -87,10 +86,10 @@ class JsonRpcClientManagerTest extends BaseTestCase
public function testRunMethodWithException()
{
$this->expectException(InvalidResultOfMethodRunException::class);
$this->setExpectedException(InvalidResultOfMethodRunException::className);
$manager = $this->createPartialMock(JsonRpcClientManager::class, ['getRpcClient']);
$rpcClient = $this->createMock(RpcClient::class);
$manager = $this->getMock(JsonRpcClientManager::className, ['getRpcClient'], [], '', false);
$rpcClient = $this->createMock('\JsonRPC\Client');
$rpcClient
->expects(self::once())
@@ -108,7 +107,7 @@ class JsonRpcClientManagerTest extends BaseTestCase
public function testGetRpcClientVisibilityAndArguments()
{
static::assertMethodVisibilityAndArguments(JsonRpcClientManager::class, 'getRpcClient', OopVisibilityType::IS_PROTECTED);
static::assertMethodVisibilityAndArguments(JsonRpcClientManager::className, 'getRpcClient', OopVisibilityType::IS_PROTECTED);
}
/**

View File

@@ -24,15 +24,15 @@ class SessionManagerTest extends BaseTestCase
{
public function testConstructorVisibilityAndArguments()
{
static::assertConstructorVisibilityAndArguments(SessionManager::class, OopVisibilityType::IS_PUBLIC, 1, 1);
static::assertConstructorVisibilityAndArguments(SessionManager::className, OopVisibilityType::IS_PUBLIC, 1, 1);
}
public function testGetSessionKeyWhenFailedWithoutReason()
{
$this->expectException(CreateSessionKeyFailedException::class);
$this->expectExceptionMessage('Create of the session key has failed');
$this->setExpectedException(CreateSessionKeyFailedException::className, 'Create of the session key has failed');
//$this->expectExceptionMessage('Create of the session key has failed');
$clientManager = $this->createMock(JsonRpcClientManager::class);
$clientManager = $this->createMock(JsonRpcClientManager::className);
$clientManager
->expects(static::any())
@@ -46,10 +46,10 @@ class SessionManagerTest extends BaseTestCase
{
$reason = 'Invalid credentials';
$this->expectException(CreateSessionKeyFailedException::class);
$this->expectExceptionMessage(sprintf('Create of the session key has failed. Reason: \'%s\'.', $reason));
$this->setExpectedException(CreateSessionKeyFailedException::className, sprintf('Create of the session key has failed. Reason: \'%s\'.', $reason));
//$this->expectExceptionMessage(sprintf('Create of the session key has failed. Reason: \'%s\'.', $reason));
$clientManager = $this->createMock(JsonRpcClientManager::class);
$clientManager = $this->createMock(JsonRpcClientManager::className);
$clientManager
->expects(static::any())
@@ -63,7 +63,7 @@ class SessionManagerTest extends BaseTestCase
public function testGetSessionKey()
{
$clientManager = $this->createMock(JsonRpcClientManager::class);
$clientManager = $this->createMock(JsonRpcClientManager::className);
$clientManager
->expects(static::any())
@@ -76,7 +76,7 @@ class SessionManagerTest extends BaseTestCase
public function testReleaseSessionKey()
{
$clientManager = $this->createMock(JsonRpcClientManager::class);
$clientManager = $this->createMock(JsonRpcClientManager::className);
$clientManager
->expects(static::any())
@@ -84,6 +84,6 @@ class SessionManagerTest extends BaseTestCase
->willReturn([]);
$sessionManager = new SessionManager($clientManager);
static::assertInstanceOf(SessionManager::class, $sessionManager->releaseSessionKey());
static::assertInstanceOf(SessionManager::className, $sessionManager->releaseSessionKey());
}
}

View File

@@ -17,7 +17,7 @@ use Meritoo\LimeSurvey\ApiClient\Result\Item\Participant;
use Meritoo\LimeSurvey\ApiClient\Result\Item\ParticipantShort;
/**
* Test case of the collection of participants (of surveys)
* Test case of the collection of participants' short data
*
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl>
* @copyright Meritoo.pl
@@ -25,7 +25,7 @@ use Meritoo\LimeSurvey\ApiClient\Result\Item\ParticipantShort;
class ParticipantsTest extends BaseTestCase
{
/**
* An empty collection of participants (of surveys)
* An empty collection of participants' short data
*
* @var Participants
*/
@@ -47,24 +47,24 @@ class ParticipantsTest extends BaseTestCase
public function testConstructorVisibilityAndArguments()
{
static::assertConstructorVisibilityAndArguments(Participants::class, OopVisibilityType::IS_PUBLIC, 1, 0);
static::assertConstructorVisibilityAndArguments(Participants::className, OopVisibilityType::IS_PUBLIC, 1, 0);
}
public function testAdd()
{
$this->expectException(DisabledMethodException::class);
$this->setExpectedException(DisabledMethodException::className);
(new Participants())->add('');
}
public function testAddMultiple()
{
$this->expectException(DisabledMethodException::class);
$this->setExpectedException(DisabledMethodException::className);
(new Participants())->addMultiple([]);
}
public function testHas()
{
$this->expectException(DisabledMethodException::class);
$this->setExpectedException(DisabledMethodException::className);
(new Participants())->has(new Participant());
}

View File

@@ -0,0 +1,194 @@
<?php
/**
* (c) Meritoo.pl, http://www.meritoo.pl
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Meritoo\LimeSurvey\Test\ApiClient\Result\Collection;
use Meritoo\Common\Exception\Method\DisabledMethodException;
use Meritoo\Common\Test\Base\BaseTestCase;
use Meritoo\Common\Type\OopVisibilityType;
use Meritoo\LimeSurvey\ApiClient\Result\Collection\SurveysSummaries;
use Meritoo\LimeSurvey\ApiClient\Result\Item\SurveySummary;
/**
* Test case of the collection of surveys' summaries (the SurveySummary class instances)
*
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl>
* @copyright Meritoo.pl
*/
class SurveysSummariesTest extends BaseTestCase
{
/**
* Empty collection of surveys' summaries
*
* @var SurveysSummaries
*/
private $emptySurveysSummaries;
/**
* Non-empty collection of surveys' summaries
*
* @var SurveysSummaries
*/
private $nonEmptySurveysSummaries;
public function testConstructorVisibilityAndArguments()
{
static::assertConstructorVisibilityAndArguments(SurveysSummaries::className, OopVisibilityType::IS_PUBLIC, 1, 0);
}
public function testAdd()
{
$this->setExpectedException(DisabledMethodException::className);
(new SurveysSummaries())->add('');
}
public function testAddMultiple()
{
$this->setExpectedException(DisabledMethodException::className);
(new SurveysSummaries())->addMultiple([]);
}
public function testHas()
{
$this->setExpectedException(DisabledMethodException::className);
(new SurveysSummaries())->has(new SurveySummary());
}
/**
* @param array $summaries Surveys' summaries to add
* @dataProvider provideSurveysSummaries
*/
public function testAddSurveysSummaries(array $summaries)
{
$existingSummariesCount = $this->nonEmptySurveysSummaries->count();
$this->emptySurveysSummaries->addSurveysSummaries($summaries);
$this->nonEmptySurveysSummaries->addSurveysSummaries($summaries);
static::assertCount(count($summaries), $this->emptySurveysSummaries);
static::assertCount(count($summaries) + $existingSummariesCount, $this->nonEmptySurveysSummaries);
}
public function testHasSurveySummaryUsingNonExistingSurvey()
{
static::assertFalse($this->emptySurveysSummaries->hasSurveySummary(1));
static::assertFalse($this->emptySurveysSummaries->hasSurveySummary(2));
static::assertFalse($this->nonEmptySurveysSummaries->hasSurveySummary(3));
static::assertFalse($this->nonEmptySurveysSummaries->hasSurveySummary(4));
}
public function testHasSurveySummaryUsingExistingSurvey()
{
static::assertTrue($this->nonEmptySurveysSummaries->hasSurveySummary(1));
static::assertTrue($this->nonEmptySurveysSummaries->hasSurveySummary(2));
}
public function testGetSurveySummaryUsingNonExistingSurvey()
{
static::assertNull($this->emptySurveysSummaries->getSurveySummary(1));
static::assertNull($this->emptySurveysSummaries->getSurveySummary(2));
static::assertNull($this->nonEmptySurveysSummaries->getSurveySummary(3));
static::assertNull($this->nonEmptySurveysSummaries->getSurveySummary(4));
}
public function testGetSurveySummaryUsingExistingSurvey()
{
$surveySummary1 = $this->nonEmptySurveysSummaries->getSurveySummary(1);
$surveySummary2 = $this->nonEmptySurveysSummaries->getSurveySummary(2);
static::assertInstanceOf(SurveySummary::className, $surveySummary1);
static::assertInstanceOf(SurveySummary::className, $surveySummary2);
static::assertEquals(0, $surveySummary1->getTokenCount());
static::assertEquals(5, $surveySummary2->getTokenCount());
static::assertEquals(0, $surveySummary1->getFullResponsesCount());
static::assertEquals(3, $surveySummary2->getFullResponsesCount());
}
/**
* Provides surveys' summaries
*
* @return array
* //return Generator
*/
public function provideSurveysSummaries()
{
return [
[
[],
],
[
[
123 => new SurveySummary(),
],
],
[
[
100 => new SurveySummary(),
500 => new SurveySummary(),
800 => new SurveySummary(),
],
],
];
/*
yield[
[],
];
yield[
[
123 => new SurveySummary(),
],
];
yield[
[
100 => new SurveySummary(),
500 => new SurveySummary(),
800 => new SurveySummary(),
],
];
*/
}
/**
* {@inheritdoc}
*/
protected function setUp()
{
parent::setUp();
$this->emptySurveysSummaries = new SurveysSummaries();
$this->nonEmptySurveysSummaries = new SurveysSummaries([
1 => new SurveySummary([
'token_count' => '0',
'token_invalid' => '0',
'token_sent' => '0',
'token_opted_out' => '0',
'token_completed' => '0',
'completed_responses' => '0',
'incomplete_responses' => '0',
'full_responses' => '0',
]),
2 => new SurveySummary([
'token_count' => '5',
'token_invalid' => '2',
'token_sent' => '0',
'token_opted_out' => '0',
'token_completed' => '2',
'completed_responses' => '1',
'incomplete_responses' => '2',
'full_responses' => '3',
]),
]);
}
}

View File

@@ -37,7 +37,7 @@ class SurveysTest extends BaseTestCase
public function testConstructorVisibilityAndArguments()
{
static::assertConstructorVisibilityAndArguments(Surveys::class, OopVisibilityType::IS_PUBLIC, 1, 0);
static::assertConstructorVisibilityAndArguments(Surveys::className, OopVisibilityType::IS_PUBLIC, 1, 0);
}
public function testAddWithoutIndex()

View File

@@ -46,7 +46,7 @@ class ParticipantShortTest extends BaseTestCase
public function testConstructorVisibilityAndArguments()
{
static::assertConstructorVisibilityAndArguments(ParticipantShort::class, OopVisibilityType::IS_PUBLIC, 1, 0);
static::assertConstructorVisibilityAndArguments(ParticipantShort::className, OopVisibilityType::IS_PUBLIC, 1, 0);
}
public function testCreateOfTheParticipant()
@@ -127,12 +127,24 @@ class ParticipantShortTest extends BaseTestCase
static::assertEquals($participant2->getEmail(), $participantShort2->getEmail());
}
/**
* {@inheritdoc}
*/
protected function setUp()
{
parent::setUp();
$this->rawData = static::getParticipantsRawData();
$this->participant1stInstance = new ParticipantShort($this->rawData[0]);
$this->participant2ndInstance = new ParticipantShort($this->rawData[1]);
}
/**
* Returns raw data of participants
*
* @return array
*/
public static function getParticipantsRawData()
private static function getParticipantsRawData()
{
return [
[
@@ -153,16 +165,4 @@ class ParticipantShortTest extends BaseTestCase
],
];
}
/**
* {@inheritdoc}
*/
protected function setUp()
{
parent::setUp();
$this->rawData = static::getParticipantsRawData();
$this->participant1stInstance = new ParticipantShort($this->rawData[0]);
$this->participant2ndInstance = new ParticipantShort($this->rawData[1]);
}
}

View File

@@ -14,6 +14,7 @@ use Meritoo\Common\Type\OopVisibilityType;
use Meritoo\LimeSurvey\ApiClient\Result\Item\Participant;
use Meritoo\LimeSurvey\ApiClient\Result\Processor\ResultProcessor;
use Meritoo\LimeSurvey\ApiClient\Type\MethodType;
use Meritoo\LimeSurvey\Test\ApiClient\Utilities\DateUtility;
/**
* Test case of the one item of the result/data: full data of participant
@@ -46,7 +47,7 @@ class ParticipantTest extends BaseTestCase
public function testConstructorVisibilityAndArguments()
{
static::assertConstructorVisibilityAndArguments(Participant::class, OopVisibilityType::IS_PUBLIC, 1, 0);
static::assertConstructorVisibilityAndArguments(Participant::className, OopVisibilityType::IS_PUBLIC, 1, 0);
}
public function testCreateOfTheParticipant()
@@ -54,7 +55,7 @@ class ParticipantTest extends BaseTestCase
$processor = new ResultProcessor();
$processed = $processor->process(MethodType::GET_PARTICIPANT_PROPERTIES, $this->rawData[0]);
static::assertInstanceOf(Participant::class, $processed);
static::assertInstanceOf(Participant::className, $processed);
}
public function testGetId()
@@ -159,12 +160,24 @@ class ParticipantTest extends BaseTestCase
static::assertNull($this->participant2ndInstance->getValidUntil());
}
/**
* {@inheritdoc}
*/
protected function setUp()
{
parent::setUp();
$this->rawData = static::getParticipantsRawData();
$this->participant1stInstance = new Participant($this->rawData[0]);
$this->participant2ndInstance = new Participant($this->rawData[1]);
}
/**
* Returns raw data of participants
*
* @return array
*/
public static function getParticipantsRawData()
private static function getParticipantsRawData()
{
return [
[
@@ -184,7 +197,7 @@ class ParticipantTest extends BaseTestCase
'completed' => 'N',
'usesleft' => 10,
'validfrom' => null,
'validuntil' => (new DateTime())->format('Y-m-d H:i:s'),
'validuntil' => DateUtility::getDateTime(),
],
[
'tid' => '456',
@@ -200,23 +213,11 @@ class ParticipantTest extends BaseTestCase
'sent' => 'Y',
'remindersent' => 'N',
'remindercount' => 1,
'completed' => 'Y',
'completed' => DateUtility::getDateTime(false),
'usesleft' => 5,
'validfrom' => (new DateTime())->format('Y-m-d H:i:s'),
'validfrom' => DateUtility::getDateTime(),
'validuntil' => null,
],
];
}
/**
* {@inheritdoc}
*/
protected function setUp()
{
parent::setUp();
$this->rawData = static::getParticipantsRawData();
$this->participant1stInstance = new Participant($this->rawData[0]);
$this->participant2ndInstance = new Participant($this->rawData[1]);
}
}

View File

@@ -45,7 +45,7 @@ class QuestionShortTest extends BaseTestCase
public function testConstructorVisibilityAndArguments()
{
static::assertConstructorVisibilityAndArguments(QuestionShort::class, OopVisibilityType::IS_PUBLIC, 1, 0);
static::assertConstructorVisibilityAndArguments(QuestionShort::className, OopVisibilityType::IS_PUBLIC, 1, 0);
}
public function testCreateOfTheQuestionShort()
@@ -158,12 +158,24 @@ class QuestionShortTest extends BaseTestCase
static::assertEquals('HR', $this->question2ndInstance->getModuleName());
}
/**
* {@inheritdoc}
*/
protected function setUp()
{
parent::setUp();
$this->rawData = static::getQuestionsRawData();
$this->question1stInstance = new QuestionShort($this->rawData[0]);
$this->question2ndInstance = new QuestionShort($this->rawData[1]);
}
/**
* Returns raw data of questions
*
* @return array
*/
public static function getQuestionsRawData()
private static function getQuestionsRawData()
{
return [
[
@@ -214,16 +226,4 @@ class QuestionShortTest extends BaseTestCase
],
];
}
/**
* {@inheritdoc}
*/
protected function setUp()
{
parent::setUp();
$this->rawData = static::getQuestionsRawData();
$this->question1stInstance = new QuestionShort($this->rawData[0]);
$this->question2ndInstance = new QuestionShort($this->rawData[1]);
}
}

View File

@@ -45,7 +45,7 @@ class QuestionTest extends BaseTestCase
public function testConstructorVisibilityAndArguments()
{
static::assertConstructorVisibilityAndArguments(Question::class, OopVisibilityType::IS_PUBLIC, 1, 0);
static::assertConstructorVisibilityAndArguments(Question::className, OopVisibilityType::IS_PUBLIC, 1, 0);
}
public function testCreateOfTheQuestionShort()
@@ -53,7 +53,7 @@ class QuestionTest extends BaseTestCase
$processor = new ResultProcessor();
$processed = $processor->process(MethodType::GET_QUESTION_PROPERTIES, $this->rawData);
static::assertInstanceOf(Question::class, $processed);
static::assertInstanceOf(Question::className, $processed);
}
public function testGetId()
@@ -194,12 +194,24 @@ class QuestionTest extends BaseTestCase
static::assertNull($this->question2ndInstance->getDefaultValue());
}
/**
* {@inheritdoc}
*/
protected function setUp()
{
parent::setUp();
$this->rawData = static::getQuestionsRawData();
$this->question1stInstance = new Question($this->rawData[0]);
$this->question2ndInstance = new Question($this->rawData[1]);
}
/**
* Returns raw data of questions
*
* @return array
*/
public static function getQuestionsRawData()
private static function getQuestionsRawData()
{
return [
[
@@ -276,16 +288,4 @@ class QuestionTest extends BaseTestCase
],
];
}
/**
* {@inheritdoc}
*/
protected function setUp()
{
parent::setUp();
$this->rawData = static::getQuestionsRawData();
$this->question1stInstance = new Question($this->rawData[0]);
$this->question2ndInstance = new Question($this->rawData[1]);
}
}

View File

@@ -0,0 +1,138 @@
<?php
/**
* (c) Meritoo.pl, http://www.meritoo.pl
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Meritoo\LimeSurvey\Test\ApiClient\Result\Item;
use Meritoo\Common\Test\Base\BaseTestCase;
use Meritoo\Common\Type\OopVisibilityType;
use Meritoo\LimeSurvey\ApiClient\Result\Item\SurveySummary;
use Meritoo\LimeSurvey\ApiClient\Result\Processor\ResultProcessor;
use Meritoo\LimeSurvey\ApiClient\Type\MethodType;
/**
* Test case of the one item of the result/data: survey's summary (contains aggregated data)
*
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl>
* @copyright Meritoo.pl
*/
class SurveySummaryTest extends BaseTestCase
{
public function testConstructorVisibilityAndArguments()
{
static::assertConstructorVisibilityAndArguments(SurveySummary::className, OopVisibilityType::IS_PUBLIC, 1, 0);
}
/**
* @param array $rawData Raw data of survey's summary
* @dataProvider provideRawData
*/
public function testCreateOfTheSurveySummary(array $rawData)
{
$processor = new ResultProcessor();
$processed = $processor->process(MethodType::GET_SUMMARY, $rawData);
/* @var SurveySummary $processed */
static::assertEquals($rawData['token_count'], $processed->getTokenCount());
static::assertEquals($rawData['token_invalid'], $processed->getTokenInvalidCount());
static::assertEquals($rawData['token_sent'], $processed->getTokenSentCount());
static::assertEquals($rawData['token_opted_out'], $processed->getTokenOptedOutCount());
static::assertEquals($rawData['token_completed'], $processed->getTokenCompletedCount());
static::assertEquals($rawData['completed_responses'], $processed->getCompleteResponsesCount());
static::assertEquals($rawData['incomplete_responses'], $processed->getIncompleteResponsesCount());
static::assertEquals($rawData['full_responses'], $processed->getFullResponsesCount());
}
/**
* Provides raw data of survey's summary
*
* @return array
* //return Generator
*/
public function provideRawData()
{
return [
[
[
'token_count' => '0',
'token_invalid' => '0',
'token_sent' => '0',
'token_opted_out' => '0',
'token_completed' => '0',
'completed_responses' => '0',
'incomplete_responses' => '0',
'full_responses' => '0',
],
],
[
[
'token_count' => '28',
'token_invalid' => '0',
'token_sent' => '5',
'token_opted_out' => '0',
'token_completed' => '6',
'completed_responses' => '6',
'incomplete_responses' => '10',
'full_responses' => '16',
],
],
[
[
'token_count' => '28',
'token_invalid' => '0',
'token_sent' => '0',
'token_opted_out' => '0',
'token_completed' => '2',
'completed_responses' => '2',
'incomplete_responses' => '12',
'full_responses' => '14',
],
],
];
/*
yield[
[
'token_count' => '0',
'token_invalid' => '0',
'token_sent' => '0',
'token_opted_out' => '0',
'token_completed' => '0',
'completed_responses' => '0',
'incomplete_responses' => '0',
'full_responses' => '0',
],
];
yield[
[
'token_count' => '28',
'token_invalid' => '0',
'token_sent' => '5',
'token_opted_out' => '0',
'token_completed' => '6',
'completed_responses' => '6',
'incomplete_responses' => '10',
'full_responses' => '16',
],
];
yield[
[
'token_count' => '28',
'token_invalid' => '0',
'token_sent' => '0',
'token_opted_out' => '0',
'token_completed' => '2',
'completed_responses' => '2',
'incomplete_responses' => '12',
'full_responses' => '14',
],
];
*/
}
}

View File

@@ -14,6 +14,7 @@ use Meritoo\Common\Type\OopVisibilityType;
use Meritoo\LimeSurvey\ApiClient\Result\Item\Survey;
use Meritoo\LimeSurvey\ApiClient\Result\Processor\ResultProcessor;
use Meritoo\LimeSurvey\ApiClient\Type\MethodType;
use Meritoo\LimeSurvey\Test\ApiClient\Utilities\DateUtility;
/**
* Test case of the one item of the result/data: survey
@@ -46,7 +47,7 @@ class SurveyTest extends BaseTestCase
public function testConstructorVisibilityAndArguments()
{
static::assertConstructorVisibilityAndArguments(Survey::class, OopVisibilityType::IS_PUBLIC, 1, 0);
static::assertConstructorVisibilityAndArguments(Survey::className, OopVisibilityType::IS_PUBLIC, 1, 0);
}
public function testCreateOfTheSurvey()
@@ -99,13 +100,13 @@ class SurveyTest extends BaseTestCase
'sid' => '123',
'surveyls_title' => 'Test',
'startdate' => null,
'expires' => (new DateTime())->format('Y-m-d H:i:s'),
'expires' => DateUtility::getDateTime(),
'active' => 'N',
],
[
'sid' => '456',
'surveyls_title' => 'Another Test',
'startdate' => (new DateTime())->format('Y-m-d H:i:s'),
'startdate' => DateUtility::getDateTime(),
'expires' => null,
'active' => 'Y',
],

View File

@@ -27,7 +27,7 @@ class ResultProcessorTest extends BaseTestCase
{
public function testConstructorVisibilityAndArguments()
{
static::assertHasNoConstructor(ResultProcessor::class);
static::assertHasNoConstructor(ResultProcessor::className);
}
public function testProcessWithEmptyRawData()
@@ -72,17 +72,17 @@ class ResultProcessorTest extends BaseTestCase
static::assertNotEmpty($processed);
static::assertFalse(is_array($processed));
static::assertInstanceOf(BaseItem::class, $processed);
static::assertInstanceOf(BaseItem::className, $processed);
}
public function testGetItemClassNameVisibilityAndArguments()
{
static::assertMethodVisibilityAndArguments(ResultProcessor::class, 'getItemClassName', OopVisibilityType::IS_PRIVATE, 1, 1);
static::assertMethodVisibilityAndArguments(ResultProcessor::className, 'getItemClassName', OopVisibilityType::IS_PRIVATE, 1, 1);
}
public function testRunWithUnknownResultClass()
{
$this->expectException(UnknownInstanceOfResultItem::class);
$this->setExpectedException(UnknownInstanceOfResultItem::className);
$rawData = [
'lorem' => 'ipsum',

View File

@@ -8,13 +8,13 @@
namespace Meritoo\LimeSurvey\Test\ApiClient\Result\Result;
use DateTime;
use Meritoo\Common\Test\Base\BaseTestCase;
use Meritoo\Common\Type\OopVisibilityType;
use Meritoo\LimeSurvey\ApiClient\Base\Result\BaseItem;
use Meritoo\LimeSurvey\ApiClient\Exception\CannotProcessDataException;
use Meritoo\LimeSurvey\ApiClient\Result\Result;
use Meritoo\LimeSurvey\ApiClient\Type\MethodType;
use Meritoo\LimeSurvey\Test\ApiClient\Utilities\DateUtility;
use PHPUnit_Framework_MockObject_MockObject;
/**
@@ -87,7 +87,7 @@ class ResultTest extends BaseTestCase
public function testConstructorVisibilityAndArguments()
{
static::assertConstructorVisibilityAndArguments(Result::class, OopVisibilityType::IS_PUBLIC, 2, 2);
static::assertConstructorVisibilityAndArguments(Result::className, OopVisibilityType::IS_PUBLIC, 2, 2);
}
public function testIsEmpty()
@@ -108,7 +108,7 @@ class ResultTest extends BaseTestCase
static::assertCount(count($this->emptyData), $emptyData);
static::assertCount(count($this->iterableData), $iterableData);
static::assertInstanceOf(BaseItem::class, $notIterableData);
static::assertInstanceOf(BaseItem::className, $notIterableData);
}
public function testGetDataUsingRawData()
@@ -128,18 +128,18 @@ class ResultTest extends BaseTestCase
public function testGetDataUsingProcessedDataWhoCannotBeProcessed()
{
$this->expectException(CannotProcessDataException::class);
$this->setExpectedException(CannotProcessDataException::className);
$this->statusInsteadDataResult->getData();
}
public function testGetProcessedDataVisibilityAndArguments()
{
static::assertMethodVisibilityAndArguments(Result::class, 'getProcessedData', OopVisibilityType::IS_PRIVATE, 1, 1);
static::assertMethodVisibilityAndArguments(Result::className, 'getProcessedData', OopVisibilityType::IS_PRIVATE, 1, 1);
}
public function testGetResultProcessorVisibilityAndArguments()
{
static::assertMethodVisibilityAndArguments(Result::class, 'getResultProcessor', OopVisibilityType::IS_PRIVATE);
static::assertMethodVisibilityAndArguments(Result::className, 'getResultProcessor', OopVisibilityType::IS_PRIVATE);
}
public function testGetStatusWhenIsNotProvided()
@@ -179,7 +179,7 @@ class ResultTest extends BaseTestCase
[
'sid' => '456',
'surveyls_title' => 'Another Test',
'startdate' => (new DateTime())->format('Y-m-d H:i:s'),
'startdate' => DateUtility::getDateTime(),
'expires' => null,
'active' => 'Y',
],
@@ -218,6 +218,6 @@ class ResultTest extends BaseTestCase
*/
private function getResultMock($constructorArguments)
{
return $this->getMockForAbstractClass(Result::class, $constructorArguments);
return $this->getMockForAbstractClass(Result::className, $constructorArguments);
}
}

View File

@@ -18,11 +18,11 @@ use Meritoo\LimeSurvey\ApiClient\Exception\CannotProcessDataException;
use Meritoo\LimeSurvey\ApiClient\Exception\MissingParticipantOfSurveyException;
use Meritoo\LimeSurvey\ApiClient\Manager\JsonRpcClientManager;
use Meritoo\LimeSurvey\ApiClient\Manager\SessionManager;
use Meritoo\LimeSurvey\ApiClient\Result\Collection\Participants;
use Meritoo\LimeSurvey\ApiClient\Result\Collection\ParticipantsDetails;
use Meritoo\LimeSurvey\ApiClient\Result\Item\Participant;
use Meritoo\LimeSurvey\ApiClient\Result\Item\ParticipantShort;
use Meritoo\LimeSurvey\ApiClient\Service\ParticipantService;
use Meritoo\LimeSurvey\ApiClient\Type\ReasonType;
use Meritoo\LimeSurvey\Test\ApiClient\Utilities\DateUtility;
use PHPUnit_Framework_MockObject_MockObject;
/**
@@ -33,6 +33,13 @@ use PHPUnit_Framework_MockObject_MockObject;
*/
class ParticipantServiceTest extends BaseTestCase
{
/**
* Raw data of participants
*
* @var array
*/
private $participantsRawData;
/**
* Service that serves participants.
* Without participants.
@@ -51,7 +58,7 @@ class ParticipantServiceTest extends BaseTestCase
public function testConstructorVisibilityAndArguments()
{
static::assertConstructorVisibilityAndArguments(ParticipantService::class, OopVisibilityType::IS_PUBLIC, 2, 1);
static::assertConstructorVisibilityAndArguments(ParticipantService::className, OopVisibilityType::IS_PUBLIC, 2, 1);
}
public function testGetClient()
@@ -62,8 +69,8 @@ class ParticipantServiceTest extends BaseTestCase
$this->createServiceWithoutParticipants($rpcClientManager, $sessionManager);
$this->createServiceWithParticipants($rpcClientManager, $sessionManager);
static::assertInstanceOf(Client::class, $this->serviceWithoutParticipants->getClient());
static::assertInstanceOf(Client::class, $this->serviceWithParticipants->getClient());
static::assertInstanceOf(Client::className, $this->serviceWithoutParticipants->getClient());
static::assertInstanceOf(Client::className, $this->serviceWithParticipants->getClient());
$connectionConfiguration = $this->getConnectionConfiguration();
$client = new Client($connectionConfiguration);
@@ -72,124 +79,46 @@ class ParticipantServiceTest extends BaseTestCase
static::assertEquals($client, $participantService->getClient());
}
public function testGetSurveyParticipants()
public function testHasParticipantUsingServiceWithoutParticipants()
{
$rpcClientManager = $this->getJsonRpcClientManager(3);
$rpcClientManager = $this->getJsonRpcClientManager(2);
$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 testGetSurveyParticipantsWithImportantException()
{
$this->expectException(CannotProcessDataException::class);
$exception = new CannotProcessDataException(ReasonType::NO_TOKEN_TABLE);
$rpcClientManager = $this->getJsonRpcClientManagerWithException(1, $exception);
$sessionManager = $this->getSessionManager();
$this->createServiceWithParticipants($rpcClientManager, $sessionManager);
$this->serviceWithParticipants->getSurveyParticipants(3);
}
public function testGetSurveyParticipantsWithNoParticipantsException()
{
$exception = new CannotProcessDataException(ReasonType::NO_PARTICIPANTS_FOUND);
$rpcClientManager = $this->getJsonRpcClientManagerWithException(1, $exception);
$sessionManager = $this->getSessionManager();
$this->createServiceWithParticipants($rpcClientManager, $sessionManager);
static::assertCount(0, $this->serviceWithParticipants->getSurveyParticipants(3));
static::assertFalse($this->serviceWithoutParticipants->hasParticipant(1, 'john@scott.com'));
static::assertFalse($this->serviceWithoutParticipants->hasParticipant(2, 'john@scott.com'));
}
public function testHasParticipant()
{
$rpcClientManager = $this->getJsonRpcClientManager(3);
$runMethodCallResults = [
[
null,
],
[
null,
],
];
$rpcClientManager = $this->getJsonRpcClientManager(2, $runMethodCallResults);
$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 testAddParticipantForNotExistingSurvey()
public function testGetParticipantDetailsWithException()
{
$this->expectException(CannotProcessDataException::class);
$exception = new CannotProcessDataException(ReasonType::NOT_EXISTING_SURVEY_ID);
$this->setExpectedException(CannotProcessDataException::className, $exception->getMessage());
$rpcClientManager = $this->getJsonRpcClientManagerWithException(1, $exception);
$sessionManager = $this->getSessionManager();
$this->createServiceWithoutParticipants($rpcClientManager, $sessionManager);
$this->createServiceWithParticipants($rpcClientManager, $sessionManager);
$surveyId = 1;
$firstName = 'John';
$lastName = 'Scott';
$email = 'john@scott.com';
$this->serviceWithoutParticipants->addParticipant($surveyId, $firstName, $lastName, $email);
$this->serviceWithParticipants->addParticipant($surveyId, $firstName, $lastName, $email);
}
public function testAddParticipant()
{
$surveyId = 1;
$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($surveyId, $firstName, $lastName, $email);
static::assertInstanceOf(Participant::class, $result);
static::assertEquals($firstName, $result->getFirstName());
static::assertEquals($lastName, $result->getLastName());
static::assertEquals($email, $result->getEmail());
}
public function testGetParticipant()
{
$rpcClientManager = $this->getJsonRpcClientManager(1);
$sessionManager = $this->getSessionManager();
$this->createServiceWithoutParticipants($rpcClientManager, $sessionManager);
$this->createServiceWithParticipants($rpcClientManager, $sessionManager);
static::assertNull($this->serviceWithoutParticipants->getParticipant(1, 'john@scott.com'));
$participant = $this->serviceWithParticipants->getParticipant(1, 'john@scott.com');
static::assertInstanceOf(ParticipantShort::class, $participant);
static::assertEquals('John', $participant->getFirstName());
static::assertEquals('Scott', $participant->getLastName());
static::assertEquals('john@scott.com', $participant->getEmail());
$this->serviceWithParticipants->getParticipantDetails(1, 'lorem@ipsum.com');
}
public function testGetParticipantDetails()
@@ -199,37 +128,35 @@ class ParticipantServiceTest extends BaseTestCase
$rpcClientManager = $this->getJsonRpcClientManager(1);
$this->createServiceWithoutParticipants($rpcClientManager, $sessionManager);
$runMethodCallResults = [
'tid' => 1,
'firstname' => 'John',
'lastname' => 'Scott',
'email' => 'john@scott.com',
'token' => uniqid(),
'sent' => 'N',
'completed' => 'N',
];
$rpcClientManager = $this->getJsonRpcClientManager(1, $runMethodCallResults);
$rpcClientManager = $this->getJsonRpcClientManager(0);
$this->createServiceWithParticipants($rpcClientManager, $sessionManager);
static::assertNull($this->serviceWithoutParticipants->getParticipantDetails(1, 'john@scott.com'));
$participant = $this->serviceWithParticipants->getParticipantDetails(1, 'john@scott.com');
$participant1 = $this->serviceWithoutParticipants->getParticipantDetails(1, 'john@scott.com');
$participant2 = $this->serviceWithParticipants->getParticipantDetails(1, 'john@scott.com');
static::assertInstanceOf(Participant::class, $participant);
static::assertEquals($runMethodCallResults['tid'], $participant->getId());
static::assertEquals($runMethodCallResults['firstname'], $participant->getFirstName());
static::assertEquals($runMethodCallResults['lastname'], $participant->getLastName());
static::assertEquals($runMethodCallResults['email'], $participant->getEmail());
static::assertEquals($runMethodCallResults['token'], $participant->getToken());
static::assertFalse($participant->isSent());
static::assertFalse($participant->isCompleted());
static::assertNull($participant->isBlacklisted());
static::assertNull($participant->getValidFrom());
$rawData = $this->participantsRawData[0];
$id = $rawData['tid'];
$firstName = $rawData['firstname'];
$lastName = $rawData['lastname'];
$email = $rawData['email'];
$token = $rawData['token'];
static::assertNull($participant1);
static::assertInstanceOf(Participant::className, $participant2);
static::assertEquals($id, $participant2->getId());
static::assertEquals($firstName, $participant2->getFirstName());
static::assertEquals($lastName, $participant2->getLastName());
static::assertEquals($email, $participant2->getEmail());
static::assertEquals($token, $participant2->getToken());
static::assertTrue($participant2->isSent());
static::assertTrue($participant2->isCompleted());
static::assertFalse($participant2->isBlacklisted());
static::assertNull($participant2->getValidFrom());
}
public function testHasParticipantFilledSurveyWithException()
public function testHasParticipantFilledSurveyWithoutParticipants()
{
$this->expectException(MissingParticipantOfSurveyException::class);
$this->setExpectedException(MissingParticipantOfSurveyException::className);
$rpcClientManager = $this->getJsonRpcClientManager(1);
$sessionManager = $this->getSessionManager();
@@ -240,14 +167,7 @@ class ParticipantServiceTest extends BaseTestCase
public function testHasParticipantFilledSurveyUsingExistingParticipant()
{
$runMethodCallResults = [
'firstname' => 'John',
'lastname' => 'Scott',
'email' => 'john@scott.com',
'completed' => 'Y',
];
$rpcClientManager = $this->getJsonRpcClientManager(1, $runMethodCallResults);
$rpcClientManager = $this->getJsonRpcClientManager(0);
$sessionManager = $this->getSessionManager();
$this->createServiceWithParticipants($rpcClientManager, $sessionManager);
@@ -256,7 +176,7 @@ class ParticipantServiceTest extends BaseTestCase
public function testHasParticipantFilledSurveyUsingNotExistingParticipant()
{
$this->expectException(MissingParticipantOfSurveyException::class);
$this->setExpectedException(MissingParticipantOfSurveyException::className);
$rpcClientManager = $this->getJsonRpcClientManager(1);
$sessionManager = $this->getSessionManager();
@@ -265,6 +185,55 @@ class ParticipantServiceTest extends BaseTestCase
$this->serviceWithParticipants->hasParticipantFilledSurvey(3, 'mary@jane.com');
}
/**
* {@inheritdoc}
*/
protected function setUp()
{
parent::setUp();
$this->participantsRawData = [
[
'tid' => 1,
'participant_id' => null,
'mpid' => null,
'firstname' => 'John',
'lastname' => 'Scott',
'email' => 'john@scott.com',
'emailstatus' => 'OK',
'token' => uniqid(),
'language' => 'pl',
'blacklisted' => 'N',
'sent' => 'Y',
'remindersent' => 'N',
'remindercount' => 0,
'completed' => DateUtility::getDateTime(),
'usesleft' => 10,
'validfrom' => null,
'validuntil' => DateUtility::getDateTime(),
],
[
'tid' => 2,
'participant_id' => null,
'mpid' => null,
'firstname' => 'Mary',
'lastname' => 'Jane',
'email' => 'mary@jane.com',
'emailstatus' => 'OK',
'token' => uniqid(),
'language' => 'pl',
'blacklisted' => 'N',
'sent' => 'Y',
'remindersent' => 'N',
'remindercount' => 0,
'completed' => 'N',
'usesleft' => 10,
'validfrom' => null,
'validuntil' => DateUtility::getDateTime(),
],
];
}
/**
* Returns configuration used while connecting to LimeSurvey's API
*
@@ -282,7 +251,7 @@ class ParticipantServiceTest extends BaseTestCase
*/
private function getSessionManager()
{
return $this->createMock(SessionManager::class);
return $this->createMock(SessionManager::className);
}
/**
@@ -294,12 +263,24 @@ class ParticipantServiceTest extends BaseTestCase
*/
private function getJsonRpcClientManager($runMethodCallCount, array $runMethodCallResults = [])
{
$rpcClientManager = $this->createMock(JsonRpcClientManager::class);
$rpcClientManager = $this->createMock(JsonRpcClientManager::className);
$rpcClientManager
$mocker = $rpcClientManager
->expects(static::exactly($runMethodCallCount))
->method('runMethod')
->will(static::returnValue($runMethodCallResults));
->method('runMethod');
if (!empty($runMethodCallResults)) {
$function = [
$mocker,
'willReturnOnConsecutiveCalls',
];
/*
* I have to use the call_user_func_array() function to pass elements of $runMethodCallResults array as
* arguments of the willReturnOnConsecutiveCalls() method
*/
call_user_func_array($function, $runMethodCallResults);
}
return $rpcClientManager;
}
@@ -314,7 +295,7 @@ class ParticipantServiceTest extends BaseTestCase
*/
private function getJsonRpcClientManagerWithException($runMethodCallCount, Exception $exception)
{
$rpcClientManager = $this->createMock(JsonRpcClientManager::class);
$rpcClientManager = $this->createMock(JsonRpcClientManager::className);
$rpcClientManager
->expects(static::exactly($runMethodCallCount))
@@ -348,30 +329,16 @@ class ParticipantServiceTest extends BaseTestCase
$configuration = $this->getConnectionConfiguration();
$client = new Client($configuration, $rpcClientManager, $sessionManager);
$allParticipants = new Participants([
$participantsDetails = new ParticipantsDetails([
1 => new Collection([
new ParticipantShort([
'tid' => 1,
'participant_info' => [
'firstname' => 'John',
'lastname' => 'Scott',
'email' => 'john@scott.com',
],
]),
new ParticipantShort([
'tid' => 2,
'participant_info' => [
'firstname' => 'Mary',
'lastname' => 'Jane',
'email' => 'mary@jane.com',
],
]),
new Participant($this->participantsRawData[0]),
new Participant($this->participantsRawData[1]),
]),
2 => new Collection([
new ParticipantShort(),
new Participant(),
]),
]);
$this->serviceWithParticipants = new ParticipantService($client, $allParticipants);
$this->serviceWithParticipants = new ParticipantService($client, $participantsDetails);
}
}

View File

@@ -9,22 +9,26 @@
namespace Meritoo\LimeSurvey\Test\ApiClient\Service;
use Exception;
use Meritoo\Common\Collection\Collection;
use Meritoo\Common\Test\Base\BaseTestCase;
use Meritoo\Common\Type\OopVisibilityType;
use Meritoo\LimeSurvey\ApiClient\Client\Client;
use Meritoo\LimeSurvey\ApiClient\Configuration\ConnectionConfiguration;
use Meritoo\LimeSurvey\ApiClient\Exception\CannotProcessDataException;
use Meritoo\LimeSurvey\ApiClient\Exception\MissingSurveySummaryException;
use Meritoo\LimeSurvey\ApiClient\Manager\JsonRpcClientManager;
use Meritoo\LimeSurvey\ApiClient\Manager\SessionManager;
use Meritoo\LimeSurvey\ApiClient\Result\Collection\Participants;
use Meritoo\LimeSurvey\ApiClient\Result\Collection\Surveys;
use Meritoo\LimeSurvey\ApiClient\Result\Item\Participant;
use Meritoo\LimeSurvey\ApiClient\Result\Item\ParticipantShort;
use Meritoo\LimeSurvey\ApiClient\Result\Item\Survey;
use Meritoo\LimeSurvey\ApiClient\Service\SurveyService;
use Meritoo\LimeSurvey\ApiClient\Type\ReasonType;
use PHPUnit_Framework_MockObject_MockObject;
/**
* Test case of the service that serves surveys
* Test case of the service that serves surveys and participants of surveys
*
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl>
* @copyright Meritoo.pl
@@ -32,7 +36,7 @@ use PHPUnit_Framework_MockObject_MockObject;
class SurveyServiceTest extends BaseTestCase
{
/**
* Service that serves surveys.
* Service that serves surveys and participants of surveys.
* Without surveys.
*
* @var SurveyService
@@ -40,13 +44,29 @@ class SurveyServiceTest extends BaseTestCase
private $serviceWithoutSurveys;
/**
* Service that serves surveys.
* Service that serves surveys and participants of surveys.
* With surveys.
*
* @var SurveyService
*/
private $serviceWithSurveys;
/**
* Service that serves surveys and participants of surveys.
* Without participants.
*
* @var SurveyService
*/
private $serviceWithoutParticipants;
/**
* Service that serves surveys and participants of surveys.
* With participants.
*
* @var SurveyService
*/
private $serviceWithParticipants;
/**
* Base url of LimeSurvey's instance.
* Used to prepare configuration of connection.
@@ -57,7 +77,7 @@ class SurveyServiceTest extends BaseTestCase
public function testConstructorVisibilityAndArguments()
{
static::assertConstructorVisibilityAndArguments(SurveyService::class, OopVisibilityType::IS_PUBLIC, 2, 1);
static::assertConstructorVisibilityAndArguments(SurveyService::className, OopVisibilityType::IS_PUBLIC, 4, 1);
}
public function testGetClient()
@@ -68,8 +88,8 @@ class SurveyServiceTest extends BaseTestCase
$this->createServiceWithoutSurveys($rpcClientManager, $sessionManager);
$this->createServiceWithSurveys($rpcClientManager, $sessionManager);
static::assertInstanceOf(Client::class, $this->serviceWithoutSurveys->getClient());
static::assertInstanceOf(Client::class, $this->serviceWithSurveys->getClient());
static::assertInstanceOf(Client::className, $this->serviceWithoutSurveys->getClient());
static::assertInstanceOf(Client::className, $this->serviceWithSurveys->getClient());
$connectionConfiguration = $this->getConnectionConfiguration();
$client = new Client($connectionConfiguration);
@@ -78,9 +98,9 @@ class SurveyServiceTest extends BaseTestCase
static::assertEquals($client, $surveyService->getClient());
}
public function testGetAllSurveysWithImportantException()
public function testGetAllSurveysWithNoTableException()
{
$this->expectException(CannotProcessDataException::class);
$this->setExpectedException(CannotProcessDataException::className);
$exception = new CannotProcessDataException(ReasonType::NO_TOKEN_TABLE);
$rpcClientManager = $this->getJsonRpcClientManagerWithException(1, $exception);
@@ -161,6 +181,22 @@ class SurveyServiceTest extends BaseTestCase
static::assertFalse($this->serviceWithSurveys->isExistingSurvey(4, true));
}
public function testGetStartSurveyUrlByToken()
{
$rpcClientManager = $this->getJsonRpcClientManager(0);
$sessionManager = $this->getSessionManager();
$this->createServiceWithoutSurveys($rpcClientManager, $sessionManager);
$this->createServiceWithSurveys($rpcClientManager, $sessionManager);
$surveyId = 123;
$token = uniqid();
$expectedUrl = sprintf('%s/%d?token=%s', $this->connectionBaseUrl, $surveyId, $token);
static::assertEquals($expectedUrl, $this->serviceWithoutSurveys->getStartSurveyUrlByToken($surveyId, $token));
static::assertEquals($expectedUrl, $this->serviceWithSurveys->getStartSurveyUrlByToken($surveyId, $token));
}
public function testGetStartSurveyUrl()
{
$rpcClientManager = $this->getJsonRpcClientManager(0);
@@ -185,6 +221,262 @@ class SurveyServiceTest extends BaseTestCase
static::assertEquals($expectedUrl, $this->serviceWithSurveys->getStartSurveyUrl($surveyId, $participant));
}
public function testGetSurveyParticipantsWithNotExistingSurveyException()
{
$exception = new CannotProcessDataException(ReasonType::NOT_EXISTING_SURVEY_ID);
$this->setExpectedException(CannotProcessDataException::className, $exception->getMessage());
$runMethodCallResults = [
[
'token_count' => '0',
'token_invalid' => '0',
'token_sent' => '0',
'token_opted_out' => '0',
'token_completed' => '0',
'completed_responses' => '0',
'incomplete_responses' => '0',
'full_responses' => '0',
],
[
'status' => ReasonType::NOT_EXISTING_SURVEY_ID,
],
];
$rpcClientManager = $this->getJsonRpcClientManager(2, $runMethodCallResults);
$sessionManager = $this->getSessionManager();
$this->createServiceWithParticipants($rpcClientManager, $sessionManager);
$this->serviceWithParticipants->getSurveyParticipants(3);
}
public function testGetSurveyParticipantsWithNoParticipantsFoundException()
{
$runMethodCallResults = [
[
'token_count' => '0',
'token_invalid' => '0',
'token_sent' => '0',
'token_opted_out' => '0',
'token_completed' => '0',
'completed_responses' => '0',
'incomplete_responses' => '0',
'full_responses' => '0',
],
[
'status' => ReasonType::NO_PARTICIPANTS_FOUND,
],
];
$rpcClientManager = $this->getJsonRpcClientManager(2, $runMethodCallResults);
$sessionManager = $this->getSessionManager();
$this->createServiceWithParticipants($rpcClientManager, $sessionManager);
$participants = $this->serviceWithParticipants->getSurveyParticipants(3);
static::assertInstanceOf(Collection::className, $participants);
static::assertCount(0, $participants);
}
public function testGetSurveyParticipants()
{
$runMethodCallResults = [
[
'token_count' => '0',
'token_invalid' => '0',
'token_sent' => '0',
'token_opted_out' => '0',
'token_completed' => '0',
'completed_responses' => '0',
'incomplete_responses' => '0',
'full_responses' => '0',
],
null,
[
'token_count' => '0',
'token_invalid' => '0',
'token_sent' => '0',
'token_opted_out' => '0',
'token_completed' => '0',
'completed_responses' => '0',
'incomplete_responses' => '0',
'full_responses' => '0',
],
null,
[
'token_count' => '2',
'token_invalid' => '0',
'token_sent' => '0',
'token_opted_out' => '0',
'token_completed' => '0',
'completed_responses' => '0',
'incomplete_responses' => '0',
'full_responses' => '0',
],
];
$rpcClientManager = $this->getJsonRpcClientManager(6, $runMethodCallResults);
$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 testGetSurveyParticipantsWithNoTableException()
{
$this->setExpectedException(CannotProcessDataException::className);
$exception = new CannotProcessDataException(ReasonType::NO_TOKEN_TABLE);
$rpcClientManager = $this->getJsonRpcClientManagerWithException(1, $exception);
$sessionManager = $this->getSessionManager();
$this->createServiceWithParticipants($rpcClientManager, $sessionManager);
$this->serviceWithParticipants->getSurveyParticipants(3);
}
public function testGetSurveyParticipantsWithNoParticipantsException()
{
$this->setExpectedException(CannotProcessDataException::className);
$exception = new CannotProcessDataException(ReasonType::NO_PARTICIPANTS_FOUND);
$rpcClientManager = $this->getJsonRpcClientManagerWithException(1, $exception);
$sessionManager = $this->getSessionManager();
$this->createServiceWithParticipants($rpcClientManager, $sessionManager);
static::assertCount(0, $this->serviceWithParticipants->getSurveyParticipants(3));
}
public function testAddParticipantForNotExistingSurvey()
{
$this->setExpectedException(CannotProcessDataException::className);
$exception = new CannotProcessDataException(ReasonType::NOT_EXISTING_SURVEY_ID);
$rpcClientManager = $this->getJsonRpcClientManagerWithException(1, $exception);
$sessionManager = $this->getSessionManager();
$this->createServiceWithoutParticipants($rpcClientManager, $sessionManager);
$this->createServiceWithParticipants($rpcClientManager, $sessionManager);
$surveyId = 1;
$firstName = 'John';
$lastName = 'Scott';
$email = 'john@scott.com';
$this->serviceWithoutParticipants->addParticipant($surveyId, $firstName, $lastName, $email);
$this->serviceWithParticipants->addParticipant($surveyId, $firstName, $lastName, $email);
}
public function testAddParticipant()
{
$surveyId = 1;
$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($surveyId, $firstName, $lastName, $email);
static::assertInstanceOf(Participant::className, $result);
static::assertEquals($firstName, $result->getFirstName());
static::assertEquals($lastName, $result->getLastName());
static::assertEquals($email, $result->getEmail());
}
public function testGetParticipant()
{
$runMethodCallResults = [
[
'token_count' => '0',
'token_invalid' => '0',
'token_sent' => '0',
'token_opted_out' => '0',
'token_completed' => '0',
'completed_responses' => '0',
'incomplete_responses' => '0',
'full_responses' => '0',
],
null,
[
[
'tid' => 1,
'participant_info' => [
'firstname' => 'John',
'lastname' => 'Scott',
'email' => 'john@scott.com',
],
],
[
'tid' => 2,
'participant_info' => [
'firstname' => 'Mary',
'lastname' => 'Jane',
'email' => 'mary@jane.com',
],
],
],
[
'token_count' => '2',
'token_invalid' => '0',
'token_sent' => '0',
'token_opted_out' => '0',
'token_completed' => '0',
'completed_responses' => '0',
'incomplete_responses' => '0',
'full_responses' => '0',
],
];
$rpcClientManager = $this->getJsonRpcClientManager(2, $runMethodCallResults);
$sessionManager = $this->getSessionManager();
$this->createServiceWithoutParticipants($rpcClientManager, $sessionManager);
$this->createServiceWithParticipants($rpcClientManager, $sessionManager);
$participant1 = $this->serviceWithoutParticipants->getParticipant(1, 'john@scott.com');
$participant2 = $this->serviceWithParticipants->getParticipant(1, 'john@scott.com');
static::assertNull($participant1);
static::assertInstanceOf(ParticipantShort::className, $participant2);
static::assertEquals('John', $participant2->getFirstName());
static::assertEquals('Scott', $participant2->getLastName());
static::assertEquals('john@scott.com', $participant2->getEmail());
}
public function testGetSurveyTokenCountWithException()
{
$this->setExpectedException(MissingSurveySummaryException::className);
$runMethodCallResults = [
null,
];
$rpcClientManager = $this->getJsonRpcClientManager(1, $runMethodCallResults);
$sessionManager = $this->getSessionManager();
$this->createServiceWithoutSurveys($rpcClientManager, $sessionManager);
$this->serviceWithoutSurveys->getSurveyTokenCount(1);
}
/**
* Returns configuration used while connecting to LimeSurvey's API
*
@@ -202,7 +494,7 @@ class SurveyServiceTest extends BaseTestCase
*/
private function getSessionManager()
{
return $this->createMock(SessionManager::class);
return $this->createMock(SessionManager::className);
}
/**
@@ -214,12 +506,24 @@ class SurveyServiceTest extends BaseTestCase
*/
private function getJsonRpcClientManager($runMethodCallCount, array $runMethodCallResults = [])
{
$rpcClientManager = $this->createMock(JsonRpcClientManager::class);
$rpcClientManager = $this->createMock(JsonRpcClientManager::className);
$rpcClientManager
$mocker = $rpcClientManager
->expects(static::exactly($runMethodCallCount))
->method('runMethod')
->will(static::returnValue($runMethodCallResults));
->method('runMethod');
if (!empty($runMethodCallResults)) {
$function = [
$mocker,
'willReturnOnConsecutiveCalls',
];
/*
* I have to use the call_user_func_array() function to pass elements of $runMethodCallResults array as
* arguments of the willReturnOnConsecutiveCalls() method
*/
call_user_func_array($function, $runMethodCallResults);
}
return $rpcClientManager;
}
@@ -234,7 +538,7 @@ class SurveyServiceTest extends BaseTestCase
*/
private function getJsonRpcClientManagerWithException($runMethodCallCount, Exception $exception)
{
$rpcClientManager = $this->createMock(JsonRpcClientManager::class);
$rpcClientManager = $this->createMock(JsonRpcClientManager::className);
$rpcClientManager
->expects(static::exactly($runMethodCallCount))
@@ -287,4 +591,55 @@ class SurveyServiceTest extends BaseTestCase
$this->serviceWithSurveys = new SurveyService($client, $allSurveys);
}
/**
* 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 SurveyService($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 ParticipantShort([
'tid' => 1,
'participant_info' => [
'firstname' => 'John',
'lastname' => 'Scott',
'email' => 'john@scott.com',
],
]),
new ParticipantShort([
'tid' => 2,
'participant_info' => [
'firstname' => 'Mary',
'lastname' => 'Jane',
'email' => 'mary@jane.com',
],
]),
]),
2 => new Collection([
new ParticipantShort(),
]),
]);
$this->serviceWithParticipants = new SurveyService($client, null, $allParticipants);
}
}

View File

@@ -8,7 +8,6 @@
namespace Meritoo\LimeSurvey\Test\ApiClient\Type;
use Generator;
use Meritoo\Common\Test\Base\BaseTypeTestCase;
use Meritoo\LimeSurvey\ApiClient\Exception\UnknownMethodException;
use Meritoo\LimeSurvey\ApiClient\Type\MethodType;
@@ -24,7 +23,7 @@ class MethodTypeTest extends BaseTypeTestCase
{
public function testConstructorVisibilityAndArguments()
{
static::assertHasNoConstructor(MethodType::class);
static::assertHasNoConstructor(MethodType::className);
}
/**
@@ -33,7 +32,7 @@ class MethodTypeTest extends BaseTypeTestCase
*/
public function testGetValidatedMethodWithIncorrectMethod($incorrectMethod)
{
$this->expectException(UnknownMethodException::class);
$this->setExpectedException(UnknownMethodException::className);
MethodType::getValidatedMethod($incorrectMethod);
}
@@ -52,7 +51,7 @@ class MethodTypeTest extends BaseTypeTestCase
*/
public function testIsResultIterableWithIncorrectMethod($incorrectMethod)
{
$this->expectException(UnknownMethodException::class);
$this->setExpectedException(UnknownMethodException::className);
MethodType::isResultIterable($incorrectMethod);
}
@@ -70,10 +69,33 @@ class MethodTypeTest extends BaseTypeTestCase
/**
* Provides correct type of method
*
* @return Generator
* @return array
* //return Generator
*/
public function provideMethod()
{
return [
[
MethodType::ADD_RESPONSE,
],
[
MethodType::EXPORT_STATISTICS,
],
[
MethodType::GET_PARTICIPANT_PROPERTIES,
],
[
MethodType::LIST_SURVEYS,
],
[
SystemMethodType::GET_SESSION_KEY,
],
[
SystemMethodType::RELEASE_SESSION_KEY,
],
];
/*
yield[
MethodType::ADD_RESPONSE,
];
@@ -97,15 +119,36 @@ class MethodTypeTest extends BaseTypeTestCase
yield[
SystemMethodType::RELEASE_SESSION_KEY,
];
*/
}
/**
* Provides incorrect type of method
*
* @return Generator
* @return array
* //return Generator
*/
public function provideIncorrectMethod()
{
return [
[
'',
],
[
null,
],
[
true,
],
[
false,
],
[
'lorem',
],
];
/*
yield[
'',
];
@@ -125,15 +168,45 @@ class MethodTypeTest extends BaseTypeTestCase
yield[
'lorem',
];
*/
}
/**
* Provides type of method who result provided by the API is iterable and information if it's iterable
*
* @return Generator
* @return array
* //return Generator
*/
public function provideIterableType()
{
return [
[
MethodType::ADD_RESPONSE,
false,
],
[
MethodType::GET_PARTICIPANT_PROPERTIES,
false,
],
[
MethodType::LIST_PARTICIPANTS,
true,
],
[
MethodType::LIST_QUESTIONS,
true,
],
[
MethodType::LIST_SURVEYS,
true,
],
[
MethodType::LIST_USERS,
true,
],
];
/*
yield[
MethodType::ADD_RESPONSE,
false,
@@ -163,6 +236,7 @@ class MethodTypeTest extends BaseTypeTestCase
MethodType::LIST_USERS,
true,
];
*/
}
/**
@@ -176,6 +250,7 @@ class MethodTypeTest extends BaseTypeTestCase
'EXPORT_STATISTICS' => MethodType::EXPORT_STATISTICS,
'GET_PARTICIPANT_PROPERTIES' => MethodType::GET_PARTICIPANT_PROPERTIES,
'GET_QUESTION_PROPERTIES' => MethodType::GET_QUESTION_PROPERTIES,
'GET_SUMMARY' => MethodType::GET_SUMMARY,
'LIST_PARTICIPANTS' => MethodType::LIST_PARTICIPANTS,
'LIST_QUESTIONS' => MethodType::LIST_QUESTIONS,
'LIST_SURVEYS' => MethodType::LIST_SURVEYS,
@@ -196,6 +271,26 @@ class MethodTypeTest extends BaseTypeTestCase
*/
public function provideTypeToVerify()
{
return [
[
'',
false,
],
[
'lorem',
false,
],
[
MethodType::ADD_RESPONSE,
true,
],
[
MethodType::GET_PARTICIPANT_PROPERTIES,
true,
],
];
/*
yield[
'',
false,
@@ -215,5 +310,6 @@ class MethodTypeTest extends BaseTypeTestCase
MethodType::GET_PARTICIPANT_PROPERTIES,
true,
];
*/
}
}

View File

@@ -21,7 +21,7 @@ class ReasonTypeTest extends BaseTypeTestCase
{
public function testConstructorVisibilityAndArguments()
{
static::assertHasNoConstructor(ReasonType::class);
static::assertHasNoConstructor(ReasonType::className);
}
/**
@@ -30,10 +30,11 @@ class ReasonTypeTest extends BaseTypeTestCase
protected function getAllExpectedTypes()
{
return [
'NOT_EXISTING_SURVEY_ID' => ReasonType::NOT_EXISTING_SURVEY_ID,
'NO_PARTICIPANTS_FOUND' => ReasonType::NO_PARTICIPANTS_FOUND,
'NO_SURVEYS_FOUND' => ReasonType::NO_SURVEYS_FOUND,
'NO_TOKEN_TABLE' => ReasonType::NO_TOKEN_TABLE,
'NOT_EXISTING_SURVEY_ID' => ReasonType::NOT_EXISTING_SURVEY_ID,
'NO_PARTICIPANTS_FOUND' => ReasonType::NO_PARTICIPANTS_FOUND,
'NO_PARTICIPANT_PROPERTIES' => ReasonType::NO_PARTICIPANT_PROPERTIES,
'NO_SURVEYS_FOUND' => ReasonType::NO_SURVEYS_FOUND,
'NO_TOKEN_TABLE' => ReasonType::NO_TOKEN_TABLE,
];
}
@@ -50,6 +51,34 @@ class ReasonTypeTest extends BaseTypeTestCase
*/
public function provideTypeToVerify()
{
return [
[
'',
false,
],
[
'lorem',
false,
],
[
ReasonType::NOT_EXISTING_SURVEY_ID,
true,
],
[
ReasonType::NO_PARTICIPANTS_FOUND,
true,
],
[
ReasonType::NO_SURVEYS_FOUND,
true,
],
[
ReasonType::NO_TOKEN_TABLE,
true,
],
];
/*
yield[
'',
false,
@@ -79,5 +108,6 @@ class ReasonTypeTest extends BaseTypeTestCase
ReasonType::NO_TOKEN_TABLE,
true,
];
*/
}
}

View File

@@ -21,7 +21,7 @@ class SystemMethodTypeTest extends BaseTypeTestCase
{
public function testConstructorVisibilityAndArguments()
{
static::assertHasNoConstructor(SystemMethodType::class);
static::assertHasNoConstructor(SystemMethodType::className);
}
/**
@@ -48,6 +48,26 @@ class SystemMethodTypeTest extends BaseTypeTestCase
*/
public function provideTypeToVerify()
{
return [
[
'',
false,
],
[
'lorem',
false,
],
[
SystemMethodType::GET_SESSION_KEY,
true,
],
[
SystemMethodType::RELEASE_SESSION_KEY,
true,
],
];
/*
yield[
'',
false,
@@ -67,5 +87,6 @@ class SystemMethodTypeTest extends BaseTypeTestCase
SystemMethodType::RELEASE_SESSION_KEY,
true,
];
*/
}
}

Some files were not shown because too many files have changed in this diff Show More