diff --git a/.docker/config/Dockerfile b/.docker/config/Dockerfile
index cb2d05c..6102401 100644
--- a/.docker/config/Dockerfile
+++ b/.docker/config/Dockerfile
@@ -1,4 +1,4 @@
-FROM php:5.6-cli
+FROM php:5.4-cli
#
# Tools & libraries
@@ -31,12 +31,15 @@ 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
+#RUN pecl install xdebug \
+# && docker-php-ext-enable xdebug
+#COPY xdebug.ini /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
#
# Phing
diff --git a/.phing/tests.xml b/.phing/tests.xml
index 4567626..8ce4e50 100644
--- a/.phing/tests.xml
+++ b/.phing/tests.xml
@@ -146,13 +146,18 @@
2017-02-22
-->
-
+
+
diff --git a/composer.json b/composer.json
index cbe3b91..e5e15f4 100644
--- a/composer.json
+++ b/composer.json
@@ -11,22 +11,24 @@
}
],
"require": {
- "php": ">=5.6",
+ "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": {
diff --git a/src/Common/Collection/Collection.php b/src/Common/Collection/Collection.php
new file mode 100644
index 0000000..75770c2
--- /dev/null
+++ b/src/Common/Collection/Collection.php
@@ -0,0 +1,284 @@
+
+ * @copyright Meritoo.pl
+ */
+class Collection implements Countable, ArrayAccess, IteratorAggregate
+{
+ /**
+ * 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);
+ }
+}
diff --git a/src/Common/Exception/Base/UnknownTypeException.php b/src/Common/Exception/Base/UnknownTypeException.php
new file mode 100644
index 0000000..0a4c5e9
--- /dev/null
+++ b/src/Common/Exception/Base/UnknownTypeException.php
@@ -0,0 +1,41 @@
+
+ * @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);
+ }
+}
diff --git a/src/Common/Exception/Date/UnknownDatePartTypeException.php b/src/Common/Exception/Date/UnknownDatePartTypeException.php
new file mode 100644
index 0000000..d25a610
--- /dev/null
+++ b/src/Common/Exception/Date/UnknownDatePartTypeException.php
@@ -0,0 +1,32 @@
+
+ * @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));
+ }
+}
diff --git a/src/Common/Exception/File/EmptyFileException.php b/src/Common/Exception/File/EmptyFileException.php
new file mode 100644
index 0000000..14734d7
--- /dev/null
+++ b/src/Common/Exception/File/EmptyFileException.php
@@ -0,0 +1,31 @@
+
+ * @copyright Meritoo.pl
+ */
+class EmptyFileException extends \Exception
+{
+ /**
+ * 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);
+ }
+}
diff --git a/src/Common/Exception/File/EmptyFilePathException.php b/src/Common/Exception/File/EmptyFilePathException.php
new file mode 100644
index 0000000..5f80e6b
--- /dev/null
+++ b/src/Common/Exception/File/EmptyFilePathException.php
@@ -0,0 +1,26 @@
+
+ * @copyright Meritoo.pl
+ */
+class EmptyFilePathException extends \Exception
+{
+ /**
+ * Class constructor
+ */
+ public function __construct()
+ {
+ parent::__construct('Path of the file is empty. Did you provide path of proper file?');
+ }
+}
diff --git a/src/Common/Exception/File/NotExistingFileException.php b/src/Common/Exception/File/NotExistingFileException.php
new file mode 100644
index 0000000..51c6fa3
--- /dev/null
+++ b/src/Common/Exception/File/NotExistingFileException.php
@@ -0,0 +1,31 @@
+
+ * @copyright Meritoo.pl
+ */
+class NotExistingFileException extends \Exception
+{
+ /**
+ * 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);
+ }
+}
diff --git a/src/Common/Exception/Method/DisabledMethodException.php b/src/Common/Exception/Method/DisabledMethodException.php
new file mode 100644
index 0000000..7e12114
--- /dev/null
+++ b/src/Common/Exception/Method/DisabledMethodException.php
@@ -0,0 +1,40 @@
+
+ * @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);
+ }
+}
diff --git a/src/Common/Exception/Reflection/CannotResolveClassNameException.php b/src/Common/Exception/Reflection/CannotResolveClassNameException.php
new file mode 100644
index 0000000..21708a2
--- /dev/null
+++ b/src/Common/Exception/Reflection/CannotResolveClassNameException.php
@@ -0,0 +1,47 @@
+
+ * @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);
+ }
+}
diff --git a/src/Common/Exception/Reflection/MissingChildClassesException.php b/src/Common/Exception/Reflection/MissingChildClassesException.php
new file mode 100644
index 0000000..73c13b6
--- /dev/null
+++ b/src/Common/Exception/Reflection/MissingChildClassesException.php
@@ -0,0 +1,38 @@
+
+ * @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);
+ }
+}
diff --git a/src/Common/Exception/Reflection/TooManyChildClassesException.php b/src/Common/Exception/Reflection/TooManyChildClassesException.php
new file mode 100644
index 0000000..b5a4f13
--- /dev/null
+++ b/src/Common/Exception/Reflection/TooManyChildClassesException.php
@@ -0,0 +1,39 @@
+
+ * @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);
+ }
+}
diff --git a/src/Common/Exception/Regex/IncorrectColorHexLengthException.php b/src/Common/Exception/Regex/IncorrectColorHexLengthException.php
new file mode 100644
index 0000000..89ee485
--- /dev/null
+++ b/src/Common/Exception/Regex/IncorrectColorHexLengthException.php
@@ -0,0 +1,32 @@
+
+ * @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);
+ }
+}
diff --git a/src/Common/Exception/Regex/InvalidColorHexValueException.php b/src/Common/Exception/Regex/InvalidColorHexValueException.php
new file mode 100644
index 0000000..f17771a
--- /dev/null
+++ b/src/Common/Exception/Regex/InvalidColorHexValueException.php
@@ -0,0 +1,29 @@
+
+ * @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);
+ }
+}
diff --git a/src/Common/Exception/Regex/InvalidUrlException.php b/src/Common/Exception/Regex/InvalidUrlException.php
new file mode 100644
index 0000000..22834b9
--- /dev/null
+++ b/src/Common/Exception/Regex/InvalidUrlException.php
@@ -0,0 +1,25 @@
+
+ * @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);
+ }
+}
diff --git a/src/Common/Exception/Type/UnknownOopVisibilityTypeException.php b/src/Common/Exception/Type/UnknownOopVisibilityTypeException.php
new file mode 100644
index 0000000..4ac7165
--- /dev/null
+++ b/src/Common/Exception/Type/UnknownOopVisibilityTypeException.php
@@ -0,0 +1,23 @@
+
+ * @copyright Meritoo.pl
+ */
+class UnknownOopVisibilityTypeException extends UnknownTypeException
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function __construct($unknownType)
+ {
+ parent::__construct($unknownType, new OopVisibilityType(), 'OOP-related visibility');
+ }
+}
diff --git a/src/Common/Iterator/CommonIterator.php b/src/Common/Iterator/CommonIterator.php
new file mode 100644
index 0000000..9350951
--- /dev/null
+++ b/src/Common/Iterator/CommonIterator.php
@@ -0,0 +1,87 @@
+
+ * @copyright Meritoo.pl
+ */
+class CommonIterator implements Iterator
+{
+ /**
+ * Index/Position of current value
+ *
+ * @var int
+ */
+ private $currentIndex = 0;
+
+ /**
+ * Maximum index/position of current value
+ *
+ * @var int
+ */
+ private $maxIndex = 0;
+
+ /**
+ * Values to iterate
+ *
+ * @var array
+ */
+ private $values = [];
+
+ /**
+ * Class constructor
+ *
+ * @param array $values Values to iterate
+ */
+ public function __construct(array $values)
+ {
+ $this->values = $values;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function current()
+ {
+ return $this->values[$this->currentIndex];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function key()
+ {
+ return $this->currentIndex;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function next()
+ {
+ if (0 <= $this->currentIndex && $this->maxIndex > $this->currentIndex) {
+ ++$this->currentIndex;
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function rewind()
+ {
+ $this->currentIndex = 0;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function valid()
+ {
+ return 0 <= $this->currentIndex && $this->maxIndex >= $this->currentIndex;
+ }
+}
diff --git a/src/Common/Test/Base/BaseTestCase.php b/src/Common/Test/Base/BaseTestCase.php
new file mode 100644
index 0000000..9212bb2
--- /dev/null
+++ b/src/Common/Test/Base/BaseTestCase.php
@@ -0,0 +1,310 @@
+
+ * @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 CommonIterator
+ * //return Generator
+ */
+ public function provideEmptyValue()
+ {
+ return new CommonIterator([
+ '',
+ ' ',
+ null,
+ 0,
+ false,
+ [],
+ ]);
+
+ /*
+ yield[''];
+ yield[' '];
+ yield[null];
+ yield[0];
+ yield[false];
+ yield[[]];
+ */
+ }
+
+ /**
+ * Provides boolean value
+ *
+ * @return CommonIterator
+ * //return Generator
+ */
+ public function provideBooleanValue()
+ {
+ return new CommonIterator([
+ true,
+ false,
+ ]);
+
+ /*
+ yield[false];
+ yield[true];
+ */
+ }
+
+ /**
+ * Provides instance of DateTime class
+ *
+ * @return CommonIterator
+ * //return Generator
+ */
+ public function provideDateTimeInstance()
+ {
+ return new CommonIterator([
+ 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 CommonIterator
+ * //return Generator
+ */
+ public function provideDateTimeRelativeFormat()
+ {
+ return new CommonIterator([
+ '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 CommonIterator
+ * //return Generator
+ */
+ public function provideNotExistingFilePath()
+ {
+ return new CommonIterator([
+ '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);
+ }
+}
diff --git a/src/Common/Test/Base/BaseTypeTestCase.php b/src/Common/Test/Base/BaseTypeTestCase.php
new file mode 100644
index 0000000..aaa0bcc
--- /dev/null
+++ b/src/Common/Test/Base/BaseTypeTestCase.php
@@ -0,0 +1,64 @@
+
+ * @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();
+}
diff --git a/src/Common/Type/Base/BaseType.php b/src/Common/Type/Base/BaseType.php
new file mode 100644
index 0000000..56f6a19
--- /dev/null
+++ b/src/Common/Type/Base/BaseType.php
@@ -0,0 +1,53 @@
+
+ * @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);
+ }
+}
diff --git a/src/Common/Type/DatePartType.php b/src/Common/Type/DatePartType.php
new file mode 100644
index 0000000..5467a4d
--- /dev/null
+++ b/src/Common/Type/DatePartType.php
@@ -0,0 +1,62 @@
+
+ * @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';
+}
diff --git a/src/Common/Type/OopVisibilityType.php b/src/Common/Type/OopVisibilityType.php
new file mode 100644
index 0000000..59ede6d
--- /dev/null
+++ b/src/Common/Type/OopVisibilityType.php
@@ -0,0 +1,37 @@
+
+ * @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;
+}
diff --git a/src/Common/Utilities/Arrays.php b/src/Common/Utilities/Arrays.php
new file mode 100644
index 0000000..bdfe20b
--- /dev/null
+++ b/src/Common/Utilities/Arrays.php
@@ -0,0 +1,1641 @@
+
+ * @copyright Meritoo.pl
+ */
+class Arrays
+{
+ /**
+ * Name of the array's key used to store position of element of the array
+ *
+ * @var string
+ */
+ const POSITION_KEY_NAME = 'position';
+
+ /**
+ * Converts given array's column to string.
+ * Recursive call is made for multi-dimensional arrays.
+ *
+ * @param array $array Array data to be converted
+ * @param string|int $arrayColumnKey (optional) Column name
+ * @param string $separator (optional) Separator used in resultant string
+ * @return string
+ */
+ public static function values2string(array $array, $arrayColumnKey = '', $separator = ',')
+ {
+ $effect = '';
+
+ if (!empty($array)) {
+ foreach ($array as $key => $value) {
+ if (!empty($effect) &&
+ (
+ empty($arrayColumnKey) || (!is_array($value) && $key === $arrayColumnKey)
+ )
+ ) {
+ $effect .= $separator;
+ }
+
+ if (is_array($value)) {
+ $effect .= self::values2string($value, $arrayColumnKey, $separator);
+ /*
+ * Previous version. Doesn't work with array containing arrays, e.g.:
+ * array(
+ * 1 => array(
+ * 'item1',
+ * 'item2'
+ * ),
+ * 2 => array(
+ * 'item3',
+ * 'item4'
+ * )
+ * )
+ *
+ if(isset($value[$arrayColumnKey])){
+ $effect .= $value[$arrayColumnKey];
+ }
+ */
+ } else {
+ if (empty($arrayColumnKey)) {
+ $effect .= $value;
+ } elseif ($key === $arrayColumnKey) {
+ $effect .= $array[$arrayColumnKey];
+ }
+ }
+ }
+ }
+
+ return $effect;
+ }
+
+ /**
+ * Converts given array to string with keys, e.g. abc=1&def=2 or abc="1" def="2"
+ *
+ * @param array $array Array data to be converted
+ * @param string $separator (optional) Separator used between name-value pairs in resultant string
+ * @param string $valuesKeysSeparator (optional) Separator used between name and value in resultant string
+ * @param string $valuesWrapper (optional) Wrapper used to wrap values, e.g. double-quote: key="value"
+ * @return string
+ */
+ public static function valuesKeys2string($array, $separator = ',', $valuesKeysSeparator = '=', $valuesWrapper = '')
+ {
+ $effect = '';
+
+ if (is_array($array) && !empty($array)) {
+ foreach ($array as $key => $value) {
+ if (!empty($effect)) {
+ $effect .= $separator;
+ }
+
+ if (!empty($valuesWrapper)) {
+ $value = sprintf('%s%s%s', $valuesWrapper, $value, $valuesWrapper);
+ }
+
+ $effect .= $key . $valuesKeysSeparator . $value;
+ }
+ }
+
+ return $effect;
+ }
+
+ /**
+ * Converts given array's rows to csv string
+ *
+ * @param array $array Array data to be converted. It have to be an array that represents database table.
+ * @param string $separator (optional) Separator used in resultant string
+ * @return string
+ */
+ public static function values2csv($array, $separator = ',')
+ {
+ if (is_array($array) && !empty($array)) {
+ $rows = [];
+ $lineSeparator = "\n";
+
+ foreach ($array as $row) {
+ /*
+ * I have to use html_entity_decode() function here, because some string values can contain
+ * entities with semicolon and this can destroy the CSV column order.
+ */
+
+ if (is_array($row) && !empty($row)) {
+ foreach ($row as &$value) {
+ $value = html_entity_decode($value);
+ }
+
+ $rows[] = implode($separator, $row);
+ }
+ }
+
+ if (!empty($rows)) {
+ return implode($lineSeparator, $rows);
+ }
+ }
+
+ return '';
+ }
+
+ /**
+ * Returns information if given element is the first one
+ *
+ * @param array $array The array to get the first element of
+ * @param mixed $element The element to check / verify
+ * @param bool $firstLevelOnly (optional) If is set to true, first element is returned. Otherwise - totally
+ * first element is returned (first of the First array).
+ * @return bool
+ */
+ public static function isFirstElement(array $array, $element, $firstLevelOnly = true)
+ {
+ $firstElement = self::getFirstElement($array, $firstLevelOnly);
+
+ return $element === $firstElement;
+ }
+
+ /**
+ * Returns the first element of given array
+ *
+ * It may be first element of given array or the totally first element from the all elements (first element of the
+ * first array).
+ *
+ * @param array $array The array to get the first element of
+ * @param bool $firstLevelOnly (optional) If is set to true, first element is returned. Otherwise - totally
+ * first element is returned (first of the first array).
+ * @return mixed
+ */
+ public static function getFirstElement(array $array, $firstLevelOnly = true)
+ {
+ /*
+ * No elements?
+ * Nothing to do
+ */
+ if (empty($array)) {
+ return null;
+ }
+
+ $firstKey = self::getFirstKey($array);
+ $first = $array[$firstKey];
+
+ if (!$firstLevelOnly && is_array($first)) {
+ $first = self::getFirstElement($first, $firstLevelOnly);
+ }
+
+ return $first;
+ }
+
+ /**
+ * Returns first key of array
+ *
+ * @param array $array The array to get the first key of
+ * @return mixed
+ */
+ public static function getFirstKey(array $array)
+ {
+ /*
+ * No elements?
+ * Nothing to do
+ */
+ if (empty($array)) {
+ return null;
+ }
+
+ $keys = array_keys($array);
+
+ return $keys[0];
+ }
+
+ /**
+ * Returns information if given element is the last one
+ *
+ * @param array $array The array to get the last element of
+ * @param mixed $element The element to check / verify
+ * @param bool $firstLevelOnly (optional) If is set to true, last element is returned. Otherwise - totally
+ * last element is returned (last of the latest array).
+ * @return bool
+ */
+ public static function isLastElement(array $array, $element, $firstLevelOnly = true)
+ {
+ $lastElement = self::getLastElement($array, $firstLevelOnly);
+
+ return $element === $lastElement;
+ }
+
+ /**
+ * Returns the last element of given array
+ *
+ * It may be last element of given array or the totally last element from the all elements (last element of the
+ * latest array).
+ *
+ * @param array $array The array to get the last element of
+ * @param bool $firstLevelOnly (optional) If is set to true, last element is returned. Otherwise - totally
+ * last element is returned (last of the latest array).
+ * @return mixed
+ */
+ public static function getLastElement(array $array, $firstLevelOnly = true)
+ {
+ /*
+ * No elements?
+ * Nothing to do
+ */
+ if (empty($array)) {
+ return null;
+ }
+
+ $last = end($array);
+
+ if (!$firstLevelOnly && is_array($last)) {
+ $last = self::getLastElement($last, $firstLevelOnly);
+ }
+
+ return $last;
+ }
+
+ /**
+ * Returns breadcrumb (a path) to the last element of array
+ *
+ * @param array $array The array to get the breadcrumb
+ * @param string $separator (optional) Separator used to stick the elements
+ * @return string
+ */
+ public static function getLastElementBreadCrumb($array, $separator = '/')
+ {
+ $keys = array_keys($array);
+ $keysCount = count($keys);
+
+ $lastKey = $keys[$keysCount - 1];
+ $last = end($array);
+
+ $breadCrumb = $lastKey;
+
+ if (is_array($last)) {
+ $crumb = self::getLastElementBreadCrumb($last, $separator);
+ } else {
+ $crumb = $last;
+ }
+
+ return $breadCrumb . $separator . $crumb;
+ }
+
+ /**
+ * Returns the last row of array
+ *
+ * @param array $array The array to get the last row of
+ * @return mixed
+ */
+ public static function getLastRow(array $array)
+ {
+ /*
+ * No elements?
+ * Nothing to do
+ */
+ if (empty($array)) {
+ return null;
+ }
+
+ $effect = [];
+ $last = end($array);
+
+ if (is_array($last)) {
+ /*
+ * We've got an array, so looking for the last row of array will be done recursively
+ */
+ $effect = self::getLastRow($last);
+
+ /*
+ * The last row is not an array or it's an empty array?
+ * Let's use the previous candidate
+ */
+ if (!is_array($effect) || (is_array($effect) && empty($effect))) {
+ $effect = $last;
+ }
+ }
+
+ return $effect;
+ }
+
+ /**
+ * Replaces array keys that match given pattern with new key name
+ *
+ * @param array $dataArray The array
+ * @param string $oldKeyPattern Old key pattern
+ * @param string $newKey New key name
+ * @return array
+ */
+ public static function replaceArrayKeys($dataArray, $oldKeyPattern, $newKey)
+ {
+ $effect = [];
+
+ if (is_array($dataArray) && !empty($dataArray)) {
+ foreach ($dataArray as $key => $value) {
+ if (preg_match($oldKeyPattern, $key)) {
+ $key = $newKey;
+ }
+
+ if (is_array($value)) {
+ $value = self::replaceArrayKeys($value, $oldKeyPattern, $newKey);
+ }
+
+ $effect[$key] = $value;
+ }
+ }
+
+ return $effect;
+ }
+
+ /**
+ * Generates JavaScript code for given PHP array
+ *
+ * @param array $array The array that should be generated to JavaScript
+ * @param string $jsVariableName (optional) Name of the variable that will be in generated JavaScript code
+ * @param bool $preserveIndexes (optional) If is set to true and $jsVariableName isn't empty, indexes also
+ * will be added to the JavaScript code. Otherwise not.
+ * @return string|null
+ */
+ public static function array2JavaScript(array $array, $jsVariableName = '', $preserveIndexes = false)
+ {
+ /*
+ * No elements?
+ * Nothing to do
+ */
+ if (empty($array)) {
+ return null;
+ }
+
+ $effect = '';
+ $counter = 0;
+
+ $arrayCount = count($array);
+ $array = self::quoteStrings($array);
+ $isMultiDimensional = self::isMultiDimensional($array);
+
+ /*
+ * Name of the variable was not provided and it's a multi dimensional array?
+ * Let's create the name, because variable is required for later usage (related to multi dimensional array)
+ */
+ if (self::isMultiDimensional($array) && empty($jsVariableName)) {
+ $jsVariableName = 'autoGeneratedVariable';
+ }
+
+ if (!empty($jsVariableName) && is_string($jsVariableName)) {
+ $effect .= sprintf('var %s = ', $jsVariableName);
+ }
+
+ $effect .= 'new Array(';
+
+ if ($preserveIndexes || $isMultiDimensional) {
+ $effect .= $arrayCount;
+ $effect .= ');';
+ }
+
+ foreach ($array as $index => $value) {
+ ++$counter;
+
+ if (is_array($value)) {
+ $variable = $index;
+
+ if (is_integer($index)) {
+ $variable = 'value_' . $variable;
+ }
+
+ $value = self::array2JavaScript($value, $variable, $preserveIndexes);
+
+ if (!empty($value)) {
+ /*
+ * Add an empty line for the 1st iteration only. Required to avoid missing empty line after
+ * declaration of variable:
+ *
+ * var autoGeneratedVariable = new Array(...);autoGeneratedVariable[0] = new Array(...);
+ * autoGeneratedVariable[1] = new Array(...);
+ */
+ if (1 === $counter) {
+ $effect .= "\n";
+ }
+
+ $effect .= $value . "\n";
+ $effect .= sprintf('%s[%s] = %s;', $jsVariableName, Miscellaneous::quoteValue($index), $variable);
+
+ if ($counter !== $arrayCount) {
+ $effect .= "\n";
+ }
+ }
+ } else {
+ if ($preserveIndexes) {
+ if (!empty($jsVariableName)) {
+ $index = Miscellaneous::quoteValue($index);
+ $effect .= sprintf("\n%s[%s] = %s;", $jsVariableName, $index, $value);
+ }
+ } else {
+ $format = '%s';
+
+ if ($counter < $arrayCount) {
+ $format .= ', ';
+ }
+
+ $effect .= sprintf($format, $value);
+ }
+ }
+ }
+
+ if (!$preserveIndexes && !$isMultiDimensional) {
+ $effect .= ');';
+ }
+
+ return $effect;
+ }
+
+ /**
+ * Quotes (adds quotes) to elements of an array that are strings
+ *
+ * @param array $array The array to check for string values
+ * @return array
+ */
+ public static function quoteStrings($array)
+ {
+ $effect = $array;
+
+ if (is_array($array) && !empty($array)) {
+ $effect = [];
+
+ foreach ($array as $index => $value) {
+ if (is_array($value)) {
+ $value = self::quoteStrings($value);
+ } elseif (is_string($value)) {
+ if (!Regex::isQuoted($value)) {
+ $value = '\'' . $value . '\'';
+ }
+ }
+
+ $effect[$index] = $value;
+ }
+ }
+
+ return $effect;
+ }
+
+ /**
+ * Removes marginal element (first or last)
+ *
+ * @param string|array $item The item which should be shortened
+ * @param bool $last (optional) If is set to true, last element is removed. Otherwise - first.
+ * @return string|array
+ */
+ public static function removeMarginalElement($item, $last = true)
+ {
+ if (is_string($item)) {
+ if ($last) {
+ $item = substr($item, 0, strlen($item) - 1);
+ } else {
+ $item = substr($item, 1);
+ }
+ } elseif (is_array($item)) {
+ $key = self::getFirstKey($item);
+
+ if ($last) {
+ $key = self::getLastKey($item);
+ }
+
+ unset($item[$key]);
+ }
+
+ return $item;
+ }
+
+ /**
+ * Returns last key of array
+ *
+ * @param array $array The array to get the last key of
+ * @return mixed
+ */
+ public static function getLastKey(array $array)
+ {
+ $keys = array_keys($array);
+
+ return end($keys);
+ }
+
+ /**
+ * Removes element / item of given array
+ *
+ * @param array $array The array that contains element / item which should be removed
+ * @param mixed $item The element / item which should be removed
+ * @return bool|array
+ */
+ public static function removeElement(array $array, $item)
+ {
+ if (empty($array) || !in_array($item, $array)) {
+ return false;
+ }
+
+ /*
+ * Flip the array to make it looks like: value => key
+ */
+ $arrayFlipped = array_flip($array);
+
+ /*
+ * Take the key of element / item that should be removed
+ */
+ $key = $arrayFlipped[$item];
+
+ /*
+ * ...and remove the element / item
+ */
+ unset($array[$key]);
+
+ return $array;
+ }
+
+ /**
+ * Removes items from given array starting at given element (before or after the element)
+ *
+ * @param array $array The array which contains items to remove
+ * @param mixed $needle The element which is start point of deletion
+ * @param bool $before (optional) If is set to true, all elements before given needle are removed. Otherwise - all
+ * after needle.
+ */
+ public static function removeElements(&$array, $needle, $before = true)
+ {
+ if (is_array($array) && !empty($array)) {
+ if (!$before) {
+ $array = array_reverse($array, true);
+ }
+
+ foreach ($array as $key => &$value) {
+ $remove = false;
+
+ if (is_array($value)) {
+ self::removeElements($value, $needle, $before);
+
+ if (is_array($value) && empty($value)) {
+ $remove = true;
+ }
+ } else {
+ if ($value === $needle) {
+ break;
+ } else {
+ $remove = true;
+ }
+ }
+
+ if ($remove) {
+ unset($array[$key]);
+ }
+ }
+
+ if (!$before) {
+ $array = array_reverse($array, true);
+ }
+ }
+ }
+
+ /**
+ * Sets keys as values and values as keys in given array.
+ * Replaces keys with values.
+ *
+ * @param array $array The array to change values with keys
+ * @param bool $ignoreDuplicatedValues (optional) If is set to true, duplicated values are ignored. This means that
+ * when there is more than 1 value and that values become key, only the last
+ * value will be used with it's key, because other will be overridden.
+ * Otherwise - values are preserved and keys assigned to that values are
+ * returned as an array.
+ * @return array
+ *
+ * Example of $ignoreDuplicatedValues = false:
+ * - provided array
+ * $array = [
+ * 'lorem' => 100, // <-- Duplicated value
+ * 'ipsum' => 200,
+ * 'dolor' => 100, // <-- Duplicated value
+ * ];
+ *
+ * - result
+ * $replaced = [
+ * 100 => [
+ * 'lorem', // <-- Key of duplicated value
+ * 'dolor', // <-- Key of duplicated value
+ * ],
+ * 200 => 'ipsum',
+ * ];
+ */
+ public static function setKeysAsValues(array $array, $ignoreDuplicatedValues = true)
+ {
+ if (empty($array)) {
+ return [];
+ }
+
+ $replaced = [];
+
+ foreach ($array as $key => $value) {
+ /*
+ * The value it's an array?
+ * Let's replace keys with values in this array first
+ */
+ if (is_array($value)) {
+ $replaced[$key] = self::setKeysAsValues($value, $ignoreDuplicatedValues);
+ continue;
+ }
+
+ /*
+ * Duplicated values shouldn't be ignored and processed value is used as key already?
+ * Let's use an array and that will contain all values (to avoid ignoring / overriding duplicated values)
+ */
+ if (!$ignoreDuplicatedValues && isset($replaced[$value])) {
+ $existing = self::makeArray($replaced[$value]);
+
+ $replaced[$value] = array_merge($existing, [
+ $key,
+ ]);
+
+ continue;
+ }
+
+ /*
+ * Standard behaviour
+ */
+ $replaced[$value] = $key;
+ }
+
+ return $replaced;
+ }
+
+ /**
+ * Applies ksort() function recursively in the given array
+ *
+ * @param array $array The array to sort
+ * @param int $sortFlags (optional) Options of ksort() function
+ * @return array|null
+ */
+ public static function ksortRecursive(array &$array, $sortFlags = SORT_REGULAR)
+ {
+ /*
+ * No elements?
+ * Nothing to do
+ */
+ if (empty($array)) {
+ return null;
+ }
+
+ $effect = $array;
+ ksort($effect, $sortFlags);
+
+ foreach ($effect as &$value) {
+ if (is_array($value)) {
+ ksort($value, $sortFlags);
+ }
+ }
+
+ return $effect;
+ }
+
+ /**
+ * Returns count / amount of elements that are not array
+ *
+ * @param array $array The array to count
+ * @return int|null
+ */
+ public static function getNonArrayElementsCount(array $array)
+ {
+ /*
+ * No elements?
+ * Nothing to do
+ */
+ if (empty($array)) {
+ return null;
+ }
+
+ $count = 0;
+
+ foreach ($array as &$value) {
+ if (is_array($value)) {
+ $count += self::getNonArrayElementsCount($value);
+ continue;
+ }
+
+ ++$count;
+ }
+
+ return $count;
+ }
+
+ /**
+ * Converts given string with special separators to array
+ *
+ * Example:
+ * ~ string:
+ * "light:jasny|dark:ciemny"
+ *
+ * ~ array as a result:
+ * [
+ * 'light' => 'jasny',
+ * 'dark' => 'ciemny',
+ * ]
+ *
+ * @param string $string The string to be converted
+ * @param string $separator (optional) Separator used between name-value pairs in the string
+ * @param string $valuesKeysSeparator (optional) Separator used between name and value in the string
+ * @return array
+ */
+ public static function string2array($string, $separator = '|', $valuesKeysSeparator = ':')
+ {
+ /*
+ * Empty string?
+ * Nothing to do
+ */
+ if (empty($string)) {
+ return null;
+ }
+
+ $array = [];
+ $exploded = explode($separator, $string);
+
+ foreach ($exploded as $item) {
+ $exploded2 = explode($valuesKeysSeparator, $item);
+
+ if (2 == count($exploded2)) {
+ $key = trim($exploded2[0]);
+ $value = trim($exploded2[1]);
+
+ $array[$key] = $value;
+ }
+ }
+
+ return $array;
+ }
+
+ /**
+ * Returns information if given keys exist in given array
+ *
+ * @param array $keys The keys to find
+ * @param array $array The array which maybe contains keys
+ * @param bool $explicit (optional) If is set to true, all keys should exist in given array. Otherwise - not all.
+ * @return bool
+ */
+ public static function areKeysInArray($keys, $array, $explicit = true)
+ {
+ $effect = false;
+
+ if (is_array($array) && !empty($array)) {
+ $firstKey = true;
+
+ foreach ($keys as $key) {
+ $exists = array_key_exists($key, $array);
+
+ if ($firstKey) {
+ $effect = $exists;
+ $firstKey = false;
+ } else {
+ if ($explicit) {
+ $effect = $effect && $exists;
+
+ if (!$effect) {
+ break;
+ }
+ } else {
+ $effect = $effect || $exists;
+
+ if ($effect) {
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ return $effect;
+ }
+
+ /**
+ * Returns paths of the last elements
+ *
+ * @param array $array The array with elements
+ * @param string $separator (optional) Separator used in resultant strings. Default: ".".
+ * @param string $parentPath (optional) Path of the parent element. Default: "".
+ * @param string|array $stopIfMatchedBy (optional) Patterns of keys or paths that matched will stop the process
+ * of path building and including children of those keys or paths (recursive
+ * will not be used for keys in lower level of given array)
+ * @return array
+ *
+ * Examples - $stopIfMatchedBy argument:
+ * a) "\d+"
+ * b) [
+ * "lorem\-",
+ * "\d+",
+ * ];
+ */
+ public static function getLastElementsPaths(array $array, $separator = '.', $parentPath = '', $stopIfMatchedBy = '')
+ {
+ $paths = [];
+
+ if (!empty($array)) {
+ if (!empty($stopIfMatchedBy)) {
+ $stopIfMatchedBy = self::makeArray($stopIfMatchedBy);
+ }
+
+ foreach ($array as $key => $value) {
+ $path = $key;
+ $stopRecursion = false;
+
+ /*
+ * If the path of parent element is delivered,
+ * I have to use it and build longer path
+ */
+ if (!empty($parentPath)) {
+ $pathTemplate = '%s%s%s';
+ $path = sprintf($pathTemplate, $parentPath, $separator, $key);
+ }
+
+ /*
+ * Check if the key or current path matches one of patterns at which the process should be stopped,
+ * the recursive not used. It means that I have to pass current value and stop processing of the
+ * array (don't go to the next step).
+ */
+ if (!empty($stopIfMatchedBy)) {
+ foreach ($stopIfMatchedBy as $rawPattern) {
+ $pattern = sprintf('|%s|', $rawPattern);
+
+ if (preg_match($pattern, $key) || preg_match($pattern, $path)) {
+ $stopRecursion = true;
+ break;
+ }
+ }
+ }
+
+ /*
+ * The value is passed to the returned array if:
+ * - it's not an array
+ * or
+ * - the process is stopped, recursive is not used
+ */
+ if (!is_array($value) || (is_array($value) && empty($value)) || $stopRecursion) {
+ $paths[$path] = $value;
+ continue;
+ }
+
+ /*
+ * Let's iterate through the next level, using recursive
+ */
+ if (is_array($value)) {
+ $recursivePaths = self::getLastElementsPaths($value, $separator, $path, $stopIfMatchedBy);
+ $paths += $recursivePaths;
+ }
+ }
+ }
+
+ return $paths;
+ }
+
+ /**
+ * Makes and returns an array for given variable
+ *
+ * @param mixed $variable Variable that should be an array
+ * @return array
+ */
+ public static function makeArray($variable)
+ {
+ if (is_array($variable)) {
+ return $variable;
+ }
+
+ return [$variable];
+ }
+
+ /**
+ * Returns information if keys / indexes of given array are matched by given pattern
+ *
+ * @param array $array The array to check
+ * @param string $pattern The pattern which keys / indexes should match, e.g. "\d+"
+ * @param bool $firstLevelOnly (optional) If is set to true, all keys / indexes are checked. Otherwise - from the
+ * first level only.
+ * @return bool
+ */
+ public static function areAllKeysMatchedByPattern($array, $pattern, $firstLevelOnly = false)
+ {
+ /*
+ * It's not an array or it's empty array?
+ */
+ if (!is_array($array) || (is_array($array) && empty($array))) {
+ return false;
+ }
+
+ /*
+ * I suppose that all are keys are matched
+ * and then I have to look for keys that don't matches
+ */
+ $areMatched = true;
+
+ /*
+ * Building the pattern
+ */
+ $rawPattern = $pattern;
+ $pattern = sprintf('|%s|', $rawPattern);
+
+ foreach ($array as $key => $value) {
+ /*
+ * Not matched? So I have to stop the iteration, because one not matched key
+ * means that not all keys are matched by given pattern
+ */
+ if (!preg_match($pattern, $key)) {
+ $areMatched = false;
+ break;
+ }
+
+ /*
+ * The not matching key was not found and the value is an array?
+ * Let's begin recursive looking for result
+ */
+ if ($areMatched && is_array($value) && !$firstLevelOnly) {
+ $areMatched = self::areAllKeysMatchedByPattern($value, $rawPattern, $firstLevelOnly);
+ }
+ }
+
+ return $areMatched;
+ }
+
+ /**
+ * Returns information if keys / indexes of given array are integers, in other words if the array contains
+ * zero-based keys / indexes
+ *
+ * @param array $array The array to check
+ * @param bool $firstLevelOnly (optional) If is set to true, all keys / indexes are checked. Otherwise - from the
+ * first level only.
+ * @return bool
+ */
+ public static function areAllKeysIntegers($array, $firstLevelOnly = false)
+ {
+ $pattern = '\d+';
+
+ return self::areAllKeysMatchedByPattern($array, $pattern, $firstLevelOnly);
+ }
+
+ /**
+ * Returns value of given array set under given path of keys, of course if the value exists.
+ * The keys should be delivered in the same order as used by source array.
+ *
+ * @param array $array The array which should contains a value
+ * @param array $keys Keys, path of keys, to find in given array
+ * @return mixed
+ *
+ * Examples:
+ * a) $array
+ * [
+ * 'some key' => [
+ * 'another some key' => [
+ * 'yet another key' => 123,
+ * ],
+ * 'some different key' => 456,
+ * ]
+ * ]
+ *
+ * b) $keys
+ * [
+ * 'some key',
+ * 'another some key',
+ * 'yet another key',
+ * ]
+ *
+ * Based on the above examples will return:
+ * 123
+ */
+ public static function getValueByKeysPath(array $array, array $keys)
+ {
+ $value = null;
+
+ if (!empty($array) && self::issetRecursive($array, $keys)) {
+ foreach ($keys as $key) {
+ $value = $array[$key];
+ array_shift($keys);
+
+ if (is_array($value) && !empty($keys)) {
+ $value = self::getValueByKeysPath($value, $keys);
+ }
+
+ break;
+ }
+ }
+
+ return $value;
+ }
+
+ /**
+ * Returns information if given path of keys are set is given array.
+ * The keys should be delivered in the same order as used by source array.
+ *
+ * @param array $array The array to check
+ * @param array $keys Keys, path of keys, to find in given array
+ * @return bool
+ *
+ * Examples:
+ * a) $array
+ * [
+ * 'some key' => [
+ * 'another some key' => [
+ * 'yet another key' => 123,
+ * ],
+ * 'some different key' => 456,
+ * ]
+ * ]
+ *
+ * b) $keys
+ * [
+ * 'some key',
+ * 'another some key',
+ * 'yet another key',
+ * ]
+ */
+ public static function issetRecursive(array $array, array $keys)
+ {
+ $isset = false;
+
+ if (!empty($array)) {
+ foreach ($keys as $key) {
+ $isset = isset($array[$key]);
+
+ if ($isset) {
+ $newArray = $array[$key];
+ array_shift($keys);
+
+ if (is_array($newArray) && !empty($keys)) {
+ $isset = self::issetRecursive($newArray, $keys);
+ }
+ }
+
+ break;
+ }
+ }
+
+ return $isset;
+ }
+
+ /**
+ * Returns all values of given key.
+ * It may be useful when you want to retrieve all values of one column.
+ *
+ * @param array $array The array which should contain values of the key
+ * @param string $key The key
+ * @return array|null
+ */
+ public static function getAllValuesOfKey(array $array, $key)
+ {
+ if (empty($array)) {
+ return null;
+ }
+
+ $values = [];
+
+ foreach ($array as $index => $value) {
+ if ($index === $key) {
+ $values[] = $value;
+ continue;
+ }
+
+ if (is_array($value)) {
+ $recursiveValues = self::getAllValuesOfKey($value, $key);
+
+ if (!empty($recursiveValues)) {
+ $values = array_merge($values, $recursiveValues);
+ }
+ }
+ }
+
+ return $values;
+ }
+
+ /**
+ * Sets positions for each element / child of given array and returns the array
+ *
+ * Position for the 1st element / child of a parent is set to 1 and incremented for the next element and
+ * so on. Each parent is treated as separate array, so its elements are treated as positioned at 1st level.
+ *
+ * @param array $array The array which should has values of position for each element
+ * @param string $keyName (optional) Name of key which will contain the position value
+ * @param int $startPosition (optional) Default, start value of the position for main / given array, not the
+ * children
+ * @return array
+ */
+ public static function setPositions(array $array, $keyName = self::POSITION_KEY_NAME, $startPosition = null)
+ {
+ if (!empty($array)) {
+ $childPosition = 1;
+
+ if (null !== $startPosition) {
+ $array[$keyName] = $startPosition;
+ }
+
+ foreach ($array as &$value) {
+ if (is_array($value)) {
+ $value = self::setPositions($value, $keyName, $childPosition);
+ ++$childPosition;
+ }
+ }
+ }
+
+ return $array;
+ }
+
+ /**
+ * Trims string values of given array and returns the new array
+ *
+ * @param array $array The array which values should be trimmed
+ * @return array
+ */
+ public static function trimRecursive(array $array)
+ {
+ $effect = $array;
+
+ if (!empty($array)) {
+ $effect = [];
+
+ foreach ($array as $key => $value) {
+ if (is_array($value)) {
+ $effect[$key] = self::trimRecursive($value);
+ continue;
+ }
+
+ if (is_string($value)) {
+ $value = trim($value);
+ }
+
+ $effect[$key] = $value;
+ }
+ }
+
+ return $effect;
+ }
+
+ /**
+ * Sorts an array by keys given in second array as values.
+ * Keys which are not in array with order are pushed after sorted elements.
+ *
+ * Example:
+ * - array to sort:
+ *
+ * array(
+ * 'lorem' => array(
+ * 'ipsum'
+ * ),
+ * 'dolor' => array(
+ * 'sit',
+ * 'amet'
+ * ),
+ * 'neque' => 'neque'
+ * )
+ *
+ * - keys order:
+ *
+ * array(
+ * 'dolor',
+ * 'lorem'
+ * )
+ *
+ * - the result:
+ *
+ * array(
+ * 'dolor' => array(
+ * 'sit',
+ * 'amet'
+ * ),
+ * 'lorem' => array(
+ * 'ipsum'
+ * ),
+ * 'neque' => 'neque' // <-- the rest, values of other keys
+ * )
+ *
+ *
+ * @param array $array An array to sort
+ * @param array $keysOrder An array with keys of the 1st argument in proper / required order
+ * @return array|null
+ */
+ public static function sortByCustomKeysOrder(array $array, array $keysOrder)
+ {
+ /*
+ * No elements?
+ * Nothing to do
+ */
+ if (empty($array)) {
+ return null;
+ }
+
+ $ordered = [];
+
+ /*
+ * 1st iteration:
+ * Get elements in proper / required order
+ */
+ if (!empty($keysOrder)) {
+ foreach ($keysOrder as $key) {
+ if (isset($array[$key])) {
+ $ordered[$key] = $array[$key];
+ unset($array[$key]);
+ }
+ }
+ }
+
+ /*
+ * 2nd iteration:
+ * Get the rest of elements
+ */
+ if (!empty($array)) {
+ foreach ($array as $key => $element) {
+ $ordered[$key] = $element;
+ }
+ }
+
+ return $ordered;
+ }
+
+ /**
+ * Returns smartly imploded string
+ *
+ * Separators located at the beginning or end of elements are removed.
+ * It's required to avoid problems with duplicated separator, e.g. "first//second/third", where separator is a
+ * "/" string.
+ *
+ * @param array $array The array with elements to implode
+ * @param string $separator Separator used to stick together elements of given array
+ * @return string
+ */
+ public static function implodeSmart(array $array, $separator)
+ {
+ /*
+ * No elements?
+ * Nothing to do
+ */
+ if (empty($array)) {
+ return '';
+ }
+
+ foreach ($array as &$element) {
+ if (is_array($element)) {
+ $element = self::implodeSmart($element, $separator);
+ }
+
+ if (Regex::startsWith($element, $separator)) {
+ $element = substr($element, 1);
+ }
+
+ if (Regex::endsWith($element, $separator)) {
+ $element = substr($element, 0, strlen($element) - 1);
+ }
+ }
+
+ return implode($separator, $array);
+ }
+
+ /**
+ * Returns information if given array is empty, iow. information if all elements of given array are empty
+ *
+ * @param array $array The array to verify
+ * @param bool $strictNull (optional) If is set to true elements are verified if they are null. Otherwise - only
+ * if they are empty (e.g. null, '', 0, array()).
+ * @return bool
+ */
+ public static function areAllValuesEmpty(array $array, $strictNull = false)
+ {
+ /*
+ * No elements?
+ * Nothing to do
+ */
+ if (empty($array)) {
+ return false;
+ }
+
+ foreach ($array as $element) {
+ /*
+ * If elements are verified if they are exactly null and the element is:
+ * - not an array
+ * - not null
+ * or elements are NOT verified if they are exactly null and the element is:
+ * - not empty (e.g. null, '', 0, array())
+ *
+ * If one of the above is true, not all elements of given array are empty
+ */
+ if ((!is_array($element) && $strictNull && null !== $element) || !empty($element)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Returns an array containing all the entries from 1st array that are not present in 2nd array.
+ * An item from 1st array is the same as in 2nd array if both, keys and values, are the same.
+ *
+ * Example of difference:
+ * $array1 = [
+ * 1 => 'Lorem',
+ * 2 => 'ipsum,
+ * ];
+ *
+ * $array2 = [
+ * 1 => 'Lorem',
+ * 5 => 'ipsum, // <-- The same values, but different key. Here we got 5, in 1st array - 2.
+ * ];
+ *
+ * @param array $array1 The 1st array to verify
+ * @param array $array2 The 2nd array to verify
+ * @param bool $valuesOnly (optional) If is set to true, compares values only. Otherwise - keys and values
+ * (default behaviour).
+ * @return array
+ */
+ public static function arrayDiffRecursive(array $array1, array $array2, $valuesOnly = false)
+ {
+ $effect = [];
+
+ /*
+ * Values should be compared only and both arrays are one-dimensional?
+ * Let's find difference by using simple function
+ */
+ if ($valuesOnly && 1 == self::getDimensionsCount($array1) && 1 == self::getDimensionsCount($array2)) {
+ return array_diff($array1, $array2);
+ }
+
+ foreach ($array1 as $key => $value) {
+ $array2HasKey = array_key_exists($key, $array2);
+
+ /*
+ * Values should be compared only?
+ */
+ if ($valuesOnly) {
+ $difference = null;
+
+ if (is_array($value)) {
+ if ($array2HasKey && is_array($array2[$key])) {
+ $difference = self::arrayDiffRecursive($value, $array2[$key], $valuesOnly);
+ }
+ } else {
+ /*
+ * 2nd array hasn't key from 1st array?
+ * OR
+ * Key exists in both, 1st and 2nd array, but values are different?
+ */
+ if (!$array2HasKey || ($array2HasKey && $value != $array2[$key])) {
+ $difference = $value;
+ }
+ }
+
+ if (null !== $difference) {
+ $effect[] = $difference;
+ }
+ } else {
+ /*
+ * The key exists in 2nd array?
+ */
+ if ($array2HasKey) {
+ /*
+ * The value it's an array (it's a nested array)?
+ */
+ if (is_array($value)) {
+ $diff = [];
+
+ if (is_array($array2[$key])) {
+ /*
+ * Let's verify the nested array
+ */
+ $diff = self::arrayDiffRecursive($value, $array2[$key], $valuesOnly);
+ }
+
+ if (empty($diff)) {
+ continue;
+ }
+
+ $effect[$key] = $diff;
+ } else {
+ /*
+ * Value is different than in 2nd array?
+ * OKay, I've got difference
+ */
+ if ($value != $array2[$key]) {
+ $effect[$key] = $value;
+ }
+ }
+ } else {
+ /*
+ * OKay, I've got difference
+ */
+ $effect[$key] = $value;
+ }
+ }
+ }
+
+ return $effect;
+ }
+
+ /**
+ * Returns an index / key of given element in given array
+ *
+ * @param array $array The array to verify
+ * @param mixed $element The element who index / key is needed
+ * @return bool|null|mixed
+ */
+ public static function getIndexOf(array $array, $element)
+ {
+ /*
+ * No elements?
+ * Nothing to do
+ */
+ if (empty($array)) {
+ return false;
+ }
+
+ foreach ($array as $index => $value) {
+ if ($value === $element) {
+ return $index;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns an array with incremented indexes / keys
+ *
+ * @param array $array The array which indexes / keys should be incremented
+ * @param int|null $startIndex (optional) Index from which incrementation should be started. If not provided,
+ * the first index / key will be used.
+ * @param int $incrementStep (optional) Value used for incrementation. The step of incrementation.
+ * @return array
+ */
+ public static function incrementIndexes(array $array, $startIndex = null, $incrementStep = 1)
+ {
+ if (!empty($array)) {
+ $valuesToIncrement = [];
+
+ /*
+ * Start index not provided?
+ * Let's look for the first index / key of given array
+ */
+ if (null === $startIndex) {
+ $startIndex = self::getFirstKey($array);
+ }
+
+ /*
+ * Is the start index a numeric value?
+ * Other indexes / keys cannot be incremented
+ */
+ if (is_numeric($startIndex)) {
+ /*
+ * 1st step:
+ * Get values which indexes should be incremented and remove those values from given array
+ */
+ foreach ($array as $index => $value) {
+ if ($index < $startIndex) {
+ continue;
+ }
+
+ $valuesToIncrement[$index] = $value;
+ unset($array[$index]);
+ }
+
+ /*
+ * 2nd step:
+ * Increment indexes of gathered values
+ */
+ if (!empty($valuesToIncrement)) {
+ foreach ($valuesToIncrement as $oldIndex => $value) {
+ $newIndex = $oldIndex + $incrementStep;
+ $array[$newIndex] = $value;
+ }
+ }
+ }
+ }
+
+ return $array;
+ }
+
+ /**
+ * Returns next element of given array related to given element
+ *
+ * @param array $array The array with elements
+ * @param mixed $element Element for who next element should be returned
+ * @return null|mixed
+ */
+ public static function getNextElement(array $array, $element)
+ {
+ return self::getNeighbour($array, $element);
+ }
+
+ /**
+ * Returns previous element of given array related to given element
+ *
+ * @param array $array The array with elements
+ * @param mixed $element Element for who previous element should be returned
+ * @return null|mixed
+ */
+ public static function getPreviousElement(array $array, $element)
+ {
+ return self::getNeighbour($array, $element, false);
+ }
+
+ /**
+ * Returns information if given array is a multi dimensional array
+ *
+ * @param array $array The array to verify
+ * @return bool|null
+ */
+ public static function isMultiDimensional(array $array)
+ {
+ /*
+ * No elements?
+ * Nothing to do
+ */
+ if (empty($array)) {
+ return null;
+ }
+
+ return count($array) !== count($array, COUNT_RECURSIVE);
+ }
+
+ /**
+ * Returns count of dimensions, maximum nesting level actually, in given array
+ *
+ * @param array $array The array to verify
+ * @return int
+ */
+ public static function getDimensionsCount(array $array)
+ {
+ $dimensionsCount = 1;
+
+ foreach ($array as $value) {
+ if (is_array($value)) {
+ /*
+ * I have to increment returned value, because that means we've got 1 level more (if the value is an
+ * array)
+ */
+ $count = self::getDimensionsCount($value) + 1;
+
+ if ($count > $dimensionsCount) {
+ $dimensionsCount = $count;
+ }
+ }
+ }
+
+ return $dimensionsCount;
+ }
+
+ /**
+ * Returns neighbour (next or previous element) for given element
+ *
+ * @param array $array The array with elements
+ * @param mixed $element Element for who next element should be returned
+ * @param bool $next (optional) If is set to true, returns next neighbour. Otherwise - previous.
+ * @return mixed|null
+ */
+ private static function getNeighbour(array $array, $element, $next = true)
+ {
+ $noNext = $next && self::isLastElement($array, $element);
+ $noPrevious = !$next && self::isFirstElement($array, $element);
+
+ /*
+ * No elements?
+ * OR
+ * Given element does not exist in given array?
+ * OR
+ * Next neighbour should be returned and given element is last?
+ * OR
+ * Previous neighbour should be returned and given element is first?
+ *
+ * Nothing to do
+ */
+ if (empty($array) || !in_array($element, $array) || $noNext || $noPrevious) {
+ return null;
+ }
+
+ $neighbourKey = null;
+ $keys = array_keys($array);
+ $elementKey = self::getIndexOf($array, $element);
+ $indexOfKey = self::getIndexOf($keys, $elementKey);
+
+ /*
+ * Index of element or of element's key is unknown?
+ * Probably the element does not exist in given array, so... nothing to do
+ */
+ if (null === $elementKey || null === $indexOfKey) {
+ return null;
+ }
+
+ /*
+ * Looking for key of the neighbour (next or previous element)
+ */
+ if ($next) {
+ ++$indexOfKey;
+ } else {
+ --$indexOfKey;
+ }
+
+ /*
+ * Let's prepare key of the neighbour and...
+ * ...we've got the neighbour :)
+ */
+ $neighbourKey = $keys[$indexOfKey];
+
+ return $array[$neighbourKey];
+ }
+}
diff --git a/src/Common/Utilities/Date.php b/src/Common/Utilities/Date.php
new file mode 100644
index 0000000..8964691
--- /dev/null
+++ b/src/Common/Utilities/Date.php
@@ -0,0 +1,714 @@
+
+ * @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;
+ }
+}
diff --git a/src/Common/Utilities/DatePeriod.php b/src/Common/Utilities/DatePeriod.php
new file mode 100644
index 0000000..3a87d73
--- /dev/null
+++ b/src/Common/Utilities/DatePeriod.php
@@ -0,0 +1,195 @@
+
+ * @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;
+ }
+}
diff --git a/src/Common/Utilities/Miscellaneous.php b/src/Common/Utilities/Miscellaneous.php
new file mode 100644
index 0000000..b7e5011
--- /dev/null
+++ b/src/Common/Utilities/Miscellaneous.php
@@ -0,0 +1,1511 @@
+
+ * @copyright Meritoo.pl
+ */
+class Miscellaneous
+{
+ /**
+ * Returns directory's content (names of directories and files)
+ *
+ * @param string $directoryPath Path of directory who content should be returned
+ * @param bool $recursive (optional) If is set to true, sub-directories are also searched for content.
+ * Otherwise - only content of given directory is returned.
+ * @param int $maxFilesCount (optional) Maximum files that will be returned. If it's null, all files are
+ * returned.
+ * @return array|null
+ */
+ public static function getDirectoryContent($directoryPath, $recursive = false, $maxFilesCount = null)
+ {
+ /*
+ * Path of directory is unknown or does not exist and is not readable?
+ * Nothing to do
+ */
+ if (empty($directoryPath) || !is_readable($directoryPath)) {
+ return null;
+ }
+
+ $files = [];
+ $startFileName = '';
+
+ if (self::isFilePath($directoryPath)) {
+ $startDirectoryPath = dirname($directoryPath);
+ $startFileName = str_replace($startDirectoryPath, '', $directoryPath);
+
+ $directoryPath = $startDirectoryPath;
+ }
+
+ $count = 0;
+ $startFileFound = false;
+
+ if (!Regex::endsWith($directoryPath, '/')) {
+ $directoryPath .= '/';
+ }
+
+ if (Regex::startsWith($startFileName, '/')) {
+ $startFileName = mb_substr($startFileName, 1);
+ }
+
+ $directoryContent = scandir($directoryPath);
+
+ if (!empty($directoryContent)) {
+ foreach ($directoryContent as $fileName) {
+ if ('.' != $fileName && '..' != $fileName) {
+ $content = null;
+
+ if (!empty($startFileName) && !$startFileFound) {
+ if ($fileName == $startFileName) {
+ $startFileFound = true;
+ }
+
+ continue;
+ }
+
+ if ($recursive && is_dir($directoryPath . $fileName)) {
+ $content = self::getDirectoryContent($directoryPath . $fileName, true, $maxFilesCount - $count);
+ }
+
+ if (null !== $content) {
+ $files[$fileName] = $content;
+
+ if (!empty($maxFilesCount)) {
+ $count += Arrays::getNonArrayElementsCount($content);
+ }
+ } else {
+ $files[] = $fileName;
+
+ if (!empty($maxFilesCount)) {
+ ++$count;
+ }
+ }
+
+ if (!empty($maxFilesCount) && $count >= $maxFilesCount) {
+ break;
+ }
+ }
+ }
+ }
+
+ return $files;
+ }
+
+ /**
+ * Returns information if given path it's a file's path, if the path contains file name
+ *
+ * @param string $path The path to check
+ * @return bool
+ */
+ public static function isFilePath($path)
+ {
+ $info = pathinfo($path);
+
+ return isset($info['extension']) && !empty($info['extension']);
+ }
+
+ /**
+ * Converts checkbox value to boolean
+ *
+ * @param string $checkboxValue Checkbox value
+ * @return bool
+ */
+ public static function checkboxValue2Boolean($checkboxValue)
+ {
+ $mapping = [
+ 'on' => true,
+ 'off' => false,
+ ];
+
+ $clearValue = strtolower(trim($checkboxValue));
+
+ if (isset($mapping[$clearValue])) {
+ return $mapping[$clearValue];
+ }
+
+ return false;
+ }
+
+ /**
+ * Converts checkbox value to integer
+ *
+ * @param string $checkboxValue Checkbox value
+ * @return int
+ */
+ public static function checkboxValue2Integer($checkboxValue)
+ {
+ return (int)self::checkboxValue2Boolean($checkboxValue);
+ }
+
+ /**
+ * Returns name of file with given extension after verification if it contains the extension
+ *
+ * @param string $fileName The file name to verify
+ * @param string $extension The extension to verify and include
+ * @return string
+ */
+ public static function includeFileExtension($fileName, $extension)
+ {
+ if (self::getFileExtension($fileName, true) != strtolower($extension)) {
+ return sprintf('%s.%s', $fileName, $extension);
+ }
+
+ return $fileName;
+ }
+
+ /**
+ * Returns file extension
+ *
+ * @param string $fileName File name
+ * @param bool $asLowerCase (optional) if true extension is returned as lowercase string
+ * @return string
+ */
+ public static function getFileExtension($fileName, $asLowerCase = false)
+ {
+ $extension = '';
+ $matches = [];
+
+ if (preg_match('|(.+)\.(.+)|', $fileName, $matches)) {
+ $extension = end($matches);
+ }
+
+ if ($asLowerCase) {
+ return strtolower($extension);
+ }
+
+ return $extension;
+ }
+
+ /**
+ * Returns file name from given path
+ *
+ * @param string $path A path that contains file name
+ * @return string
+ */
+ public static function getFileNameFromPath($path)
+ {
+ $matches = [];
+ $pattern = sprintf('|([^\%s.]+\.[A-Za-z0-9.]+)$|', DIRECTORY_SEPARATOR);
+
+ if ((bool)preg_match($pattern, $path, $matches)) {
+ return $matches[1];
+ }
+
+ return '';
+ }
+
+ /**
+ * Returns unique name for file based on given original name
+ *
+ * @param string $originalFileName Original name of the file
+ * @param int $objectId (optional) Object ID, the ID of database's row. May be included into the
+ * generated / unique name.
+ * @return string
+ */
+ public static function getUniqueFileName($originalFileName, $objectId = 0)
+ {
+ /*
+ * Get parts of the file name:
+ * - without extension
+ * - and... the extension
+ */
+ $withoutExtension = self::getFileNameWithoutExtension($originalFileName);
+ $extension = self::getFileExtension($originalFileName, true);
+
+ /*
+ * Let's clear name of file
+ *
+ * Attention. The name without extension may be cleared / urlized only
+ * to avoid incorrect name by replacing "." with "-".
+ */
+ $withoutExtension = Urlizer::urlize($withoutExtension);
+
+ /*
+ * Now I have to complete the template used to build / generate unique name
+ */
+ $template = '%s-%s'; // file's name and unique key
+
+ if ($objectId > 0) {
+ $template .= '-%s'; // object ID
+ }
+
+ $template .= '.%s'; // file's extension
+
+ /*
+ * Add some uniqueness
+ */
+ $unique = uniqid(mt_rand(), true);
+
+ /*
+ * Finally build and return the unique name
+ */
+ if ($objectId > 0) {
+ return sprintf($template, $withoutExtension, $unique, $objectId, $extension);
+ }
+
+ return sprintf($template, $withoutExtension, $unique, $extension);
+ }
+
+ /**
+ * Returns file name without extension
+ *
+ * @param string $fileName The file name
+ * @return string
+ */
+ public static function getFileNameWithoutExtension($fileName)
+ {
+ $matches = [];
+
+ if (is_string($fileName) && (bool)preg_match('|(.+)\.(.+)|', $fileName, $matches)) {
+ return $matches[1];
+ }
+
+ return '';
+ }
+
+ /**
+ * Converts value to non-negative integer (element of the set {0, 1, 2, 3, ...})
+ *
+ * @param mixed $value Value to convert
+ * @param int $negativeReplacement (optional) Replacement for negative value
+ * @return int
+ */
+ public static function value2NonNegativeInteger($value, $negativeReplacement = 0)
+ {
+ $effect = (int)$value;
+
+ if ($effect < 0) {
+ return $negativeReplacement;
+ }
+
+ return $effect;
+ }
+
+ /**
+ * Displays variable content as preformatted text (fixed-width font and preserves both spaces and line breaks)
+ *
+ * If xdebug php module is loaded, displays variable using var_dump(), otherwise
var_dump()
.
+ * You can pass as many variables as you wish.
+ *
+ * Pass each variable as argument of this function. Amount unlimited. Variables are loaded using the
+ * func_get_args() function (@see http://pl1.php.net/manual/en/function.func-get-args.php).
+ */
+ public static function variableDump()
+ {
+ $xdebugLoaded = self::isPhpModuleLoaded('xdebug');
+
+ if (!$xdebugLoaded) {
+ echo '';
+ }
+
+ $arguments = func_get_args();
+
+ foreach ($arguments as $argument) {
+ var_dump($argument);
+ }
+
+ if (!$xdebugLoaded) {
+ echo '';
+ }
+ }
+
+ /**
+ * Returns information if given PHP module is compiled and loaded
+ *
+ * @param string $phpModuleName PHP module name
+ * @return bool
+ */
+ public static function isPhpModuleLoaded($phpModuleName)
+ {
+ $phpModulesArray = get_loaded_extensions();
+
+ return in_array($phpModuleName, $phpModulesArray);
+ }
+
+ /**
+ * Converts given string characters to latin characters
+ *
+ * @param string $string String to convert
+ * @param bool $lowerCaseHuman (optional) If is set to true, converted string is returned as lowercase and
+ * human-readable. Otherwise - as original.
+ * @param string $replacementChar (optional) Replacement character for all non-latin characters and uppercase
+ * letters, if 2nd argument is set to true
+ * @return string
+ */
+ public static function toLatin($string, $lowerCaseHuman = true, $replacementChar = '-')
+ {
+ if (is_string($string)) {
+ $string = trim($string);
+ }
+
+ /*
+ * Empty value?
+ * Nothing to do
+ */
+ if (empty($string)) {
+ return '';
+ }
+
+ $converter = Transliterator::create('Latin-ASCII;');
+
+ /*
+ * Oops, cannot instantiate converter
+ * Nothing to do
+ */
+ if (null === $converter) {
+ return '';
+ }
+
+ $converted = $converter->transliterate($string);
+
+ /*
+ * Make the string lowercase and human-readable
+ */
+ if ($lowerCaseHuman) {
+ $matches = [];
+ $matchCount = preg_match_all('|[A-Z]{1}[^A-Z]*|', $converted, $matches);
+
+ if ($matchCount > 0) {
+ $parts = $matches[0];
+ $converted = mb_strtolower(implode($replacementChar, $parts));
+ }
+ }
+
+ /*
+ * Let's replace special characters to spaces
+ * ...and finally spaces to $replacementChar
+ */
+ $replaced = preg_replace('|[^a-zA-Z0-9]|', ' ', $converted);
+
+ return preg_replace('| +|', $replacementChar, trim($replaced));
+ }
+
+ /**
+ * Returns unique string
+ *
+ * @param string $prefix (optional) Prefix of the unique string. May be used while generating the unique
+ * string simultaneously on several hosts at the same microsecond.
+ * @param bool $hashed (optional) If is set to true, the unique string is hashed additionally. Otherwise - not.
+ * @return string
+ */
+ public static function getUniqueString($prefix = '', $hashed = false)
+ {
+ $unique = uniqid($prefix, true);
+
+ if ($hashed) {
+ return sha1($unique);
+ }
+
+ return $unique;
+ }
+
+ /**
+ * Replaces part of string with other string or strings.
+ * There is a few combination of what should be searched and with what it should be replaced.
+ *
+ * @param string|array $subject The string or an array of strings to search and replace
+ * @param string|array $search String or pattern or array of patterns to find. It may be: string, an array
+ * of strings or an array of patterns.
+ * @param string|array $replacement The string or an array of strings to replace. It may be: string or an array
+ * of strings.
+ * @param bool $quoteStrings (optional) If is set to true, strings are surrounded with single quote sign
+ * @return string
+ *
+ * Example:
+ * a) an array of strings to search
+ * $subject = [
+ * 'Lorem ipsum dolor sit amet.',
+ * 'Etiam ullamcorper. Suspendisse a pellentesque dui, non felis.',
+ * ];
+ *
+ * b) an array of patterns
+ * $search = [
+ * '|ipsum|',
+ * '|pellentesque|',
+ * ];
+ *
+ * c) an array of strings to replace
+ * $replacement = [
+ * 'commodo',
+ * 'interdum',
+ * ];
+ *
+ * The result:
+ * [
+ * 'Lorem commodo dolor sit amet.',
+ * 'Etiam ullamcorper. Suspendisse a interdum dui, non felis.',
+ * ];
+ */
+ public static function replace($subject, $search, $replacement, $quoteStrings = false)
+ {
+ $effect = $subject;
+
+ $searchIsString = is_string($search);
+ $searchIsArray = is_array($search);
+
+ /*
+ * Value to find is neither a string nor an array OR it's an empty string?
+ * Nothing to do
+ */
+ if ((!$searchIsString && !$searchIsArray) || ($searchIsString && 0 == strlen($search))) {
+ return $effect;
+ }
+
+ $replacementIsString = is_string($replacement);
+ $replacementIsArray = is_array($replacement);
+
+ $bothAreStrings = $searchIsString && $replacementIsString;
+ $bothAreArrays = $searchIsArray && $replacementIsArray;
+
+ /*
+ * First step: replace strings, simple operation with strings
+ */
+ if ($searchIsString && $replacementIsString) {
+ if ($quoteStrings) {
+ $replacement = '\'' . $replacement . '\'';
+ }
+
+ $effect = str_replace($search, $replacement, $subject);
+ }
+
+ /*
+ * Second step: replace with regular expressions.
+ * Attention. Searched and replacement value should be the same type: strings or arrays.
+ */
+ if ($effect == $subject && ($bothAreStrings || $bothAreArrays)) {
+ if ($quoteStrings && $replacementIsString) {
+ $replacement = '\'' . $replacement . '\'';
+ }
+
+ /*
+ * I have to avoid string that contains spaces only, e.g. " ".
+ * It's required to avoid bug: preg_replace(): Empty regular expression.
+ */
+ $search = trim($search);
+
+ if ($searchIsArray || ($searchIsString && !empty($search))) {
+ $effect = preg_replace($search, $replacement, $subject);
+ }
+ }
+
+ /*
+ * Third step: complex replace of the replacement defined as an array.
+ * It may be useful when you want to search for a one string and replace the string with multiple values.
+ */
+ if ($effect == $subject && $searchIsString && $replacementIsArray) {
+ $subjectIsArray = is_array($subject);
+ $effect = '';
+
+ if ($subjectIsArray) {
+ $effect = [];
+ }
+
+ /*
+ * I have to make the subject an array...
+ */
+ $subject = Arrays::makeArray($subject);
+
+ /*
+ * ...and use iterate through the subjects,
+ * because explode() function expects strings as both arguments (1st and 2nd)
+ */
+ foreach ($subject as $subSubject) {
+ $subEffect = '';
+
+ $exploded = explode($search, $subSubject);
+ $explodedCount = count($exploded);
+
+ if ($quoteStrings) {
+ foreach ($replacement as &$item) {
+ if (is_string($item)) {
+ $item = '\'' . $item . '\'';
+ }
+ }
+
+ unset($item);
+ }
+
+ foreach ($exploded as $key => $item) {
+ $subEffect .= $item;
+
+ /*
+ * The replacement shouldn't be included when the searched string was not found
+ */
+ if ($explodedCount > 1 && $key < $explodedCount - 1 && isset($replacement[$key])) {
+ $subEffect .= $replacement[$key];
+ }
+ }
+
+ if ($subjectIsArray) {
+ $effect[] = $subEffect;
+ continue;
+ }
+
+ $effect .= $subEffect;
+ }
+ }
+
+ return $effect;
+ }
+
+ /**
+ * Returns new file name after adding prefix or suffix (or both of them) to the name
+ *
+ * @param string $fileName The file name
+ * @param string $prefix File name prefix
+ * @param string $suffix File name suffix
+ * @return string
+ */
+ public static function getNewFileName($fileName, $prefix, $suffix)
+ {
+ $effect = $fileName;
+
+ if (!empty($fileName) && (!empty($prefix) || !empty($suffix))) {
+ $name = self::getFileNameWithoutExtension($fileName);
+ $extension = self::getFileExtension($fileName);
+
+ $effect = sprintf('%s%s%s.%s', $prefix, $name, $suffix, $extension);
+ }
+
+ return $effect;
+ }
+
+ /**
+ * Returns operating system name PHP is running on
+ *
+ * @return string
+ */
+ public static function getOperatingSystemNameServer()
+ {
+ return php_uname('s');
+ }
+
+ /**
+ * Returns part of string preserving words
+ *
+ * @param string $text The string / text
+ * @param int $maxLength Maximum length of given string
+ * @param string $suffix (optional) The suffix to add at the end of string
+ * @return string
+ */
+ public static function substringToWord($text, $maxLength, $suffix = '...')
+ {
+ $effect = $text;
+
+ $textLength = mb_strlen($text, 'utf-8');
+ $suffixLength = mb_strlen($suffix, 'utf-8');
+
+ $maxLength -= $suffixLength;
+
+ if ($textLength > $maxLength) {
+ $effect = mb_substr($text, 0, $maxLength, 'utf-8');
+ $lastSpacePosition = mb_strrpos($effect, ' ', 'utf-8');
+
+ if (false !== $lastSpacePosition) {
+ $effect = mb_substr($effect, 0, $lastSpacePosition, 'utf-8');
+ }
+
+ $effect .= $suffix;
+ }
+
+ return $effect;
+ }
+
+ /**
+ * Breaks long text
+ *
+ * @param string $text The text to check and break
+ * @param int $perLine (optional) Characters count per line
+ * @param string $separator (optional) Separator that is placed beetwen lines
+ * @param string $encoding (optional) Character encoding. Used by mb_substr().
+ * @param int $proportionalAberration (optional) Proportional aberration for chars (percent value)
+ * @return string
+ */
+ public static function breakLongText(
+ $text,
+ $perLine = 100,
+ $separator = '
',
+ $encoding = 'utf-8',
+ $proportionalAberration = 20
+ ) {
+ $effect = $text;
+ $textLength = mb_strlen($text);
+
+ if (!empty($text) && $textLength > $perLine) {
+ /*
+ * The html_entity_decode() function is used here, because while operating
+ * on string that contains only special characters the string is divided
+ * incorrectly, e.g. "<<<<<" -> "<<<<&
lt;".
+ */
+ //$text = htmlspecialchars_decode($text);
+ $text = html_entity_decode($text, ENT_QUOTES);
+
+ $effect = '';
+ $currentPosition = 0;
+
+ $charsAberration = ceil($perLine * ($proportionalAberration / 100));
+ $charsPerLineDefault = $perLine;
+
+ while ($currentPosition <= $textLength) {
+ $insertSeparator = false;
+
+ /*
+ * Looking for spaces before and after current position. It was done, because text wasn't
+ * broken properly and some words were breaked and placed into two lines.
+ */
+ if ($charsAberration > 0) {
+ $length = $perLine + $charsAberration;
+ $lineWithAberration = mb_substr($text, $currentPosition, $length, $encoding);
+
+ if (!Regex::contains($lineWithAberration, ' ')) {
+ $length = $perLine - $charsAberration;
+ $lineWithAberration = mb_substr($text, $currentPosition, $length, $encoding);
+ }
+
+ if (Regex::startsWith($lineWithAberration, ' ')) {
+ ++$currentPosition;
+ $lineWithAberration = ltrim($lineWithAberration);
+ }
+
+ $spacePosition = mb_strrpos($lineWithAberration, ' ', 0, $encoding);
+
+ if ($spacePosition > 0) {
+ $perLine = $spacePosition;
+ $insertSeparator = true;
+ }
+ }
+
+ $charsOneLine = mb_substr($text, $currentPosition, $perLine, $encoding);
+
+ /*
+ * The htmlspecialchars() function is used here, because...
+ * Reason and comment the same as above for html_entity_decode() function.
+ */
+
+ $effect .= htmlspecialchars($charsOneLine);
+ //$effect .= $charsOneLine;
+
+ $currentPosition += $perLine;
+ $oneLineContainsSpace = Regex::contains($charsOneLine, ' ');
+
+ if (($insertSeparator || !$oneLineContainsSpace) && $currentPosition <= $textLength) {
+ $effect .= $separator;
+ }
+
+ $perLine = $charsPerLineDefault;
+ }
+ }
+
+ return $effect;
+ }
+
+ /**
+ * Removes the directory.
+ * If not empty, removes also contents.
+ *
+ * @param string $directoryPath Directory path
+ * @param bool $contentOnly (optional) If is set to true, only content of the directory is removed, not
+ * directory. Otherwise - directory is removed too.
+ * @return bool
+ */
+ public static function removeDirectory($directoryPath, $contentOnly = false)
+ {
+ if (!file_exists($directoryPath)) {
+ return true;
+ }
+
+ if (!is_dir($directoryPath)) {
+ return unlink($directoryPath);
+ }
+
+ foreach (scandir($directoryPath) as $item) {
+ if ('.' == $item || '..' == $item) {
+ continue;
+ }
+
+ if (!self::removeDirectory($directoryPath . DIRECTORY_SEPARATOR . $item)) {
+ return false;
+ }
+ }
+
+ if (!$contentOnly) {
+ return rmdir($directoryPath);
+ }
+
+ return true;
+ }
+
+ /**
+ * Returns information if value is decimal
+ *
+ * @param mixed $value The value to check
+ * @return bool
+ */
+ public static function isDecimal($value)
+ {
+ return is_scalar($value) && floor($value) !== (float)$value;
+ }
+
+ /**
+ * Returns the string in camel case
+ *
+ * @param string $string The string to convert e.g. this-is-eXamplE (return: thisIsExample)
+ * @param string $separator (optional) Separator used to find parts of the string, e.g. '-' or ','
+ * @return string
+ */
+ public static function getCamelCase($string, $separator = ' ')
+ {
+ if (empty($string)) {
+ return '';
+ }
+
+ $effect = '';
+ $members = explode($separator, $string);
+
+ foreach ($members as $key => $value) {
+ $value = mb_strtolower($value);
+
+ if (0 == $key) {
+ $effect .= self::lowercaseFirst($value);
+ } else {
+ $effect .= self::uppercaseFirst($value);
+ }
+ }
+
+ return $effect;
+ }
+
+ /**
+ * Make a string's first character lowercase
+ *
+ * @param string $text The text to get first character lowercase
+ * @param bool|null $restLowercase (optional) Information that to do with rest of given string
+ * @return string
+ *
+ * Values of the $restLowercase argument:
+ * - null (default): nothing is done with the string
+ * - true: the rest of string is lowercased
+ * - false: the rest of string is uppercased
+ *
+ * Some explanation:
+ * Function lcfirst() is available for PHP >= 5.30, so I wrote my own function that lowercases first character of
+ * the string.
+ */
+ public static function lowercaseFirst($text, $restLowercase = null)
+ {
+ if (empty($text)) {
+ return '';
+ }
+
+ $effect = $text;
+
+ if ($restLowercase) {
+ $effect = mb_strtolower($effect);
+ } elseif (false === $restLowercase) {
+ $effect = mb_strtoupper($effect);
+ }
+
+ if (function_exists('lcfirst')) {
+ $effect = lcfirst($effect);
+ } else {
+ $first = mb_strtolower($effect[0]);
+ $rest = mb_substr($effect, 1);
+
+ $effect = $first . $rest;
+ }
+
+ return $effect;
+ }
+
+ /**
+ * Make a string's first character uppercase
+ *
+ * @param string $text The text to get uppercase
+ * @param bool|null $restLowercase (optional) Information that to do with rest of given string
+ * @return string
+ *
+ * Values of the $restLowercase argument:
+ * - null (default): nothing is done with the string
+ * - true: the rest of string is lowercased
+ * - false: the rest of string is uppercased
+ */
+ public static function uppercaseFirst($text, $restLowercase = null)
+ {
+ if (empty($text)) {
+ return '';
+ }
+
+ $effect = $text;
+
+ if ($restLowercase) {
+ $effect = mb_strtolower($effect);
+ } elseif (false === $restLowercase) {
+ $effect = mb_strtoupper($effect);
+ }
+
+ if (function_exists('ucfirst')) {
+ $effect = ucfirst($effect);
+ } else {
+ $first = mb_strtoupper($effect[0]);
+ $rest = mb_substr($effect, 1);
+
+ $effect = $first . $rest;
+ }
+
+ return $effect;
+ }
+
+ /**
+ * Quotes given value with apostrophes or quotation marks
+ *
+ * @param mixed $value The value to quote
+ * @param bool $useApostrophe (optional) If is set to true, apostrophes are used. Otherwise - quotation marks.
+ * @return string
+ */
+ public static function quoteValue($value, $useApostrophe = true)
+ {
+ if (is_string($value)) {
+ $quotes = '"';
+
+ if ($useApostrophe) {
+ $quotes = '\'';
+ }
+
+ $value = sprintf('%s%s%s', $quotes, $value, $quotes);
+ }
+
+ return $value;
+ }
+
+ /**
+ * Returns size (of file or directory) in human readable format
+ *
+ * @param int $sizeInBytes The size in bytes
+ * @return string
+ */
+ public static function getHumanReadableSize($sizeInBytes)
+ {
+ $units = [
+ 'B',
+ 'KB',
+ 'MB',
+ 'GB',
+ 'TB',
+ 'PB',
+ ];
+ $index = floor(log($sizeInBytes, 1024));
+
+ $size = round($sizeInBytes / pow(1024, $index), 2);
+ $unit = $units[(int)$index];
+
+ return sprintf('%s %s', $size, $unit);
+ }
+
+ /**
+ * Returns string without the last element.
+ * The string should contain given separator.
+ *
+ * @param string $string The string to check
+ * @param string $separator The separator which divides elements of string
+ * @return string
+ */
+ public static function getStringWithoutLastElement($string, $separator)
+ {
+ $elements = self::getStringElements($string, $separator);
+ $lastKey = Arrays::getLastKey($elements);
+
+ unset($elements[$lastKey]);
+
+ return implode($separator, $elements);
+ }
+
+ /**
+ * Returns elements of given string divided by given separator
+ *
+ * @param string $string The string to check
+ * @param string $separator The separator which divides elements of string
+ * @return array
+ */
+ public static function getStringElements($string, $separator)
+ {
+ $matches = [];
+ $pattern = sprintf('|[^\%s]+|', $separator);
+ $matchCount = preg_match_all($pattern, $string, $matches);
+
+ if ($matchCount > 1) {
+ return $matches[0];
+ }
+
+ return [];
+ }
+
+ /**
+ * Returns the last element of given string divided by given separator
+ *
+ * @param string $string The string to check
+ * @param string $separator The separator which divides elements of string
+ * @return string|null
+ */
+ public static function getLastElementOfString($string, $separator)
+ {
+ $elements = self::getStringElements($string, $separator);
+
+ /*
+ * No elements?
+ * Nothing to do
+ */
+ if (empty($elements)) {
+ return null;
+ }
+
+ $element = Arrays::getLastElement($elements);
+
+ return trim($element);
+ }
+
+ /**
+ * Returns smartly trimmed string.
+ * If the string is empty, contains only spaces, e.g. " ", nothing is done and the original string is returned.
+ *
+ * @param string $string The string to trim
+ * @return string
+ */
+ public static function trimSmart($string)
+ {
+ $trimmed = trim($string);
+
+ if (empty($trimmed)) {
+ return $string;
+ }
+
+ return $trimmed;
+ }
+
+ /**
+ * Returns concatenated given paths
+ *
+ * The paths may be passed as:
+ * - an array of paths / strings
+ * - strings passed as following arguments
+ *
+ * Examples:
+ * - concatenatePaths(['path/first', 'path/second', 'path/third']);
+ * - concatenatePaths('path/first', 'path/second', 'path/third');
+ *
+ * @param string|array $paths Paths co concatenate. As described above: an array of paths / strings or strings
+ * passed as following arguments.
+ * @return string
+ */
+ public static function concatenatePaths($paths)
+ {
+ /*
+ * If paths are not provided as array, get the paths from methods' arguments
+ */
+ if (!is_array($paths)) {
+ $paths = func_get_args();
+ }
+
+ /*
+ * No paths provided?
+ * Nothing to do
+ */
+ if (empty($paths)) {
+ return '';
+ }
+
+ /*
+ * Some useful variables
+ */
+ $concatenated = '';
+ $firstWindowsBased = false;
+ $separator = DIRECTORY_SEPARATOR;
+
+ foreach ($paths as $path) {
+ $path = trim($path);
+
+ /*
+ * Empty paths are useless
+ */
+ if (empty($path)) {
+ continue;
+ }
+
+ /*
+ * Does the first path is a Windows-based path?
+ */
+ if (Arrays::isFirstElement($paths, $path)) {
+ $firstWindowsBased = Regex::isWindowsBasedPath($path);
+
+ if ($firstWindowsBased) {
+ $separator = '\\';
+ }
+ }
+
+ /*
+ * Remove the starting / beginning directory's separator
+ */
+ $path = self::removeStartingDirectorySeparator($path, $separator);
+
+ /*
+ * Removes the ending directory's separator
+ */
+ $path = self::removeEndingDirectorySeparator($path, $separator);
+
+ /*
+ * If OS is Windows, first part of the concatenated path should be the first passed path,
+ * because in Windows paths starts with drive letter, e.g. "C:", and the directory separator is not
+ * necessary at the beginning.
+ */
+ if ($firstWindowsBased && empty($concatenated)) {
+ $concatenated = $path;
+ continue;
+ }
+
+ /*
+ * Concatenate the paths / strings with OS-related directory separator between them (slash or backslash)
+ */
+ $concatenated = sprintf('%s%s%s', $concatenated, $separator, $path);
+ }
+
+ return $concatenated;
+ }
+
+ /**
+ * Removes the starting / beginning directory's separator
+ *
+ * @param string $text Text 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), separator
+ * provided by operating system will be used.
+ * @return string
+ */
+ public static function removeStartingDirectorySeparator($text, $separator = '')
+ {
+ /*
+ * Not a string?
+ * Nothing to do
+ */
+ if (!is_string($text)) {
+ return '';
+ }
+
+ if (empty($separator)) {
+ $separator = DIRECTORY_SEPARATOR;
+ }
+
+ $effect = trim($text);
+
+ if (Regex::startsWithDirectorySeparator($effect, $separator)) {
+ $effect = mb_substr($effect, mb_strlen($separator));
+ }
+
+ return $effect;
+ }
+
+ /**
+ * Removes the ending directory's separator
+ *
+ * @param string $text Text 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 removeEndingDirectorySeparator($text, $separator = '')
+ {
+ /*
+ * Not a string?
+ * Nothing to do
+ */
+ if (!is_string($text)) {
+ return '';
+ }
+
+ if (empty($separator)) {
+ $separator = DIRECTORY_SEPARATOR;
+ }
+
+ $effect = trim($text);
+
+ if (Regex::endsWithDirectorySeparator($effect, $separator)) {
+ $effect = mb_substr($effect, 0, mb_strlen($effect) - mb_strlen($separator));
+ }
+
+ return $effect;
+ }
+
+ /**
+ * Returns safely value of global variable, found in one of the global arrays / variables, e.g. $_GET
+ *
+ * @param int $globalSourceType Represents the global array / variable. One of constants: INPUT_GET, INPUT_POST,
+ * INPUT_COOKIE, INPUT_SERVER, or INPUT_ENV.
+ * @param string $variableName Name of the variable to return value
+ * @return mixed
+ */
+ public static function getSafelyGlobalVariable($globalSourceType, $variableName)
+ {
+ $value = filter_input($globalSourceType, $variableName);
+
+ if (null === $value) {
+ $globalSource = null;
+
+ switch ($globalSourceType) {
+ case INPUT_GET:
+ $globalSource = $_GET;
+ break;
+
+ case INPUT_POST:
+ $globalSource = $_POST;
+ break;
+
+ case INPUT_COOKIE:
+ $globalSource = $_COOKIE;
+ break;
+
+ case INPUT_SERVER:
+ $globalSource = $_SERVER;
+ break;
+
+ case INPUT_ENV:
+ $globalSource = $_ENV;
+ break;
+ }
+
+ if (null !== $globalSource && isset($globalSource[$variableName])) {
+ $value = $globalSource[$variableName];
+
+ if (!ini_get('magic_quotes_gpc')) {
+ $value = addslashes($value);
+ }
+ }
+ }
+
+ return $value;
+ }
+
+ /**
+ * Returns a CURL response with parsed HTTP headers as array with "headers", "cookies" and "content" keys
+ *
+ * The headers and cookies are parsed and returned as an array, and an array of Cookie objects. Returned array looks
+ * like this example:
+ *
+ * [
+ * 'headers' => [
+ * 'Content-Type' => 'text/html; charset=UTF-8',
+ * ...
+ * ],
+ * 'cookies' => [
+ * new Symfony\Component\HttpFoundation\Cookie(),
+ * new Symfony\Component\HttpFoundation\Cookie(),
+ * ...
+ * ],
+ * 'content' => '...'
+ * ]
+ *
+ *
+ * If you want to attach HTTP headers into response content by CURL you need to set "CURLOPT_HEADER" option
+ * to "true". To read exact length of HTTP headers from CURL you can use "curl_getinfo()" function
+ * and read "CURLINFO_HEADER_SIZE" option.
+ *
+ * @param string $response the full content of response, including HTTP headers
+ * @param int $headerSize The length of HTTP headers in content
+ * @return array
+ */
+ public static function getCurlResponseWithHeaders($response, $headerSize)
+ {
+ $headerContent = mb_substr($response, 0, $headerSize);
+ $content = mb_substr($response, $headerSize);
+ $headers = [];
+ $cookies = [];
+
+ /*
+ * Let's transform headers content into two arrays: headers and cookies
+ */
+ foreach (explode("\r\n", $headerContent) as $i => $line) {
+ /*
+ * First line is only HTTP status and is unneeded so skip it
+ */
+ if (0 === $i) {
+ continue;
+ }
+
+ if (Regex::contains($line, ':')) {
+ list($key, $value) = explode(': ', $line);
+
+ /*
+ * If the header is a "set-cookie" let's save it to "cookies" array
+ */
+ if ('Set-Cookie' === $key) {
+ $cookieParameters = explode(';', $value);
+
+ $name = '';
+ $value = '';
+ $expire = 0;
+ $path = '/';
+ $domain = null;
+ $secure = false;
+ $httpOnly = true;
+
+ foreach ($cookieParameters as $j => $parameter) {
+ $param = explode('=', $parameter);
+
+ /*
+ * First parameter will be always a cookie name and it's value. It is not needed to run
+ * further actions for them, so save the values and move to next parameter.
+ */
+ if (0 === $j) {
+ $name = trim($param[0]);
+ $value = trim($param[1]);
+ continue;
+ }
+
+ /*
+ * Now there would be the rest of cookie parameters, names of params are sent different way so
+ * I need to lowercase the names and remove unneeded spaces.
+ */
+ $paramName = mb_strtolower(trim($param[0]));
+ $paramValue = true;
+
+ /*
+ * Some parameters don't have value e.g. "secure", but the value for them if they're specified
+ * is "true". Otherwise - just read a value for parameter if exists.
+ */
+ if (array_key_exists(1, $param)) {
+ $paramValue = trim($param[1]);
+ }
+
+ switch ($paramName) {
+ case 'expires':
+ $expire = $paramValue;
+ break;
+ case 'path':
+ $path = $paramValue;
+ break;
+ case 'domain':
+ $domain = $paramValue;
+ break;
+ case 'secure':
+ $secure = $paramValue;
+ break;
+ case 'httponly':
+ $httpOnly = $paramValue;
+ break;
+ }
+ }
+
+ /*
+ * Create new Cookie object and add it to "cookies" array.
+ * I must skip to next header as cookies shouldn't be saved in "headers" array.
+ */
+ $cookies[] = new Cookie($name, $value, $expire, $path, $domain, $secure, $httpOnly);
+ continue;
+ }
+
+ /*
+ * Save response header which is not a cookie
+ */
+ $headers[$key] = $value;
+ }
+ }
+
+ return [
+ 'headers' => $headers,
+ 'cookies' => $cookies,
+ 'content' => $content,
+ ];
+ }
+
+ /**
+ * Adds missing the "0" characters to given number until given length is reached
+ *
+ * Example:
+ * - number: 201
+ * - length: 6
+ * - will be returned: 000201
+ *
+ * If "before" parameter is false, zeros will be inserted after given number. If given number is longer than
+ * given length the number will be returned as it was given to the method.
+ *
+ * @param mixed $number Number for who the "0" characters should be inserted
+ * @param int $length Wanted length of final number
+ * @param bool $before (optional) If false, 0 characters will be inserted after given number
+ * @return string
+ */
+ public static function fillMissingZeros($number, $length, $before = true)
+ {
+ /*
+ * It's not a number? Empty string is not a number too.
+ * Nothing to do
+ */
+ if (!is_numeric($number)) {
+ return '';
+ }
+
+ $text = trim($number);
+ $textLength = mb_strlen($text);
+
+ if ($length <= $textLength) {
+ return $text;
+ }
+
+ for ($i = ($length - $textLength); 0 < $i; --$i) {
+ if ($before) {
+ $text = '0' . $text;
+ continue;
+ }
+
+ $text = $text . '0';
+ }
+
+ return $text;
+ }
+
+ /**
+ * Returns information if given value is located in interval between given utmost left and right values
+ *
+ * @param int|float $value Value to verify
+ * @param int|float $left Left utmost value of interval
+ * @param int|float $right Right utmost value of interval
+ * @return bool
+ */
+ public static function isBetween($value, $left, $right)
+ {
+ return $value > $left && $value < $right;
+ }
+
+ /**
+ * Returns type of given variable.
+ * If it's an object, full class name is returned.
+ *
+ * @param mixed $variable Variable who type should be returned
+ * @return string
+ */
+ public static function getType($variable)
+ {
+ if (is_object($variable)) {
+ return Reflection::getClassName($variable);
+ }
+
+ return gettype($variable);
+ }
+
+ /**
+ * Returns valid value of color's component (e.g. red).
+ * If given value is greater than 0, returns the value. Otherwise - 0.
+ *
+ * @param int $colorComponent Color's component to verify. Decimal value, e.g. 255.
+ * @param bool $asHexadecimal (optional) If is set to true, hexadecimal value is returned (default behaviour).
+ * Otherwise - decimal.
+ * @return int|string
+ */
+ public static function getValidColorComponent($colorComponent, $asHexadecimal = true)
+ {
+ $colorComponent = (int)$colorComponent;
+
+ if ($colorComponent < 0 || $colorComponent > 255) {
+ $colorComponent = 0;
+ }
+
+ if ($asHexadecimal) {
+ $hexadecimal = dechex($colorComponent);
+
+ if (1 == strlen($hexadecimal)) {
+ return sprintf('0%s', $hexadecimal, $hexadecimal);
+ }
+
+ return $hexadecimal;
+ }
+
+ return $colorComponent;
+ }
+
+ /**
+ * Returns inverted value of color for given color
+ *
+ * @param string $color Hexadecimal value of color to invert (with or without hash), e.g. "dd244c" or "#22a5fe"
+ * @return string
+ */
+ public static function getInvertedColor($color)
+ {
+ /*
+ * Prepare the color for later usage
+ */
+ $color = trim($color);
+ $withHash = Regex::startsWith($color, '#');
+
+ /*
+ * Verify and get valid value of color.
+ * An exception will be thrown if the value is not a color.
+ */
+ $color = Regex::getValidColorHexValue($color);
+
+ /*
+ * Grab color's components
+ */
+ $red = hexdec(substr($color, 0, 2));
+ $green = hexdec(substr($color, 2, 2));
+ $blue = hexdec(substr($color, 4, 2));
+
+ /*
+ * Calculate inverted color's components
+ */
+ $redInverted = self::getValidColorComponent(255 - $red);
+ $greenInverted = self::getValidColorComponent(255 - $green);
+ $blueInverted = self::getValidColorComponent(255 - $blue);
+
+ /*
+ * Voila, here is the inverted color
+ */
+ $invertedColor = sprintf('%s%s%s', $redInverted, $greenInverted, $blueInverted);
+
+ if ($withHash) {
+ return sprintf('#%s', $invertedColor);
+ }
+
+ return $invertedColor;
+ }
+
+ /**
+ * Returns project's root path.
+ * Looks for directory that contains composer.json.
+ *
+ * @return string
+ */
+ public static function getProjectRootPath()
+ {
+ $projectRootPath = '';
+
+ $fileName = 'composer.json';
+ $directoryPath = __DIR__;
+
+ /*
+ * Path of directory it's not the path of last directory?
+ */
+ while (DIRECTORY_SEPARATOR !== $directoryPath) {
+ $filePath = static::concatenatePaths($directoryPath, $fileName);
+
+ /*
+ * Is here file we are looking for?
+ * Maybe it's a project's root path
+ */
+ if (file_exists($filePath)) {
+ $projectRootPath = $directoryPath;
+ }
+
+ $directoryPath = dirname($directoryPath);
+ }
+
+ return $projectRootPath;
+ }
+}
diff --git a/src/Common/Utilities/Reflection.php b/src/Common/Utilities/Reflection.php
new file mode 100644
index 0000000..4e94900
--- /dev/null
+++ b/src/Common/Utilities/Reflection.php
@@ -0,0 +1,668 @@
+
+ * @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
+ * 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();
+ }
+}
diff --git a/src/Common/Utilities/Regex.php b/src/Common/Utilities/Regex.php
new file mode 100644
index 0000000..85cf1c0
--- /dev/null
+++ b/src/Common/Utilities/Regex.php
@@ -0,0 +1,726 @@
+
+ * @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);
+ }
+}
diff --git a/src/Base/Result/BaseItem.php b/src/LimeSurvey/Base/Result/BaseItem.php
similarity index 95%
rename from src/Base/Result/BaseItem.php
rename to src/LimeSurvey/Base/Result/BaseItem.php
index 638e89b..02b57cb 100644
--- a/src/Base/Result/BaseItem.php
+++ b/src/LimeSurvey/Base/Result/BaseItem.php
@@ -16,6 +16,8 @@ namespace Meritoo\LimeSurvey\ApiClient\Base\Result;
*/
abstract class BaseItem
{
+ const className = 'Meritoo\LimeSurvey\ApiClient\Base\Result\BaseItem';
+
/**
* Class constructor
*
diff --git a/src/Client/Client.php b/src/LimeSurvey/Client/Client.php
similarity index 98%
rename from src/Client/Client.php
rename to src/LimeSurvey/Client/Client.php
index 0c33fde..c0d9faa 100644
--- a/src/Client/Client.php
+++ b/src/LimeSurvey/Client/Client.php
@@ -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
*
diff --git a/src/Configuration/ConnectionConfiguration.php b/src/LimeSurvey/Configuration/ConnectionConfiguration.php
similarity index 98%
rename from src/Configuration/ConnectionConfiguration.php
rename to src/LimeSurvey/Configuration/ConnectionConfiguration.php
index 0faa62e..ba9afe5 100644
--- a/src/Configuration/ConnectionConfiguration.php
+++ b/src/LimeSurvey/Configuration/ConnectionConfiguration.php
@@ -19,6 +19,8 @@ use Meritoo\Common\Utilities\Regex;
*/
class ConnectionConfiguration
{
+ const className = 'Meritoo\LimeSurvey\ApiClient\Configuration\ConnectionConfiguration';
+
/**
* Base url.
* Protocol & domain.
diff --git a/src/Exception/CannotProcessDataException.php b/src/LimeSurvey/Exception/CannotProcessDataException.php
similarity index 93%
rename from src/Exception/CannotProcessDataException.php
rename to src/LimeSurvey/Exception/CannotProcessDataException.php
index 3cc6980..2c03579 100644
--- a/src/Exception/CannotProcessDataException.php
+++ b/src/LimeSurvey/Exception/CannotProcessDataException.php
@@ -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"
*
diff --git a/src/Exception/CreateSessionKeyFailedException.php b/src/LimeSurvey/Exception/CreateSessionKeyFailedException.php
similarity index 90%
rename from src/Exception/CreateSessionKeyFailedException.php
rename to src/LimeSurvey/Exception/CreateSessionKeyFailedException.php
index e326b72..0fa92a5 100644
--- a/src/Exception/CreateSessionKeyFailedException.php
+++ b/src/LimeSurvey/Exception/CreateSessionKeyFailedException.php
@@ -18,6 +18,8 @@ use Exception;
*/
class CreateSessionKeyFailedException extends Exception
{
+ const className = 'Meritoo\LimeSurvey\ApiClient\Exception\CreateSessionKeyFailedException';
+
/**
* Class constructor
*
diff --git a/src/Exception/IncorrectClassOfResultItemException.php b/src/LimeSurvey/Exception/IncorrectClassOfResultItemException.php
similarity index 90%
rename from src/Exception/IncorrectClassOfResultItemException.php
rename to src/LimeSurvey/Exception/IncorrectClassOfResultItemException.php
index 0851d10..3146329 100644
--- a/src/Exception/IncorrectClassOfResultItemException.php
+++ b/src/LimeSurvey/Exception/IncorrectClassOfResultItemException.php
@@ -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);
}
}
diff --git a/src/Exception/InvalidResultOfMethodRunException.php b/src/LimeSurvey/Exception/InvalidResultOfMethodRunException.php
similarity index 93%
rename from src/Exception/InvalidResultOfMethodRunException.php
rename to src/LimeSurvey/Exception/InvalidResultOfMethodRunException.php
index 7b639b0..b8e659d 100644
--- a/src/Exception/InvalidResultOfMethodRunException.php
+++ b/src/LimeSurvey/Exception/InvalidResultOfMethodRunException.php
@@ -19,6 +19,8 @@ use Meritoo\Common\Utilities\Arrays;
*/
class InvalidResultOfMethodRunException extends Exception
{
+ const className = 'Meritoo\LimeSurvey\ApiClient\Exception\InvalidResultOfMethodRunException';
+
/**
* Class constructor
*
diff --git a/src/Exception/MissingParticipantOfSurveyException.php b/src/LimeSurvey/Exception/MissingParticipantOfSurveyException.php
similarity index 89%
rename from src/Exception/MissingParticipantOfSurveyException.php
rename to src/LimeSurvey/Exception/MissingParticipantOfSurveyException.php
index 4f58849..ab968b1 100644
--- a/src/Exception/MissingParticipantOfSurveyException.php
+++ b/src/LimeSurvey/Exception/MissingParticipantOfSurveyException.php
@@ -16,6 +16,8 @@ namespace Meritoo\LimeSurvey\ApiClient\Exception;
*/
class MissingParticipantOfSurveyException extends \Exception
{
+ const className = 'Meritoo\LimeSurvey\ApiClient\Exception\MissingParticipantOfSurveyException';
+
/**
* Class constructor
*
diff --git a/src/Exception/UnknownInstanceOfResultItem.php b/src/LimeSurvey/Exception/UnknownInstanceOfResultItem.php
similarity index 90%
rename from src/Exception/UnknownInstanceOfResultItem.php
rename to src/LimeSurvey/Exception/UnknownInstanceOfResultItem.php
index e96c4c3..eeefbf3 100644
--- a/src/Exception/UnknownInstanceOfResultItem.php
+++ b/src/LimeSurvey/Exception/UnknownInstanceOfResultItem.php
@@ -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);
}
}
diff --git a/src/Exception/UnknownMethodException.php b/src/LimeSurvey/Exception/UnknownMethodException.php
similarity index 90%
rename from src/Exception/UnknownMethodException.php
rename to src/LimeSurvey/Exception/UnknownMethodException.php
index a207bd7..0bea822 100644
--- a/src/Exception/UnknownMethodException.php
+++ b/src/LimeSurvey/Exception/UnknownMethodException.php
@@ -19,6 +19,8 @@ use Meritoo\LimeSurvey\ApiClient\Type\MethodType;
*/
class UnknownMethodException extends UnknownTypeException
{
+ const className = 'Meritoo\LimeSurvey\ApiClient\Exception\UnknownMethodException';
+
/**
* {@inheritdoc}
*/
diff --git a/src/Manager/JsonRpcClientManager.php b/src/LimeSurvey/Manager/JsonRpcClientManager.php
similarity index 97%
rename from src/Manager/JsonRpcClientManager.php
rename to src/LimeSurvey/Manager/JsonRpcClientManager.php
index c41b8d2..02b3946 100644
--- a/src/Manager/JsonRpcClientManager.php
+++ b/src/LimeSurvey/Manager/JsonRpcClientManager.php
@@ -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
*
diff --git a/src/Manager/SessionManager.php b/src/LimeSurvey/Manager/SessionManager.php
similarity index 97%
rename from src/Manager/SessionManager.php
rename to src/LimeSurvey/Manager/SessionManager.php
index ff03b4b..74f530e 100644
--- a/src/Manager/SessionManager.php
+++ b/src/LimeSurvey/Manager/SessionManager.php
@@ -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.
diff --git a/src/Result/Collection/Participants.php b/src/LimeSurvey/Result/Collection/Participants.php
similarity index 97%
rename from src/Result/Collection/Participants.php
rename to src/LimeSurvey/Result/Collection/Participants.php
index 577435f..cee2244 100644
--- a/src/Result/Collection/Participants.php
+++ b/src/LimeSurvey/Result/Collection/Participants.php
@@ -24,6 +24,8 @@ use Meritoo\LimeSurvey\ApiClient\Result\Item\ParticipantShort;
*/
class Participants extends Collection
{
+ const className = 'Meritoo\LimeSurvey\ApiClient\Result\Collection\Participants';
+
/**
* {@inheritdoc}
*/
diff --git a/src/Result/Collection/Surveys.php b/src/LimeSurvey/Result/Collection/Surveys.php
similarity index 94%
rename from src/Result/Collection/Surveys.php
rename to src/LimeSurvey/Result/Collection/Surveys.php
index a9c1337..07fceb1 100644
--- a/src/Result/Collection/Surveys.php
+++ b/src/LimeSurvey/Result/Collection/Surveys.php
@@ -19,6 +19,8 @@ use Meritoo\LimeSurvey\ApiClient\Result\Item\Survey;
*/
class Surveys extends Collection
{
+ const className = 'Meritoo\LimeSurvey\ApiClient\Result\Collection\Surveys';
+
/**
* {@inheritdoc}
*/
diff --git a/src/Result/Item/Participant.php b/src/LimeSurvey/Result/Item/Participant.php
similarity index 98%
rename from src/Result/Item/Participant.php
rename to src/LimeSurvey/Result/Item/Participant.php
index 17f02dd..cf89f4b 100644
--- a/src/Result/Item/Participant.php
+++ b/src/LimeSurvey/Result/Item/Participant.php
@@ -20,6 +20,8 @@ use Meritoo\LimeSurvey\ApiClient\Base\Result\BaseItem;
*/
class Participant extends BaseItem
{
+ const className = 'Meritoo\LimeSurvey\ApiClient\Result\Item\Participant';
+
/**
* ID of the participant
*
diff --git a/src/Result/Item/ParticipantShort.php b/src/LimeSurvey/Result/Item/ParticipantShort.php
similarity index 96%
rename from src/Result/Item/ParticipantShort.php
rename to src/LimeSurvey/Result/Item/ParticipantShort.php
index 67d739a..aa83c33 100644
--- a/src/Result/Item/ParticipantShort.php
+++ b/src/LimeSurvey/Result/Item/ParticipantShort.php
@@ -18,6 +18,8 @@ use Meritoo\LimeSurvey\ApiClient\Base\Result\BaseItem;
*/
class ParticipantShort extends BaseItem
{
+ const className = 'Meritoo\LimeSurvey\ApiClient\Result\Item\ParticipantShort';
+
/**
* ID of the participant
*
diff --git a/src/Result/Item/Question.php b/src/LimeSurvey/Result/Item/Question.php
similarity index 97%
rename from src/Result/Item/Question.php
rename to src/LimeSurvey/Result/Item/Question.php
index 3270998..a7b9c1a 100644
--- a/src/Result/Item/Question.php
+++ b/src/LimeSurvey/Result/Item/Question.php
@@ -16,6 +16,8 @@ namespace Meritoo\LimeSurvey\ApiClient\Result\Item;
*/
class Question extends QuestionShort
{
+ const className = 'Meritoo\LimeSurvey\ApiClient\Result\Item\Question';
+
/**
* Available answers
*
diff --git a/src/Result/Item/QuestionShort.php b/src/LimeSurvey/Result/Item/QuestionShort.php
similarity index 98%
rename from src/Result/Item/QuestionShort.php
rename to src/LimeSurvey/Result/Item/QuestionShort.php
index 107ded3..51c99a1 100644
--- a/src/Result/Item/QuestionShort.php
+++ b/src/LimeSurvey/Result/Item/QuestionShort.php
@@ -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
*
diff --git a/src/Result/Item/Survey.php b/src/LimeSurvey/Result/Item/Survey.php
similarity index 97%
rename from src/Result/Item/Survey.php
rename to src/LimeSurvey/Result/Item/Survey.php
index 0f83073..52265d9 100644
--- a/src/Result/Item/Survey.php
+++ b/src/LimeSurvey/Result/Item/Survey.php
@@ -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
*
diff --git a/src/Result/Processor/ResultProcessor.php b/src/LimeSurvey/Result/Processor/ResultProcessor.php
similarity index 91%
rename from src/Result/Processor/ResultProcessor.php
rename to src/LimeSurvey/Result/Processor/ResultProcessor.php
index 563ebbc..7a082f6 100644
--- a/src/Result/Processor/ResultProcessor.php
+++ b/src/LimeSurvey/Result/Processor/ResultProcessor.php
@@ -27,6 +27,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 +90,23 @@ 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::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 +121,7 @@ class ResultProcessor
throw new UnknownInstanceOfResultItem($method);
}
- if (Reflection::isChildOfClass($className, BaseItem::class)) {
+ if (Reflection::isChildOfClass($className, BaseItem::className)) {
return $className;
}
diff --git a/src/Result/Result.php b/src/LimeSurvey/Result/Result.php
similarity index 98%
rename from src/Result/Result.php
rename to src/LimeSurvey/Result/Result.php
index a7cc8b9..d467e43 100644
--- a/src/Result/Result.php
+++ b/src/LimeSurvey/Result/Result.php
@@ -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.
*
diff --git a/src/Service/ParticipantService.php b/src/LimeSurvey/Service/ParticipantService.php
similarity index 98%
rename from src/Service/ParticipantService.php
rename to src/LimeSurvey/Service/ParticipantService.php
index 3d83a01..64a11b7 100644
--- a/src/Service/ParticipantService.php
+++ b/src/LimeSurvey/Service/ParticipantService.php
@@ -26,6 +26,8 @@ use Meritoo\LimeSurvey\ApiClient\Type\ReasonType;
*/
class ParticipantService
{
+ const className = 'Meritoo\LimeSurvey\ApiClient\Service\ParticipantService';
+
/**
* Client of the LimeSurvey's API
*
diff --git a/src/Service/SurveyService.php b/src/LimeSurvey/Service/SurveyService.php
similarity index 98%
rename from src/Service/SurveyService.php
rename to src/LimeSurvey/Service/SurveyService.php
index aca16c5..51c3429 100644
--- a/src/Service/SurveyService.php
+++ b/src/LimeSurvey/Service/SurveyService.php
@@ -25,6 +25,8 @@ use Meritoo\LimeSurvey\ApiClient\Type\ReasonType;
*/
class SurveyService
{
+ const className = 'Meritoo\LimeSurvey\ApiClient\Service\SurveyService';
+
/**
* Client of the LimeSurvey's API
*
diff --git a/src/Type/MethodType.php b/src/LimeSurvey/Type/MethodType.php
similarity index 97%
rename from src/Type/MethodType.php
rename to src/LimeSurvey/Type/MethodType.php
index 9b950d7..aba402b 100644
--- a/src/Type/MethodType.php
+++ b/src/LimeSurvey/Type/MethodType.php
@@ -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
*
diff --git a/src/Type/ReasonType.php b/src/LimeSurvey/Type/ReasonType.php
similarity index 93%
rename from src/Type/ReasonType.php
rename to src/LimeSurvey/Type/ReasonType.php
index 3b7ca81..cd33d1b 100644
--- a/src/Type/ReasonType.php
+++ b/src/LimeSurvey/Type/ReasonType.php
@@ -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
*
diff --git a/src/Type/SystemMethodType.php b/src/LimeSurvey/Type/SystemMethodType.php
similarity index 90%
rename from src/Type/SystemMethodType.php
rename to src/LimeSurvey/Type/SystemMethodType.php
index 9e1b2aa..0690787 100644
--- a/src/Type/SystemMethodType.php
+++ b/src/LimeSurvey/Type/SystemMethodType.php
@@ -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
*
diff --git a/tests/Base/Result/BaseItemTest.php b/tests/Base/Result/BaseItemTest.php
index 1efd5c0..932a745 100644
--- a/tests/Base/Result/BaseItemTest.php
+++ b/tests/Base/Result/BaseItemTest.php
@@ -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);
}
}
diff --git a/tests/Client/ClientTest.php b/tests/Client/ClientTest.php
index fb5fa03..ba51d7d 100644
--- a/tests/Client/ClientTest.php
+++ b/tests/Client/ClientTest.php
@@ -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
diff --git a/tests/Configuration/ConnectionConfigurationTest.php b/tests/Configuration/ConnectionConfigurationTest.php
index 3f1883e..695ad3a 100644
--- a/tests/Configuration/ConnectionConfigurationTest.php
+++ b/tests/Configuration/ConnectionConfigurationTest.php
@@ -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',
];
+ */
}
/**
diff --git a/tests/Exception/CannotProcessDataExceptionTest.php b/tests/Exception/CannotProcessDataExceptionTest.php
index d751433..ee2b0c0 100644
--- a/tests/Exception/CannotProcessDataExceptionTest.php
+++ b/tests/Exception/CannotProcessDataExceptionTest.php
@@ -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'),
];
+ */
}
}
diff --git a/tests/Exception/CreateSessionKeyFailedExceptionTest.php b/tests/Exception/CreateSessionKeyFailedExceptionTest.php
index 7a465e8..b25c315 100644
--- a/tests/Exception/CreateSessionKeyFailedExceptionTest.php
+++ b/tests/Exception/CreateSessionKeyFailedExceptionTest.php
@@ -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'),
];
+ */
}
}
diff --git a/tests/Exception/IncorrectClassOfResultItemExceptionTest.php b/tests/Exception/IncorrectClassOfResultItemExceptionTest.php
index 6fa8189..c8b9a62 100644
--- a/tests/Exception/IncorrectClassOfResultItemExceptionTest.php
+++ b/tests/Exception/IncorrectClassOfResultItemExceptionTest.php
@@ -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),
];
+ */
}
}
diff --git a/tests/Exception/InvalidResultOfMethodRunExceptionTest.php b/tests/Exception/InvalidResultOfMethodRunExceptionTest.php
index 4179592..d5db24c 100644
--- a/tests/Exception/InvalidResultOfMethodRunExceptionTest.php
+++ b/tests/Exception/InvalidResultOfMethodRunExceptionTest.php
@@ -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"'),
];
+ */
}
}
diff --git a/tests/Exception/MissingParticipantOfSurveyExceptionTest.php b/tests/Exception/MissingParticipantOfSurveyExceptionTest.php
index 081fbbe..6e1f144 100644
--- a/tests/Exception/MissingParticipantOfSurveyExceptionTest.php
+++ b/tests/Exception/MissingParticipantOfSurveyExceptionTest.php
@@ -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);
}
/**
@@ -41,12 +41,27 @@ class MissingParticipantOfSurveyExceptionTest extends BaseTestCase
/**
* Provides ID of survey and e-mail address of the participant
*
- * @return Generator
+ * @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',
@@ -58,5 +73,6 @@ class MissingParticipantOfSurveyExceptionTest extends BaseTestCase
'another@email.comm',
sprintf($template, 'another@email.comm', 1234),
];
+ */
}
}
diff --git a/tests/Exception/UnknownInstanceOfResultItemTest.php b/tests/Exception/UnknownInstanceOfResultItemTest.php
index badf1e0..46a2320 100644
--- a/tests/Exception/UnknownInstanceOfResultItemTest.php
+++ b/tests/Exception/UnknownInstanceOfResultItemTest.php
@@ -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'),
];
+ */
}
}
diff --git a/tests/Exception/UnknownMethodExceptionTest.php b/tests/Exception/UnknownMethodExceptionTest.php
index 681bcfb..f14acaf 100644
--- a/tests/Exception/UnknownMethodExceptionTest.php
+++ b/tests/Exception/UnknownMethodExceptionTest.php
@@ -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),
];
+ */
}
}
diff --git a/tests/Manager/JsonRpcClientManagerTest.php b/tests/Manager/JsonRpcClientManagerTest.php
index 30d182d..93a9f6c 100644
--- a/tests/Manager/JsonRpcClientManagerTest.php
+++ b/tests/Manager/JsonRpcClientManagerTest.php
@@ -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);
}
/**
diff --git a/tests/Manager/SessionManagerTest.php b/tests/Manager/SessionManagerTest.php
index 158bcb5..ce3ddfd 100644
--- a/tests/Manager/SessionManagerTest.php
+++ b/tests/Manager/SessionManagerTest.php
@@ -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());
}
}
diff --git a/tests/Result/Collection/ParticipantsTest.php b/tests/Result/Collection/ParticipantsTest.php
index 131c982..a4adc89 100644
--- a/tests/Result/Collection/ParticipantsTest.php
+++ b/tests/Result/Collection/ParticipantsTest.php
@@ -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());
}
diff --git a/tests/Result/Collection/SurveysTest.php b/tests/Result/Collection/SurveysTest.php
index cc91985..5d0ff45 100644
--- a/tests/Result/Collection/SurveysTest.php
+++ b/tests/Result/Collection/SurveysTest.php
@@ -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()
diff --git a/tests/Result/Item/ParticipantShortTest.php b/tests/Result/Item/ParticipantShortTest.php
index d21e1df..1f34fb0 100644
--- a/tests/Result/Item/ParticipantShortTest.php
+++ b/tests/Result/Item/ParticipantShortTest.php
@@ -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()
diff --git a/tests/Result/Item/ParticipantTest.php b/tests/Result/Item/ParticipantTest.php
index eddd4e9..f7b6d20 100644
--- a/tests/Result/Item/ParticipantTest.php
+++ b/tests/Result/Item/ParticipantTest.php
@@ -46,7 +46,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 +54,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()
diff --git a/tests/Result/Item/QuestionShortTest.php b/tests/Result/Item/QuestionShortTest.php
index fd056fc..c431767 100644
--- a/tests/Result/Item/QuestionShortTest.php
+++ b/tests/Result/Item/QuestionShortTest.php
@@ -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()
diff --git a/tests/Result/Item/QuestionTest.php b/tests/Result/Item/QuestionTest.php
index 1cf1e27..1dd161c 100644
--- a/tests/Result/Item/QuestionTest.php
+++ b/tests/Result/Item/QuestionTest.php
@@ -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()
diff --git a/tests/Result/Item/SurveyTest.php b/tests/Result/Item/SurveyTest.php
index 638cac9..593d9ee 100644
--- a/tests/Result/Item/SurveyTest.php
+++ b/tests/Result/Item/SurveyTest.php
@@ -46,7 +46,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()
diff --git a/tests/Result/Processor/ResultProcessorTest.php b/tests/Result/Processor/ResultProcessorTest.php
index 2d98225..6bd40fd 100644
--- a/tests/Result/Processor/ResultProcessorTest.php
+++ b/tests/Result/Processor/ResultProcessorTest.php
@@ -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',
diff --git a/tests/Result/ResultTest.php b/tests/Result/ResultTest.php
index 5ccc906..a176a1c 100644
--- a/tests/Result/ResultTest.php
+++ b/tests/Result/ResultTest.php
@@ -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()
@@ -218,6 +218,6 @@ class ResultTest extends BaseTestCase
*/
private function getResultMock($constructorArguments)
{
- return $this->getMockForAbstractClass(Result::class, $constructorArguments);
+ return $this->getMockForAbstractClass(Result::className, $constructorArguments);
}
}
diff --git a/tests/Service/ParticipantServiceTest.php b/tests/Service/ParticipantServiceTest.php
index 3e217b2..7853652 100644
--- a/tests/Service/ParticipantServiceTest.php
+++ b/tests/Service/ParticipantServiceTest.php
@@ -51,7 +51,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 +62,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);
@@ -90,7 +90,7 @@ class ParticipantServiceTest extends BaseTestCase
public function testGetSurveyParticipantsWithImportantException()
{
- $this->expectException(CannotProcessDataException::class);
+ $this->setExpectedException(CannotProcessDataException::className);
$exception = new CannotProcessDataException(ReasonType::NO_TOKEN_TABLE);
$rpcClientManager = $this->getJsonRpcClientManagerWithException(1, $exception);
@@ -129,7 +129,7 @@ class ParticipantServiceTest extends BaseTestCase
public function testAddParticipantForNotExistingSurvey()
{
- $this->expectException(CannotProcessDataException::class);
+ $this->setExpectedException(CannotProcessDataException::className);
$exception = new CannotProcessDataException(ReasonType::NOT_EXISTING_SURVEY_ID);
$rpcClientManager = $this->getJsonRpcClientManagerWithException(1, $exception);
@@ -169,7 +169,7 @@ class ParticipantServiceTest extends BaseTestCase
$this->createServiceWithoutParticipants($rpcClientManager, $sessionManager);
$result = $this->serviceWithoutParticipants->addParticipant($surveyId, $firstName, $lastName, $email);
- static::assertInstanceOf(Participant::class, $result);
+ static::assertInstanceOf(Participant::className, $result);
static::assertEquals($firstName, $result->getFirstName());
static::assertEquals($lastName, $result->getLastName());
static::assertEquals($email, $result->getEmail());
@@ -186,7 +186,7 @@ class ParticipantServiceTest extends BaseTestCase
static::assertNull($this->serviceWithoutParticipants->getParticipant(1, 'john@scott.com'));
$participant = $this->serviceWithParticipants->getParticipant(1, 'john@scott.com');
- static::assertInstanceOf(ParticipantShort::class, $participant);
+ static::assertInstanceOf(ParticipantShort::className, $participant);
static::assertEquals('John', $participant->getFirstName());
static::assertEquals('Scott', $participant->getLastName());
static::assertEquals('john@scott.com', $participant->getEmail());
@@ -215,7 +215,7 @@ class ParticipantServiceTest extends BaseTestCase
static::assertNull($this->serviceWithoutParticipants->getParticipantDetails(1, 'john@scott.com'));
$participant = $this->serviceWithParticipants->getParticipantDetails(1, 'john@scott.com');
- static::assertInstanceOf(Participant::class, $participant);
+ static::assertInstanceOf(Participant::className, $participant);
static::assertEquals($runMethodCallResults['tid'], $participant->getId());
static::assertEquals($runMethodCallResults['firstname'], $participant->getFirstName());
static::assertEquals($runMethodCallResults['lastname'], $participant->getLastName());
@@ -229,7 +229,7 @@ class ParticipantServiceTest extends BaseTestCase
public function testHasParticipantFilledSurveyWithException()
{
- $this->expectException(MissingParticipantOfSurveyException::class);
+ $this->setExpectedException(MissingParticipantOfSurveyException::className);
$rpcClientManager = $this->getJsonRpcClientManager(1);
$sessionManager = $this->getSessionManager();
@@ -256,7 +256,7 @@ class ParticipantServiceTest extends BaseTestCase
public function testHasParticipantFilledSurveyUsingNotExistingParticipant()
{
- $this->expectException(MissingParticipantOfSurveyException::class);
+ $this->setExpectedException(MissingParticipantOfSurveyException::className);
$rpcClientManager = $this->getJsonRpcClientManager(1);
$sessionManager = $this->getSessionManager();
@@ -282,7 +282,7 @@ class ParticipantServiceTest extends BaseTestCase
*/
private function getSessionManager()
{
- return $this->createMock(SessionManager::class);
+ return $this->createMock(SessionManager::className);
}
/**
@@ -294,7 +294,7 @@ class ParticipantServiceTest extends BaseTestCase
*/
private function getJsonRpcClientManager($runMethodCallCount, array $runMethodCallResults = [])
{
- $rpcClientManager = $this->createMock(JsonRpcClientManager::class);
+ $rpcClientManager = $this->createMock(JsonRpcClientManager::className);
$rpcClientManager
->expects(static::exactly($runMethodCallCount))
@@ -314,7 +314,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))
diff --git a/tests/Service/SurveyServiceTest.php b/tests/Service/SurveyServiceTest.php
index a34cf68..7e71161 100644
--- a/tests/Service/SurveyServiceTest.php
+++ b/tests/Service/SurveyServiceTest.php
@@ -57,7 +57,7 @@ class SurveyServiceTest extends BaseTestCase
public function testConstructorVisibilityAndArguments()
{
- static::assertConstructorVisibilityAndArguments(SurveyService::class, OopVisibilityType::IS_PUBLIC, 2, 1);
+ static::assertConstructorVisibilityAndArguments(SurveyService::className, OopVisibilityType::IS_PUBLIC, 2, 1);
}
public function testGetClient()
@@ -68,8 +68,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);
@@ -80,7 +80,7 @@ class SurveyServiceTest extends BaseTestCase
public function testGetAllSurveysWithImportantException()
{
- $this->expectException(CannotProcessDataException::class);
+ $this->setExpectedException(CannotProcessDataException::className);
$exception = new CannotProcessDataException(ReasonType::NO_TOKEN_TABLE);
$rpcClientManager = $this->getJsonRpcClientManagerWithException(1, $exception);
@@ -202,7 +202,7 @@ class SurveyServiceTest extends BaseTestCase
*/
private function getSessionManager()
{
- return $this->createMock(SessionManager::class);
+ return $this->createMock(SessionManager::className);
}
/**
@@ -214,7 +214,7 @@ class SurveyServiceTest extends BaseTestCase
*/
private function getJsonRpcClientManager($runMethodCallCount, array $runMethodCallResults = [])
{
- $rpcClientManager = $this->createMock(JsonRpcClientManager::class);
+ $rpcClientManager = $this->createMock(JsonRpcClientManager::className);
$rpcClientManager
->expects(static::exactly($runMethodCallCount))
@@ -234,7 +234,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))
diff --git a/tests/Type/MethodTypeTest.php b/tests/Type/MethodTypeTest.php
index 0e9f24b..0b6d9cc 100644
--- a/tests/Type/MethodTypeTest.php
+++ b/tests/Type/MethodTypeTest.php
@@ -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,
];
+ */
}
/**
@@ -196,6 +270,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 +309,6 @@ class MethodTypeTest extends BaseTypeTestCase
MethodType::GET_PARTICIPANT_PROPERTIES,
true,
];
+ */
}
}
diff --git a/tests/Type/ReasonTypeTest.php b/tests/Type/ReasonTypeTest.php
index cb86bf8..ac28014 100644
--- a/tests/Type/ReasonTypeTest.php
+++ b/tests/Type/ReasonTypeTest.php
@@ -21,7 +21,7 @@ class ReasonTypeTest extends BaseTypeTestCase
{
public function testConstructorVisibilityAndArguments()
{
- static::assertHasNoConstructor(ReasonType::class);
+ static::assertHasNoConstructor(ReasonType::className);
}
/**
@@ -50,6 +50,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 +107,6 @@ class ReasonTypeTest extends BaseTypeTestCase
ReasonType::NO_TOKEN_TABLE,
true,
];
+ */
}
}
diff --git a/tests/Type/SystemMethodTypeTest.php b/tests/Type/SystemMethodTypeTest.php
index 779c10c..aeb6c95 100644
--- a/tests/Type/SystemMethodTypeTest.php
+++ b/tests/Type/SystemMethodTypeTest.php
@@ -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,
];
+ */
}
}