diff --git a/.coveralls.yml b/.coveralls.yml
new file mode 100644
index 0000000..38bd628
--- /dev/null
+++ b/.coveralls.yml
@@ -0,0 +1,2 @@
+coverage_clover: build/reports/coveralls/clover.xml
+json_path: build/reports/coveralls/upload.json
diff --git a/.env.dist b/.env
similarity index 80%
rename from .env.dist
rename to .env
index 4c093b4..1adfa20 100644
--- a/.env.dist
+++ b/.env
@@ -1,6 +1,6 @@
-# -----------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
### Docker
-# -----------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
#
# All containers
@@ -12,4 +12,4 @@ DOCKER_CONTAINER_PROJECT=common-library
# PHP configuration:
# - timezone
#
-TIMEZONE=Europe/Warsaw
+PHP_DATE_TIMEZONE=Europe/London
diff --git a/.gitignore b/.gitignore
index cb92a06..52730bb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,59 +1,19 @@
# ------------------------------------------------------------------------------
-### Environment-related parameters
+### Linux template
# ------------------------------------------------------------------------------
-.env
+*~
+# temporary files which can be created if a process still has a handle open of a deleted file
+.fuse_hidden*
-# ------------------------------------------------------------------------------
-### Vendors
-# ------------------------------------------------------------------------------
-/vendor/
+# KDE directory preferences
+.directory
+# Linux trash folder which might appear on any partition or disk
+.Trash-*
-# ------------------------------------------------------------------------------
-### Composer
-# ------------------------------------------------------------------------------
-/composer.lock
-/composer.phar
-
-
-# ------------------------------------------------------------------------------
-### Phing
-# ------------------------------------------------------------------------------
-/phing/properties
-
-
-# ------------------------------------------------------------------------------
-### PHPUnit
-# ------------------------------------------------------------------------------
-/phpunit.xml
-
-
-# ------------------------------------------------------------------------------
-### PHP Coding Standards Fixer
-# ------------------------------------------------------------------------------
-/.php_cs
-/.php_cs.cache
-
-
-# -----------------------------------------------------------------------------
-### Build files
-# -----------------------------------------------------------------------------
-/build/
-
-
-# ------------------------------------------------------------------------------
-### Generated databases
-# ------------------------------------------------------------------------------
-/data/tmp
-*.sql
-*.sqlite
-
-
-# ------------------------------------------------------------------------------
-### JetBrains template
-# ------------------------------------------------------------------------------
-/.idea
+# .nfs files are created when an open file is removed but is still being accessed
+.nfs*
# ------------------------------------------------------------------------------
@@ -87,29 +47,12 @@ Temporary Items
.apdisk
-# ------------------------------------------------------------------------------
-### Linux template
-# ------------------------------------------------------------------------------
-*~
-
-# temporary files which can be created if a process still has a handle open of a deleted file
-.fuse_hidden*
-
-# KDE directory preferences
-.directory
-
-# Linux trash folder which might appear on any partition or disk
-.Trash-*
-
-# .nfs files are created when an open file is removed but is still being accessed
-.nfs*
-
-
# ------------------------------------------------------------------------------
### Windows template
# ------------------------------------------------------------------------------
# Windows thumbnail cache files
Thumbs.db
+Thumbs.db:encryptable
ehthumbs.db
ehthumbs_vista.db
@@ -131,3 +74,131 @@ $RECYCLE.BIN/
# Windows shortcuts
*.lnk
+
+
+# ------------------------------------------------------------------------------
+### JetBrains template
+# ------------------------------------------------------------------------------
+# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
+# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
+
+# User-specific stuff
+.idea/**/workspace.xml
+.idea/**/tasks.xml
+.idea/**/usage.statistics.xml
+.idea/**/dictionaries
+.idea/**/shelf
+
+# Generated files
+.idea/**/contentModel.xml
+
+# Sensitive or high-churn files
+.idea/**/dataSources/
+.idea/**/dataSources.ids
+.idea/**/dataSources.local.xml
+.idea/**/sqlDataSources.xml
+.idea/**/dynamic.xml
+.idea/**/uiDesigner.xml
+.idea/**/dbnavigator.xml
+
+# Gradle
+.idea/**/gradle.xml
+.idea/**/libraries
+
+# Gradle and Maven with auto-import
+# When using Gradle or Maven with auto-import, you should exclude module files,
+# since they will be recreated, and may cause churn. Uncomment if using
+# auto-import.
+# .idea/modules.xml
+# .idea/*.iml
+# .idea/modules
+# *.iml
+# *.ipr
+
+# CMake
+cmake-build-*/
+
+# Mongo Explorer plugin
+.idea/**/mongoSettings.xml
+
+# File-based project format
+*.iws
+
+# IntelliJ
+out/
+
+# mpeltonen/sbt-idea plugin
+.idea_modules/
+
+# JIRA plugin
+atlassian-ide-plugin.xml
+
+# Cursive Clojure plugin
+.idea/replstate.xml
+
+# Crashlytics plugin (for Android Studio and IntelliJ)
+com_crashlytics_export_strings.xml
+crashlytics.properties
+crashlytics-build.properties
+fabric.properties
+
+# Editor-based Rest Client
+.idea/httpRequests
+
+# Android studio 3.1+ serialized cache file
+.idea/caches/build_file_checksums.ser
+
+
+# ------------------------------------------------------------------------------
+### Build files
+# ------------------------------------------------------------------------------
+/build/
+
+
+# ------------------------------------------------------------------------------
+### Phing
+# ------------------------------------------------------------------------------
+/phing/properties
+
+
+# ------------------------------------------------------------------------------
+### Infection
+# ------------------------------------------------------------------------------
+/infection.json
+
+
+# ------------------------------------------------------------------------------
+### Temporary data & databases
+# ------------------------------------------------------------------------------
+/data/tmp
+*.sqlite
+
+
+# ------------------------------------------------------------------------------
+### Composer & vendors
+# ------------------------------------------------------------------------------
+/composer.lock
+/composer.phar
+/vendor/
+
+
+# ------------------------------------------------------------------------------
+### PHPUnit
+# ------------------------------------------------------------------------------
+/phpunit.xml
+/.phpunit.result.cache
+/tests/Resources/var
+
+
+# ------------------------------------------------------------------------------
+### PHP Coding Standards Fixer
+# ------------------------------------------------------------------------------
+/.php_cs
+/.php_cs.cache
+
+
+# ------------------------------------------------------------------------------
+### PHP_CodeSniffer
+# ------------------------------------------------------------------------------
+/.phpcs-cache
+/phpcs.xml
diff --git a/.php_cs.dist b/.php_cs.dist
index d2f2f3c..d925f44 100644
--- a/.php_cs.dist
+++ b/.php_cs.dist
@@ -1,27 +1,52 @@
in([
- __DIR__ . '/src',
- __DIR__ . '/tests',
+ ->in(__DIR__)
+ ->exclude([
+ 'build',
+ 'vendor',
+ ])
+ ->notPath([
+ 'tests/Resources/var/',
]);
return PhpCsFixer\Config::create()
->setRules([
- '@Symfony' => true,
- 'binary_operator_spaces' => [
+ '@Symfony' => true,
+ '@PhpCsFixer' => true,
+ '@PHP71Migration' => true,
+ 'array_syntax' => ['syntax' => 'short'],
+ 'binary_operator_spaces' => [
'align_double_arrow' => true,
],
- 'blank_line_before_return' => false,
- 'cast_spaces' => false,
- 'concat_space' => [
+ 'blank_line_before_return' => false,
+ 'cast_spaces' => false,
+ 'concat_space' => [
'spacing' => 'one',
],
+ 'ordered_class_elements' => [
+ 'order' => [
+ 'use_trait',
+ 'constant_public',
+ 'constant_protected',
+ 'constant_private',
+ 'property_public',
+ 'property_protected',
+ 'property_private',
+ 'construct',
+ 'destruct',
+ 'magic',
+ 'method_public',
+ 'method_protected',
+ 'method_private',
+ ],
+ ],
'phpdoc_add_missing_param_annotation' => true,
- 'phpdoc_align' => false,
- 'phpdoc_order' => true,
- 'phpdoc_separation' => false,
- 'phpdoc_summary' => false,
- 'trim_array_spaces' => false,
+ 'phpdoc_align' => false,
+ 'phpdoc_order' => true,
+ 'phpdoc_separation' => false,
+ 'phpdoc_summary' => false,
+ 'trim_array_spaces' => false,
])
- ->setFinder($finder);
+ ->setFinder($finder)
+;
diff --git a/.travis-php-config.ini b/.travis-php-config.ini
new file mode 100644
index 0000000..c0f1249
--- /dev/null
+++ b/.travis-php-config.ini
@@ -0,0 +1,2 @@
+date.timezone = Europe/London
+memory_limit = 2G
diff --git a/.travis.yml b/.travis.yml
index f1bd310..8f3d997 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,17 +1,23 @@
language: php
php:
- - 5.6
- - 7.0
- - 7.1
- 7.2
+ - 7.3
+ - 7.4
before_install:
- sudo locale-gen de_DE.UTF-8 es_ES.UTF-8 en_GB.UTF-8 en_US.UTF-8 fr_FR.UTF-8 it_IT.UTF-8 pl_PL.UTF-8 ru_RU.UTF-8
- - composer global require hirak/prestissimo
+ - pear channel-discover pear.phing.info
install:
- - travis_wait 30 composer install -v
+ - pear install phing/phing
+ - phpenv rehash
+
+before_script:
+ - phpenv config-add .travis-php-config.ini
script:
- - php ./vendor/bin/phpunit
+ - phing
+
+after_success:
+ - travis_retry php vendor/bin/php-coveralls -v
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 475b1be..f7ee8f8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,106 @@
Common and useful classes, methods, exceptions etc.
+# 1.1.8
+
+1. [Composer] Upgrade all dev packages (to the latest, stable versions for PHP `7.4`)
+2. [BaseCollection] Interfaces of different types of collections. May be used to build specific collections.
+
+# 1.1.7
+
+1. [Arrays] Allow to define a key of next level elements in a function that returns elements from given level
+
+# 1.1.6
+
+1. [Arrays] Function that returns elements from given level
+
+# 1.1.5
+
+1. [BaseCollection] Prepare elements while adding them by `addMultiple()` method in the same way as passing them in
+ constructor.
+
+# 1.1.4
+
+1. [BaseCollection] Fix incorrectly working limit() method
+
+# 1.1.3
+
+1. Move `Renderable` class: `Meritoo\Common` -> `Meritoo\Common\Contract`
+2. Create and implement `CollectionInterface` as contract of all collections (e.g. based on the `BaseCollection` class)
+
+# 1.1.2
+
+1. Change mode of `Xdebug` to `coverage` in Docker's configuration to make it possible to generate code coverage by
+ `PHPUnit`
+2. Mark PHPUnit test as risky when it does not have a `@covers` annotation
+
+# 1.1.1
+
+1. [BaseCollection] Treat the `null` index as "no index" only while adding new element, iow. do not treat empty string
+ as "no index" behaviour.
+2. [Miscellaneous] [Regex] Use simpler & stronger pattern to match name of file
+3. Do not install `hirak/prestissimo` package while running Travis CI (incompatible with your PHP version, PHP
+ extensions and Composer version)
+4. Use PHP `7.4` while running build in Travis CI
+
+# 1.1.0
+
+1. Rename Meritoo\Common\Collection\Collection class to Meritoo\Common\Collection\BaseCollection. Add BaseCollection::
+ isValidType() method to validate type of element before add it to collection. Add BaseCollection ::prepareElements()
+ method to allow preparation of elements in custom way.
+
+# 1.0.6
+
+1. Use `.env` instead of `.env.dist`
+2. Docker > use images (instead of Dockerfiles)
+3. composer > squizlabs/php_codesniffer package > use ^3.4 (instead of ^2.9)
+4. Do not require name of class by BaseTestCaseTrait::assertMethodVisibilityAndArguments() method
+5. PHP CS Fixer > configuration > make more readable & remove unnecessary code
+6. Update .gitignore, docker-compose.yml, phpunit.xml.dist
+
+# 1.0.5
+
+1. Collection > trait > return "void" where "self" causes type hinting problem and is not required
+
+# 1.0.4
+
+1. PHP Coding Standards Fixer > update configuration
+2. Phing > tests > add task for Psalm (https://psalm.dev)
+3. Collection > trait > split into smaller traits (to make it more flexible)
+
+# 1.0.3
+
+1. Travis CI > run many tasks using Phing > update configuration
+2. Template with placeholders > verification of placeholders without values > make stronger and point out which are
+ missing
+3. Reflection > getPropertyValue() method > look for the property in parent classes
+
+# 1.0.2
+
+1. Phing > remove old and unused tools
+2. Phing > configuration > minor updates
+3. Implement Mutation Testing Framework (infection/infection package)
+4. Travis CI > run many tasks using Phing (instead of PHPUnit only)
+5. Fix integration with [Coveralls](https://www.coveralls.io) (available as the badge in [README.md](README.md))
+6. Implement [PHPStan](https://github.com/phpstan/phpstan)
+7. PHPUnit > execute tests in random order
+8. Implement [Psalm](https://github.com/vimeo/psalm)
+9. Infection (Mutation Testing Framework) > fix bugs while running (generate proper code coverage, bugs while running
+ tests randomly)
+10. Phing > php-coveralls > add task
+
+# 1.0.1
+
+1. Regex > make compatible with PHP 7.3 Tests > Regex > fix "preg_match(): Compilation failed: invalid range in
+ character class at offset 4" bug
+2. Collection/storage of templates
+3. Template with placeholders that may be filled by real data
+4. RenderableInterface > something that may be rendered
+
+# 1.0.0
+
+1. Composer > support/require PHP 7.2+ (instead of 5.6+)
+
# 0.1.8
1. Size, e.g. of image
@@ -40,7 +140,8 @@ Common and useful classes, methods, exceptions etc.
1. Tests > refactoring & minor improvements
2. Utilities > CssSelector > useful methods related to CSS selectors
-3. Utilities > Bootstrap4CssSelector > useful methods related to CSS selectors and the Bootstrap4 (front-end component library)
+3. Utilities > Bootstrap4CssSelector > useful methods related to CSS selectors and the Bootstrap4 (front-end component
+ library)
# 0.1.2
@@ -79,5 +180,6 @@ Common and useful classes, methods, exceptions etc.
4. StyleCI & PHP Coding Standards Fixer: update configuration
5. Documentation > Docker > add paragraph for PHP Coding Standards Fixer
6. Coding standard > fix automatically
-7. StyleCI configuration > fix bug "The provided fixer 'binary_operator_spaces' cannot be enabled again because it was already enabled"
+7. StyleCI configuration > fix bug "The provided fixer 'binary_operator_spaces' cannot be enabled again because it was
+ already enabled"
8. StyleCI > disable & remove
diff --git a/README.md b/README.md
index f3b06ea..c1c26b4 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,12 @@
Common and useful classes, methods, exceptions etc.
-[](https://img.shields.io/badge/php-%3E%3D5.6-blue.svg) [](https://travis-ci.org/meritoo/common-library) [](https://packagist.org/packages/meritoo/common-library) [](https://github.com/meritoo/common-library) [](https://github.com/meritoo/common-library) [](https://coveralls.io/github/meritoo/common-library?branch=master)
+
+[](https://travis-ci.com/meritoo/common-library)
+[](https://packagist.org/packages/meritoo/common-library)
+[](https://github.com/meritoo/common-library)
+[](https://github.com/meritoo/common-library)
+[](https://coveralls.io/github/meritoo/common-library)
# Installation
@@ -29,11 +34,12 @@ composer require wiosna-dev/common-library
# Usage
1. [Base test case (with common methods and data providers)](docs/Base-test-case.md)
-2. [Collection of elements](docs/Collection-of-elements.md)
+2. [Collection of elements](docs/Collection/BaseCollection.md)
3. [Exceptions](docs/Static-methods.md)
4. [Static methods](docs/Static-methods.md)
- 1. [Arrays](docs/Static-methods/Arrays.md)
- 2. [Regex](docs/Static-methods/Regex.md)
+ 1. [Arrays](docs/Static-methods/Arrays.md)
+ 2. [Regex](docs/Static-methods/Regex.md)
+ 3. [Uri](docs/Static-methods/Uri.md)
5. [Value Objects](docs/Value-Objects.md)
# Development
diff --git a/VERSION b/VERSION
index 699c6c6..18efdb9 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.1.8
+1.1.8
diff --git a/build.xml b/build.xml
index 594cf4b..5275a88 100644
--- a/build.xml
+++ b/build.xml
@@ -3,12 +3,12 @@
-
+
-
+
-
+
@@ -20,11 +20,11 @@
-
+
-
+
diff --git a/composer.json b/composer.json
index 44804c5..f119e81 100644
--- a/composer.json
+++ b/composer.json
@@ -10,24 +10,25 @@
}
],
"require": {
+ "php": "^7.4",
"ext-dom": "*",
"ext-fileinfo": "*",
- "ext-json": "*",
- "ext-simplexml": "*",
- "php": ">=5.6",
"ext-intl": "*",
+ "ext-json": "*",
"ext-pcre": "*",
- "doctrine/orm": "^2.5",
- "gedmo/doctrine-extensions": "^2.4"
+ "ext-simplexml": "*",
+ "doctrine/orm": "^2.6",
+ "gedmo/doctrine-extensions": "^3.0"
},
"require-dev": {
- "friendsofphp/php-cs-fixer": "^2.2",
- "pdepend/pdepend": "^2.5",
- "phploc/phploc": "^2.1",
- "phpmd/phpmd": "^2.6",
- "phpunit/phpunit": "^4.8",
- "sebastian/phpcpd": "^2.0",
- "squizlabs/php_codesniffer": "^2.9"
+ "friendsofphp/php-cs-fixer": "^3.11",
+ "infection/infection": "^0.26",
+ "php-coveralls/php-coveralls": "^2.5",
+ "phpstan/phpstan": "^1.8",
+ "phpunit/phpunit": "^9",
+ "sebastian/phpcpd": "^6.0",
+ "squizlabs/php_codesniffer": "^3.7",
+ "vimeo/psalm": "^4.0"
},
"autoload": {
"psr-4": {
diff --git a/docker-compose.yml b/docker-compose.yml
index 6224f02..98a0357 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -5,29 +5,29 @@ services:
# Required to run project
#
php:
- image: ${DOCKER_CONTAINER_OWNER}/${DOCKER_CONTAINER_PROJECT}-php
+ image: meritoo/php:7.4
container_name: ${DOCKER_CONTAINER_OWNER}-${DOCKER_CONTAINER_PROJECT}-php
entrypoint: php
command: -S 0.0.0.0:9999
- build:
- context: ./docker/config
- args:
- - TIMEZONE=${TIMEZONE}
+ environment:
+ PHP_DATE_TIMEZONE: ${PHP_DATE_TIMEZONE}
volumes:
- - .:/project:cached
+ - .:/var/www/application:cached
composer:
- image: ${DOCKER_CONTAINER_OWNER}/${DOCKER_CONTAINER_PROJECT}-php
+ image: meritoo/php:7.4
container_name: ${DOCKER_CONTAINER_OWNER}-${DOCKER_CONTAINER_PROJECT}-composer
entrypoint: php -d memory_limit=-1 /usr/local/bin/composer
volumes:
- - .:/project:cached
+ - .:/var/www/application:cached
#
# Required to run PHPUnit's tests
#
phpunit:
- image: ${DOCKER_CONTAINER_OWNER}/${DOCKER_CONTAINER_PROJECT}-php
+ image: meritoo/php:7.4
container_name: ${DOCKER_CONTAINER_OWNER}-${DOCKER_CONTAINER_PROJECT}-phpunit
entrypoint: ./vendor/bin/phpunit
command: --version
volumes:
- - .:/project:cached
+ - .:/var/www/application:cached
+ environment:
+ XDEBUG_MODE: coverage
diff --git a/docker/config/Dockerfile b/docker/config/Dockerfile
deleted file mode 100644
index 277e672..0000000
--- a/docker/config/Dockerfile
+++ /dev/null
@@ -1,131 +0,0 @@
-FROM php:5.6-cli
-MAINTAINER Meritoo
-
-#
-# Tools & libraries
-#
-RUN apt-get update \
- && apt-get install -y --no-install-recommends \
- vim \
- git \
- unzip \
- libicu-dev \
- locales \
- && apt-get clean \
- && rm -rf \
- /var/lib/apt/lists/* \
- /tmp/* \
- /var/tmp/*
-
-#
-# Generating locales:
-# - de_DE
-# - es_ES
-# - en_GB
-# - en_US
-# - fr_FR
-# - it_IT
-# - pl_PL
-# - ru_RU
-#
-RUN sed -i 's/^# de_DE/de_DE/g; \
- s/^# es_ES/es_ES/g; \
- s/^# en_GB/en_GB/g; \
- s/^# en_US/en_US/g; \
- s/^# fr_FR/fr_FR/g; \
- s/^# it_IT/it_IT/g; \
- s/^# pl_PL/pl_PL/g; \
- s/^# ru_RU/ru_RU/g;' /etc/locale.gen \
- && locale-gen
-
-#
-# Set default language
-#
-# Required to avoid problem with using strange language by error messages.
-# Example: "chmod(): Aucun fichier ou dossier de ce type"
-#
-ENV LANGUAGE=en_US.UTF-8
-
-#
-# PHP extensions
-#
-RUN docker-php-ext-install \
- intl \
- mbstring
-
-#
-# PHP extensions (PECL):
-# - Xdebug
-#
-RUN pecl install \
- xdebug-2.5.5 \
- && docker-php-ext-enable \
- xdebug
-
-COPY xdebug.ini /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
-
-#
-# PHP configuration:
-# - default configuration
-# - timezone
-#
-COPY php.ini /usr/local/etc/php/php.ini
-ARG TIMEZONE
-RUN ln -snf /usr/share/zoneinfo/${TIMEZONE} /etc/localtime \
- && echo ${TIMEZONE} > /etc/timezone \
- && printf '[PHP]\ndate.timezone = "%s"\n' ${TIMEZONE} > /usr/local/etc/php/conf.d/tzone.ini \
- && "date"
-#RUN echo "\n""date.timezone = $TIMEZONE""\n" >> /usr/local/etc/php/php.ini
-
-#
-# Phing
-#
-RUN pear channel-discover pear.phing.info \
- && pear install [--alldeps] phing/phing
-
-#
-# Composer - environment variables:
-# - disable warning about running commands as root/super user
-# - disable automatic clearing of sudo sessions
-#
-# More:
-# https://getcomposer.org/doc/03-cli.md#composer-allow-superuser
-#
-ENV COMPOSER_ALLOW_SUPERUSER 1
-
-#
-# Composer + https://packagist.org/packages/hirak/prestissimo package
-#
-RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" \
- && php -r "if (hash_file('SHA384', 'composer-setup.php') === \
- '93b54496392c062774670ac18b134c3b3a95e5a5e5c8f1a9f115f203b75bf9a129d5daa8ba6a13e2cc8a1da0806388a8') { echo \
- 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;" \
- && php composer-setup.php --install-dir=/usr/local/bin --filename=composer \
- && php -r "unlink('composer-setup.php');" \
- && composer global require \
- --no-plugins \
- --no-scripts \
- --no-progress \
- --no-suggest \
- --no-interaction \
- --prefer-dist \
- --optimize-autoloader \
- --classmap-authoritative \
- hirak/prestissimo \
- && rm -rf ~/.composer/cache/* \
- && composer clear-cache \
- && composer --version
-
-#
-# Bash
-#
-RUN sed -i 's/^# export/export/g; \
- s/^# alias/alias/g;' ~/.bashrc \
- && echo 'COLUMNS=200'"\n" >> ~/.bashrc
-
-#
-# Use project-related binaries globally
-#
-ENV PATH="/project/vendor/bin:${PATH}"
-
-WORKDIR /project
diff --git a/docker/config/php.ini b/docker/config/php.ini
deleted file mode 100644
index b984c5d..0000000
--- a/docker/config/php.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-display_errors = On
-display_startup_errors = On
-error_reporting = E_ALL
diff --git a/docker/config/xdebug.ini b/docker/config/xdebug.ini
deleted file mode 100644
index 22b2547..0000000
--- a/docker/config/xdebug.ini
+++ /dev/null
@@ -1,6 +0,0 @@
-[xdebug]
-zend_extension=xdebug.so
-
-xdebug.remote_enable=1
-xdebug.remote_port=9001
-xdebug.remote_host=10.254.254.254
diff --git a/docs/Base-test-case.md b/docs/Base-test-case.md
index b35c744..87e2a04 100644
--- a/docs/Base-test-case.md
+++ b/docs/Base-test-case.md
@@ -4,7 +4,15 @@ Common and useful classes, methods, exceptions etc.
# Base test case (with common methods and data providers)
-Located here: `Meritoo\Common\Test\Base\BaseTestCase`. Just extend the `BaseTestCase` class and use it like in `Meritoo\Common\Test\Utilities\DateTest` class:
+Located here: `Meritoo\Common\Test\Base\BaseTestCase`.
+
+##### Usage
+
+1. Just extend the `BaseTestCase` class or implement `Meritoo\Common\Traits\Test\Base\BaseTestCaseTrait` trait.
+2. Use one of available data providers, e.g. `@dataProvider provideEmptyValue`, or asserts,
+ e.g. `static::assertMethodVisibility($method, $visibilityType);`
+
+##### Examples
```php
class DateTest extends BaseTestCase
@@ -22,8 +30,6 @@ class DateTest extends BaseTestCase
}
```
-or in `Meritoo\Common\Test\Utilities\MimeTypesTest` class:
-
```php
class MimeTypesTest extends BaseTestCase
{
@@ -45,11 +51,13 @@ class MimeTypesTest extends BaseTestCase
# More
1. [**Base test case (with common methods and data providers)**](Base-test-case.md)
-2. [Collection of elements](Collection-of-elements.md)
-3. [Exceptions](Exceptions.md)
-4. [Static methods](Static-methods.md)
- 1. [Arrays](Static-methods/Arrays.md)
- 2. [Regex](Static-methods/Regex.md)
-5. [Value Objects](Value-Objects.md)
+2. [Collection of elements](Collection/BaseCollection.md)
+3. [Templates](Collection/Templates.md)
+4. [Exceptions](Exceptions.md)
+5. [Static methods](Static-methods.md)
+ 1. [Arrays](Static-methods/Arrays.md)
+ 2. [Regex](Static-methods/Regex.md)
+ 3. [Uri](Static-methods/Uri.md)
+6. [Value Objects](Value-Objects.md)
[‹ Back to `Readme`](../README.md)
diff --git a/docs/Collection-of-elements.md b/docs/Collection-of-elements.md
deleted file mode 100644
index 2493afc..0000000
--- a/docs/Collection-of-elements.md
+++ /dev/null
@@ -1,53 +0,0 @@
-# Meritoo Common Library
-
-Common and useful classes, methods, exceptions etc.
-
-# Collection of elements
-
-Located here: `Meritoo\Common\Collection\Collection`. It's a set of some elements, e.g. objects. It's iterable and countable. Provides very useful methods. Some of them:
-- `getFirst()` - returns the first element in the collection
-- `getLast()` - returns the last element in the collection
-- `isEmpty()` - returns information if collection is empty
-- `add($element, $index = null)` - adds given element (at the end of collection)
-- `addMultiple($elements, $useIndexes = false)` - adds given elements (at the end of collection)
-- `prepend($element)` - prepends given element (adds given element at the beginning of collection)
-- `remove($element)` - removes given element
-
-Examples of usage below.
-
-### An empty collection
-
-```php
-use Meritoo\Common\Collection\Collection;
-
-$emptyCollection = new Collection();
-var_dump($emptyCollection->isEmpty()); // bool(true)
-```
-
-### Simple collection
-
-```php
-use Meritoo\Common\Collection\Collection;
-
-$elements = [
- 'lorem',
- 'ipsum',
- 123 => 'dolor',
- 345 => 'sit',
-];
-
-$simpleCollection = new Collection($elements);
-var_dump($simpleCollection->has('dolor')); // bool(true)
-```
-
-# More
-
-1. [Base test case (with common methods and data providers)](Base-test-case.md)
-2. [**Collection of elements**](Collection-of-elements.md)
-3. [Exceptions](Exceptions.md)
-4. [Static methods](Static-methods.md)
- 1. [Arrays](Static-methods/Arrays.md)
- 2. [Regex](Static-methods/Regex.md)
-5. [Value Objects](Value-Objects.md)
-
-[‹ Back to `Readme`](../README.md)
diff --git a/docs/Collection/BaseCollection.md b/docs/Collection/BaseCollection.md
new file mode 100644
index 0000000..b31e6a9
--- /dev/null
+++ b/docs/Collection/BaseCollection.md
@@ -0,0 +1,90 @@
+# Meritoo Common Library
+
+Common and useful classes, methods, exceptions etc.
+
+# BaseCollection
+
+### Namespace
+
+`Meritoo\Common\Collection\BaseCollection`
+
+### Info
+
+It's a set of some elements with the same type, e.g. objects. It's iterable and countable. Provides very useful methods.
+Some of them:
+
+- `getFirst()` - returns the first element in the collection
+- `getLast()` - returns the last element in the collection
+- `isEmpty()` - returns information if collection is empty
+- `add($element, $index = null)` - adds given element (at the end of collection)
+- `addMultiple($elements, $useIndexes = false)` - adds given elements (at the end of collection)
+- `prepend($element)` - prepends given element (adds given element at the beginning of collection)
+- `remove($element)` - removes given element
+
+### Implementation
+
+You have to implement:
+
+```php
+abstract protected function isValidType($element): bool;
+```
+
+This method verifies 1 element before it will be added to collection. Returns information if the element has valid,
+expected type.
+
+Example (from `Meritoo\Common\Collection\Templates` class):
+
+```php
+protected function isValidType($element): bool
+{
+ return $element instanceof Template;
+}
+```
+
+### Methods to overwrite
+
+You can, if you wish, overwrite these methods:
+
+1. To prepare elements used to initialize the collection in your own way:
+
+ ```php
+ protected function prepareElements(array $elements): array
+ ```
+
+2. To validate type of elements in your own way:
+
+ ```php
+ protected function getElementsWithValidType(array $elements): array
+ ```
+
+### Examples of usage
+
+```php
+use Meritoo\Common\Collection\StringCollection;
+
+$emptyCollection = new StringCollection();
+var_dump($emptyCollection->isEmpty()); // bool(true)
+
+$elements = [
+ 'lorem',
+ 'ipsum',
+ 123 => 'dolor',
+ 345 => 'sit',
+];
+
+$simpleCollection = new StringCollection($elements);
+var_dump($simpleCollection->has('dolor')); // bool(true)
+```
+
+# More
+
+1. [Base test case (with common methods and data providers)](../Base-test-case.md)
+2. [**Collection of elements**](BaseCollection.md)
+3. [Templates](Templates.md)
+4. [Exceptions](../Exceptions.md)
+5. [Static methods](../Static-methods.md)
+ 1. [Arrays](../Static-methods/Arrays.md)
+ 2. [Regex](../Static-methods/Regex.md)
+6. [Value Objects](../Value-Objects.md)
+
+[‹ Back to `Readme`](../../README.md)
diff --git a/docs/Collection/Templates.md b/docs/Collection/Templates.md
new file mode 100644
index 0000000..48258f5
--- /dev/null
+++ b/docs/Collection/Templates.md
@@ -0,0 +1,67 @@
+# Meritoo Common Library
+
+Common and useful classes, methods, exceptions etc.
+
+# Templates
+
+### Namespace
+
+`Meritoo\Common\Collection\Templates`
+
+### Info
+
+Collection/storage of templates, instance of `Meritoo\Common\ValueObject\Template` class.
+
+##### New instance
+
+New instance can be created using:
+
+1. Constructor:
+
+ ```php
+ new Templates([
+ 'first' => new Template('First name: %first_name%'),
+ 'last' => new Template('Last name: %last_name%'),
+ ]);
+ ```
+
+2. Static method `fromArray(array $templates)` - creates and returns the collection from given array
+
+ ```php
+ Templates::fromArray([
+ 'first' => 'First name: %first_name%',
+ 'last' => 'Last name: %last_name%',
+ ]);
+ ```
+
+##### Methods
+
+Has all methods of parent class `Meritoo\Common\Collection\Collection` + `findTemplate(string $index)` method that finds
+and returns template with given index.
+
+Example of usage:
+
+```php
+$templates = new Templates([
+ 'first' => new Template('First name: %first_name%'),
+ 'last' => new Template('Last name: %last_name%'),
+]);
+
+$template = $templates->findTemplate('first'); // new Template('First name: %first_name%')
+```
+
+Throws an `Meritoo\Common\Exception\ValueObject\Template\TemplateNotFoundException` exception if template with given
+index was not found.
+
+# More
+
+1. [Base test case (with common methods and data providers)](../Base-test-case.md)
+2. [Collection of elements](BaseCollection.md)
+3. [**Templates**](Templates.md)
+4. [Exceptions](../Exceptions.md)
+5. [Static methods](../Static-methods.md)
+ 1. [Arrays](../Static-methods/Arrays.md)
+ 2. [Regex](../Static-methods/Regex.md)
+6. [Value Objects](../Value-Objects.md)
+
+[‹ Back to `Readme`](../../README.md)
diff --git a/docs/Development.md b/docs/Development.md
index 7f60fb0..589a44c 100644
--- a/docs/Development.md
+++ b/docs/Development.md
@@ -17,9 +17,9 @@ Development-related information
2. Rebuild project by running command (installs packages, prepares required directories and runs tests):
- ```bash
- docker-compose exec php phing
- ```
+ ```bash
+ docker-compose exec php phing
+ ```
> [What is Docker?](https://www.docker.com/what-docker)
@@ -105,12 +105,48 @@ docker-compose exec php phing -f phing/tests.xml test:phpunit
docker-compose run --rm phpunit --verbose --no-coverage
```
-# Versions of packages
+# Infection - Mutation Testing
-### squizlabs/php_codesniffer
+Served by [Infection — Mutation Testing Framework](https://infection.github.io).
-I have to use [squizlabs/php_codesniffer](https://packagist.org/packages/squizlabs/php_codesniffer) `^2.9` instead of
-`^3.3`, because [Phing doesn't support 3.x PHP_CodeSniffer](https://github.com/phingofficial/phing/issues/716).
+### Running tests
+
+```bash
+$ docker-compose exec php bash
+root@18f2f0cfaa5d:/var/www/application# XDEBUG_MODE=coverage ./vendor/bin/infection --threads=$(nproc)
+```
+
+or
+
+```bash
+$ docker-compose exec php bash
+root@18f2f0cfaa5d:/var/www/application# XDEBUG_MODE=coverage phing -f phing/tests.xml test:infection
+```
+
+### Result of testing
+
+##### Terminal
+
+Example of output:
+
+```bash
+125 mutations were generated:
+ 105 mutants were killed
+ 3 mutants were not covered by tests
+ 5 covered mutants were not detected
+ 0 errors were encountered
+ 12 time outs were encountered
+
+Metrics:
+ Mutation Score Indicator (MSI): 93%
+ Mutation Code Coverage: 97%
+ Covered Code MSI: 95%
+```
+
+##### Stored in `build/reports/infection` directory
+
+* `build/reports/infection/infection-log.txt`
+* `build/reports/infection/summary-log.txt`
# Other
diff --git a/docs/Exceptions.md b/docs/Exceptions.md
index 14d7021..ccbb022 100644
--- a/docs/Exceptions.md
+++ b/docs/Exceptions.md
@@ -6,7 +6,8 @@ Common and useful classes, methods, exceptions etc.
### Create instance of exception
-This package contains a lot of exceptions. Each of them contains static method `create()` with proper arguments that is used to create instance of the exception. Example:
+This package contains a lot of exceptions. Each of them contains static method `create()` with proper arguments that is
+used to create instance of the exception. Example:
```php
use Meritoo\Common\Exception\Bundle\IncorrectBundleNameException;
@@ -17,11 +18,14 @@ throw IncorrectBundleNameException::create('RisusIpsum');
##### Short description
-It's a `Meritoo\Common\Exception\Base\UnknownTypeException` class. Related to `Meritoo\Common\Type\Base\BaseType` class that represents type of something, e.g. type of button, order.
+It's a `Meritoo\Common\Exception\Base\UnknownTypeException` class. Related to `Meritoo\Common\Type\Base\BaseType` class
+that represents type of something, e.g. type of button, order.
##### Usage
-You can extend `Meritoo\Common\Exception\Base\UnknownTypeException` class and create your own static method, e.g. `createException()`, which will be used create instance of the exception. Inside the `createException()` method you can call `parent::create()` method.
+You can extend `Meritoo\Common\Exception\Base\UnknownTypeException` class and create your own static method,
+e.g. `createException()`, which will be used create instance of the exception. Inside the `createException()` method you
+can call `parent::create()` method.
##### Example
@@ -54,11 +58,13 @@ class UnknownSimpleTypeException extends UnknownTypeException
# More
1. [Base test case (with common methods and data providers)](Base-test-case.md)
-2. [Collection of elements](Collection-of-elements.md)
-3. [**Exceptions**](Exceptions.md)
-4. [Static methods](Static-methods.md)
- 1. [Arrays](Static-methods/Arrays.md)
- 2. [Regex](Static-methods/Regex.md)
-5. [Value Objects](Value-Objects.md)
+2. [Collection of elements](Collection/BaseCollection.md)
+3. [Templates](Collection/Templates.md)
+4. [**Exceptions**](Exceptions.md)
+5. [Static methods](Static-methods.md)
+ 1. [Arrays](Static-methods/Arrays.md)
+ 2. [Regex](Static-methods/Regex.md)
+ 3. [Uri](Static-methods/Uri.md)
+6. [Value Objects](Value-Objects.md)
[‹ Back to `Readme`](../README.md)
diff --git a/docs/Static-methods.md b/docs/Static-methods.md
index d1d2227..19c8fff 100644
--- a/docs/Static-methods.md
+++ b/docs/Static-methods.md
@@ -4,7 +4,8 @@ Common and useful classes, methods, exceptions etc.
# Static methods
-This package contains a lot of class with static methods, so usage is not so complicated. Just run the static method who would you like to use. Example:
+This package contains a lot of class with static methods, so usage is not so complicated. Just run the static method who
+would you like to use. Example:
```php
use Meritoo\Common\Utilities\Arrays;
@@ -16,11 +17,13 @@ var_dump($firstElement); // string(5) "lorem"
# More
1. [Base test case (with common methods and data providers)](Base-test-case.md)
-2. [Collection of elements](Collection-of-elements.md)
-3. [Exceptions](Exceptions.md)
-4. [**Static methods**](Static-methods.md)
- 1. [Arrays](Static-methods/Arrays.md)
- 2. [Regex](Static-methods/Regex.md)
-5. [Value Objects](Value-Objects.md)
+2. [Collection of elements](Collection/BaseCollection.md)
+3. [Templates](Collection/Templates.md)
+4. [Exceptions](Exceptions.md)
+5. [**Static methods**](Static-methods.md)
+ 1. [Arrays](Static-methods/Arrays.md)
+ 2. [Regex](Static-methods/Regex.md)
+ 3. [Uri](Static-methods/Uri.md)
+6. [Value Objects](Value-Objects.md)
[‹ Back to `Readme`](../README.md)
diff --git a/docs/Static-methods/Arrays.md b/docs/Static-methods/Arrays.md
index b798505..ade1780 100644
--- a/docs/Static-methods/Arrays.md
+++ b/docs/Static-methods/Arrays.md
@@ -9,6 +9,31 @@ Common and useful classes, methods, exceptions etc.
Class: `Meritoo\Common\Utilities\Arrays`
File: `src/Utilities/Arrays.php`
+### containsEmptyStringsOnly(array): bool
+
+> Returns information if given array contains an empty strings only
+
+##### Arguments
+
+- `array $array` - The array to verify
+
+##### Examples
+
+1)
+
+- array: `[]` (an empty array)
+- result: `false`
+
+2)
+
+- array: `["", -1]`
+- result: `false`
+
+3)
+
+- array: `["", null, ""]`
+- result: `true`
+
### getNonEmptyValues(array $values)
> Returns non-empty values, e.g. without "" (empty string), null or []
@@ -17,17 +42,19 @@ File: `src/Utilities/Arrays.php`
- `array $values` - The values to filter
-##### Example 1
+##### Examples
+
+1)
- values: `[]` (no values)
- result: `[]` (an empty array)
-##### Example 2
+2)
- values: `[null, ""]` (all empty values)
- result: `[]` (an empty array)
-##### Example 3
+3)
- values: `["test 1", "", 123, null, 0]`
- result: `["test 1", 123, 0]`
@@ -41,25 +68,27 @@ File: `src/Utilities/Arrays.php`
- `array $values` - The values to filter
- `[string $separator]` - (optional) Separator used to implode the values. Default: ", ".
-##### Example 1
+##### Examples
+
+1)
- values: `[]` (no values)
- separator: default or any other string
- result: `""` (an empty string)
-##### Example 2
+2)
- values: `[null, ""]` (all empty values)
- separator: default or any other string
- result: `""` (an empty string)
-##### Example 3
+3)
- values: `["test 1", "", 123, null, 0]`
- separator: `", "` (default)
- result: `"test 1, 123, 0"`
-##### Example 4
+4)
- values: `["test 1", "", 123, null, 0]`
- separator: `" | "`
@@ -68,11 +97,13 @@ File: `src/Utilities/Arrays.php`
# More
1. [Base test case (with common methods and data providers)](../Base-test-case.md)
-2. [Collection of elements](../Collection-of-elements.md)
-3. [Exceptions](../Exceptions.md)
-4. [Static methods](../Static-methods.md)
- 1. [**Arrays**](Arrays.md)
- 2. [Regex](Regex.md)
-5. [Value Objects](../Value-Objects.md)
+2. [Collection of elements](../Collection/BaseCollection.md)
+3. [Templates](../Collection/Templates.md)
+4. [Exceptions](../Exceptions.md)
+5. [Static methods](../Static-methods.md)
+ 1. [**Arrays**](Arrays.md)
+ 2. [Regex](Regex.md)
+ 3. [Uri](Uri.md)
+6. [Value Objects](../Value-Objects.md)
[‹ Back to `Readme`](../../README.md)
diff --git a/docs/Static-methods/Regex.md b/docs/Static-methods/Regex.md
index e4ec57c..7e5e697 100644
--- a/docs/Static-methods/Regex.md
+++ b/docs/Static-methods/Regex.md
@@ -17,29 +17,83 @@ File: `src/Utilities/Regex.php`
- `string $value` - Value that should be transformed to slug
-##### Example 1
+##### Examples
+
+1)
- value: non-scalar or `null`
- result: `false`
-##### Example 2
+2)
- value: `""` (an empty string)
- result: `""` (an empty string)
-##### Example 3
+3)
- value: `"Lorem ipsum. Dolor sit 12.34 amet."`
- result: `"lorem-ipsum-dolor-sit-1234-amet"`
+### clearBeginningSlash(string): string
+
+> Clears, removes slash from the beginning of given string
+
+##### Arguments
+
+- `string $string` - String that may contains slash as the 1st character
+
+##### Examples
+
+1)
+
+- string: `"lorem ipsum"`
+- result: `"lorem ipsum"`
+
+2)
+
+- string: `"/lorem ipsum"`
+- result: `"lorem ipsum"`
+
+3)
+
+- string: `"/ lorem 123 ipsum"`
+- result: `" lorem 123 ipsum"`
+
+### clearEndingSlash(string): string
+
+> Clears, removes slash from the end of given string
+
+##### Arguments
+
+- `string $string` - String that may contains slash as the last character
+
+##### Examples
+
+1)
+
+- string: `"lorem ipsum"`
+- result: `"lorem ipsum"`
+
+2)
+
+- string: `"lorem ipsum/"`
+- result: `"lorem ipsum"`
+
+3)
+
+- string: `"lorem 123 ipsum /"`
+- result: `"lorem 123 ipsum "`
+
# More
1. [Base test case (with common methods and data providers)](../Base-test-case.md)
-2. [Collection of elements](../Collection-of-elements.md)
-3. [Exceptions](../Exceptions.md)
-4. [Static methods](../Static-methods.md)
- 1. [Arrays](../Static-methods/Arrays.md)
- 2. [**Regex**](Regex.md)
-5. [Value Objects](../Value-Objects.md)
+2. [Collection of elements](../Collection/BaseCollection.md)
+3. [Templates](../Collection/Templates.md)
+4. [Exceptions](../Exceptions.md)
+5. [Static methods](../Static-methods.md)
+ 1. [Arrays](../Static-methods/Arrays.md)
+ 2. [**Regex**](Regex.md)
+ 3. [Uri](Uri.md)
+6. [Value Objects](../Value-Objects.md)
[‹ Back to `Readme`](../../README.md)
diff --git a/docs/Static-methods/Uri.md b/docs/Static-methods/Uri.md
new file mode 100644
index 0000000..33cd80c
--- /dev/null
+++ b/docs/Static-methods/Uri.md
@@ -0,0 +1,47 @@
+# Meritoo Common Library
+
+Common and useful classes, methods, exceptions etc.
+
+# Uri
+
+> Useful methods related to uri
+
+Class: `Meritoo\Common\Utilities\Uri`
+File: `src/Utilities/Uri.php`
+
+### buildUrl(string, string ...): string
+
+> Builds url with given root url and parts of url (concatenates them using "/")
+
+##### Arguments
+
+- `string $rootUrl` - Protocol and domain (or domain only)
+- `string ...$urlParts` - Parts of url that will be concatenated with the rool url by "/"
+
+##### Examples
+
+1)
+
+- rootUrl: `"http://my.example"`
+- urlParts: `""` (an empty string)
+- result: `"http://my.example"`
+
+2)
+
+- rootUrl: `"http://my.example"`
+- urlParts: `"/test", "/123"`
+- result: `"http://my.example/test/123"`
+
+# More
+
+1. [Base test case (with common methods and data providers)](../Base-test-case.md)
+2. [Collection of elements](../Collection/BaseCollection.md)
+3. [Templates](../Collection/Templates.md)
+4. [Exceptions](../Exceptions.md)
+5. [Static methods](../Static-methods.md)
+ 1. [Arrays](Arrays.md)
+ 2. [Regex](Regex.md)
+ 3. [**Uri**](Uri.md)
+6. [Value Objects](../Value-Objects.md)
+
+[‹ Back to `Readme`](../../README.md)
diff --git a/docs/Value-Objects.md b/docs/Value-Objects.md
index 0d2f6ef..77a47dc 100644
--- a/docs/Value-Objects.md
+++ b/docs/Value-Objects.md
@@ -15,6 +15,7 @@ Located in `Meritoo\Common\ValueObject` namespace and in `src/ValueObject/` dire
##### Info
Represents address of company, institution, user etc. Contains properties:
+
1. `$street` - the street
2. `$buildingNumber` - the number of building
3. `$flatNumber` - the number of flat
@@ -66,6 +67,7 @@ $asString = (string)$address; // "4th Avenue 10/200, 00123, New York"
##### Info
Represents bank account. Contains properties:
+
1. `$bankName` - name of bank
2. `$accountNumber` - number of bank's account
@@ -101,6 +103,7 @@ $asString = (string)$bank; // "Bank of America, 1234567890"
##### Info
Represents a company. Contains properties:
+
1. `$name` - name of company
2. `$address` - address of company
3. `$bankAccount` - bank account of company
@@ -145,7 +148,9 @@ $asString = (string)$company; // "Test 1, 4th Avenue 10/200, 00123, New York, Ba
##### Info
-Represents human. Based on `\Meritoo\Common\Traits\ValueObject\HumanTrait` trait. Contains properties same as `HumanTrait` trait:
+Represents human. Based on `\Meritoo\Common\Traits\ValueObject\HumanTrait` trait. Contains properties same
+as `HumanTrait` trait:
+
1. `$firstName` - first name
2. `$lastName` - last name
3. `$email` - email address
@@ -186,6 +191,7 @@ $asString2 = (string)$human2; // "John Scott "
##### Info
Size, e.g. of image. Contains properties:
+
1. `width` - the width
2. `height` - the height
3. `unit` - unit used when width or height should be returned with unit, default: `"px"`
@@ -218,13 +224,15 @@ New instance can be created using static methods:
##### Methods
Has:
+
- getters and setters for `width` and `height` properties.
- setter for `separator` property
- `toString()` and `toArray()` methods that returns size represented as string and array
##### Conversion to string (using `__toString()` method)
-Instance of `Size` may be represented as string that contains width and height separated by separator (default: `" x "`).
+Instance of `Size` may be represented as string that contains width and height separated by separator (default: `" x "`)
+.
Example:
@@ -239,6 +247,56 @@ $size->setSeparator('X');
$asString2 = (string)$size; // "200X100"
```
+### Template
+
+##### Namespace
+
+`Meritoo\Common\ValueObject\Template`
+
+##### Info
+
+Template with placeholders that may be filled by real data. Contains properties:
+
+1. `$content` - raw string with placeholders (content of the template)
+
+##### New instance
+
+New instance can be created using constructor:
+
+```php
+new Template('First name: %first_name%');
+```
+
+Each placeholder should be wrapped by `%` character, e.g. `%first_name%`. If content of template is an empty string or
+does not contain 1 placeholder at least, an `Meritoo\Common\Exception\ValueObject\Template\InvalidContentException`
+exception will be thrown.
+
+Examples of invalid content of template:
+
+```php
+new Template(''); // An empty string
+new Template('test'); // Without placeholders
+new Template('This is %test'); // With starting tag only (invalid placeholder)
+```
+
+##### Methods
+
+Has 1 public method: `fill(array $values)`. Returns content of the template filled with given values (by replacing
+placeholders with their proper values).
+
+Example of usage:
+
+```php
+$template = new Template('My name is %name% and I am %profession%');
+$result = $template->fill([
+ 'name' => 'Jane',
+ 'profession' => 'photographer',
+]); // "My name is Jane and I am photographer"
+```
+
+Throws an `Meritoo\Common\Exception\ValueObject\Template\NotEnoughValuesException` exception if there is not enough
+values (iow. more placeholders than values).
+
### Version
##### Namespace
@@ -248,6 +306,7 @@ $asString2 = (string)$size; // "200X100"
##### Info
Represents version of software. Contains properties:
+
1. `$majorPart` - the "major" part of version
2. `$minorPart` - the "minor" part of version
3. `$patchPart` - the "patch" part of version
@@ -258,22 +317,22 @@ New instance can be created using:
1. Constructor:
- ```php
- new Version(1, 0, 2);
- ```
+ ```php
+ new Version(1, 0, 2);
+ ```
2. Static methods:
- 1. `fromArray()` - creates new instance using given version as array
+ 1. `fromArray(array $version)` - creates new instance using given version as array
- ```php
- Version::fromArray([1, 0, 2]);
- ```
+ ```php
+ Version::fromArray([1, 0, 2]);
+ ```
- 2. `fromString()` - creates new instance using given version as string:
+ 2. `fromString(string $version)` - creates new instance using given version as string:
- ```php
- Version::fromString('1.0.2');
- ```
+ ```php
+ Version::fromString('1.0.2');
+ ```
##### Methods
@@ -281,7 +340,8 @@ Has getters for each property: `getMajorPart()`, `getMinorPart()`, `getPatchPart
##### Conversion to string (using `__toString()` method)
-Instance of `Version` may be represented as string that contains all properties separated by `.` (`$majorPart`.`$minorPart`.`$patchPart`).
+Instance of `Version` may be represented as string that contains all properties separated by `.` (`$majorPart`
+.`$minorPart`.`$patchPart`).
Example:
@@ -293,11 +353,13 @@ $asString = (string)$version; // "1.0.2"
# More
1. [Base test case (with common methods and data providers)](Base-test-case.md)
-2. [Collection of elements](Collection-of-elements.md)
-3. [Exceptions](Exceptions.md)
-4. [Static methods](Static-methods.md)
- 1. [Arrays](Static-methods/Arrays.md)
- 2. [Regex](Static-methods/Regex.md)
-5. [**Value Objects**](Value-Objects.md)
+2. [Collection of elements](Collection/BaseCollection.md)
+3. [Templates](Collection/Templates.md)
+4. [Exceptions](Exceptions.md)
+5. [Static methods](Static-methods.md)
+ 1. [Arrays](Static-methods/Arrays.md)
+ 2. [Regex](Static-methods/Regex.md)
+ 3. [Uri](Static-methods/Uri.md)
+6. [**Value Objects**](Value-Objects.md)
[‹ Back to `Readme`](../README.md)
diff --git a/infection.json.dist b/infection.json.dist
new file mode 100644
index 0000000..06b8a4c
--- /dev/null
+++ b/infection.json.dist
@@ -0,0 +1,13 @@
+{
+ "timeout": 10,
+ "source": {
+ "directories": [
+ "src"
+ ]
+ },
+ "logs": {
+ "text": "build/reports/infection/infection-log.txt",
+ "summary": "build/reports/infection/summary-log.txt",
+ "debug": "build/reports/infection/debug-log.txt"
+ }
+}
diff --git a/phing/app.xml b/phing/app.xml
index 5688569..68c33cf 100644
--- a/phing/app.xml
+++ b/phing/app.xml
@@ -3,17 +3,17 @@
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
@@ -50,46 +50,41 @@
-
+
-
-
-
+
+
+
-
+
-
+
-
+
-
-
-
-
-
-
-
+
+
-
+
-
+
@@ -98,20 +93,20 @@
-
+
-
-
-
+
+
+
-
+
-
+
@@ -121,24 +116,24 @@
-
-
+
+
-
+
-
+
-
-
+
+
@@ -147,15 +142,15 @@
-
-
+
+
-
+
@@ -163,10 +158,10 @@
-
+
-
+
@@ -174,11 +169,11 @@
-
+
-
-
-
+
+
+
diff --git a/phing/filesets.xml b/phing/filesets.xml
index c3aea0c..59355ff 100644
--- a/phing/filesets.xml
+++ b/phing/filesets.xml
@@ -1,36 +1,14 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/phing/properties.dist b/phing/properties.dist
index bcb2fb5..76237a2 100644
--- a/phing/properties.dist
+++ b/phing/properties.dist
@@ -24,11 +24,11 @@ cache.clearWithWarmup = false
#
composer.download_command = bash ${project.basedir}/phing/composer-install.sh
-# Path to composer executable or downloaded composer.phar file
+# Path to Composer executable or downloaded composer.phar file
#
composer.path = ${project.basedir}/composer.phar
-# Path to php executable used by composer
+# Path to PHP executable used by Composer
#
composer.php = php
@@ -39,10 +39,6 @@ composer.php = php
# System directories
#
dir.src = ${project.basedir}/src
-dir.var = ${project.basedir}/tests/Resources/var
-dir.cache = ${dir.var}/cache
-dir.logs = ${dir.var}/log
-dir.sessions = ${dir.var}/sessions
dir.data = ${project.basedir}/data
dir.tests = ${project.basedir}/tests
@@ -50,19 +46,24 @@ dir.tests = ${project.basedir}/tests
#
dir.build = ${project.basedir}/build
dir.reports = ${dir.build}/reports
-dir.reports.pdepend = ${dir.reports}/pdepend
-dir.reports.coverage = ${dir.reports}/phpunit_coverage
+dir.reports.coverage = ${dir.reports}/phpunit-coverage
+dir.reports.code_sniffer = ${dir.reports}/code_sniffer
# Data directories
#
dir.data.tests = ${dir.data}/tests
dir.data.temporary = ${dir.data}/tmp
-# Docker directories
+# --------------------------------------------------------------------------------
+# Static Analysis
+# --------------------------------------------------------------------------------
+
+# Paths of frameworks used to run analysis:
+# - PHPStan
#
-dir.docker = ${project.basedir}/docker
-dir.docker.data = ${dir.docker}/data/db
-dir.docker.logs = ${dir.docker}/logs/nginx
+check.phpstan.command = ./vendor/bin/phpstan analyse
+check.psalm.command = ./vendor/bin/psalm --report=build/reports/psalm.json
+check.php_coveralls.command = ./vendor/bin/php-coveralls --ansi -v
# --------------------------------------------------------------------------------
# Testing
@@ -72,11 +73,17 @@ dir.docker.logs = ${dir.docker}/logs/nginx
#
tests.cs_fixer.command = ./vendor/bin/php-cs-fixer fix --verbose
+# Path of the PHP_CodeSniffer (https://github.com/squizlabs/PHP_CodeSniffer)
+#
+tests.code_sniffer.command = ./vendor/bin/phpcs --report-full=${dir.reports.code_sniffer}/full.txt --report-summary=${dir.reports.code_sniffer}/summary.txt --report-checkstyle=${dir.reports.code_sniffer}/checkstyle.xml
+
# Test database path
#
tests.database = ${dir.data.temporary}/database.sqlite
# Paths of frameworks used to run tests:
# - PHPUnit (unit tests)
+# - Infection (mutation tests)
#
tests.phpunit.command = ./vendor/bin/phpunit --verbose
+tests.mutation.command = ./vendor/bin/infection --ansi --threads=$(nproc) --coverage=build/reports/infection
diff --git a/phing/tests.xml b/phing/tests.xml
index 92f6190..4005fde 100644
--- a/phing/tests.xml
+++ b/phing/tests.xml
@@ -1,30 +1,30 @@
-
+
-
+
-
+
-
+
-
-
-
-
-
-
+
+
+
+
+
+
-
+
@@ -37,97 +37,87 @@
-
+
-
+
-
-
-
-
-
-
+
-
-
+
+
-
-
-
-
-
-
-
+
+
+
-
-
-
-
-
-
-
-
+
+
+
-
-
-
-
-
+
+
+
-
+
+
+
+
+
+
-
+
-
+
-
-
-
+
+
+
-
+
-
-
-
+
+
+
diff --git a/phpcs.xml.dist b/phpcs.xml.dist
new file mode 100644
index 0000000..2930822
--- /dev/null
+++ b/phpcs.xml.dist
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+ src/
+ tests/
+
+
diff --git a/phpstan.neon.dist b/phpstan.neon.dist
new file mode 100644
index 0000000..31f6166
--- /dev/null
+++ b/phpstan.neon.dist
@@ -0,0 +1,5 @@
+parameters:
+ level: 1
+ paths:
+ - src
+ - tests
diff --git a/phpunit.xml.dist b/phpunit.xml.dist
index f54393f..7e7cc7a 100644
--- a/phpunit.xml.dist
+++ b/phpunit.xml.dist
@@ -1,30 +1,37 @@
-
-
+
+
+
+ src
+
+
+
+
+
+
+
-
+
-
- tests/
+ tests
+
+
+ tests/Collection
-
-
-
- src/
-
-
-
-
+
diff --git a/psalm.xml b/psalm.xml
new file mode 100644
index 0000000..c0db670
--- /dev/null
+++ b/psalm.xml
@@ -0,0 +1,53 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Collection/BaseCollection.php b/src/Collection/BaseCollection.php
new file mode 100644
index 0000000..f6ff521
--- /dev/null
+++ b/src/Collection/BaseCollection.php
@@ -0,0 +1,349 @@
+
+ * @copyright Meritoo
+ */
+abstract class BaseCollection implements CollectionInterface
+{
+ /**
+ * The elements of collection
+ *
+ * @var array
+ */
+ private array $elements;
+
+ /**
+ * Class constructor
+ *
+ * @param array $elements (optional) Elements of collection
+ */
+ public function __construct(array $elements = [])
+ {
+ $validated = $this->getElementsWithValidType($elements);
+ $this->elements = $this->prepareElements($validated);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function add($element, $index = null): void
+ {
+ if (!$this->isValidType($element)) {
+ return;
+ }
+
+ if (null === $index) {
+ $this->elements[] = $element;
+
+ return;
+ }
+
+ $this->elements[$index] = $element;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function addMultiple($elements, bool $useIndexes = false): void
+ {
+ if (empty($elements)) {
+ return;
+ }
+
+ $prepared = $this->prepareElements($elements);
+
+ foreach ($prepared as $index => $element) {
+ if ($useIndexes) {
+ $this->add($element, $index);
+
+ continue;
+ }
+
+ $this->add($element);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function append($element): void
+ {
+ $this->elements[] = $element;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function clear(): void
+ {
+ $this->elements = [];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function count(): int
+ {
+ return count($this->elements);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getByIndex($index)
+ {
+ return $this->elements[$index] ?? null;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getFirst()
+ {
+ return Arrays::getFirstElement($this->elements);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getIterator(): ArrayIterator
+ {
+ return new ArrayIterator($this->elements);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getLast()
+ {
+ return Arrays::getLastElement($this->elements);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getNext($element)
+ {
+ return Arrays::getNextElement($this->elements, $element);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getPrevious($element)
+ {
+ return Arrays::getPreviousElement($this->elements, $element);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function has($element): bool
+ {
+ $index = Arrays::getIndexOf($this->elements, $element);
+
+ return null !== $index && false !== $index;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function isEmpty(): bool
+ {
+ return empty($this->elements);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function isFirst($element): bool
+ {
+ return reset($this->elements) === $element;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function isLast($element): bool
+ {
+ return end($this->elements) === $element;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function limit(int $max, int $offset = 0): self
+ {
+ $result = clone $this;
+
+ $negativeMax = $max <= 0;
+ $exceededMax = $max >= $this->count();
+
+ if ($negativeMax || $exceededMax) {
+ if ($negativeMax) {
+ $result->clear();
+ }
+
+ return $result;
+ }
+
+ $iteration = -1;
+
+ foreach ($result as $index => $element) {
+ $iteration++;
+
+ if ($iteration >= $offset && $iteration < $offset + $max) {
+ continue;
+ }
+
+ unset($result[$index]);
+ }
+
+ return $result;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function offsetExists($offset): bool
+ {
+ return $this->exists($offset);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function offsetGet($offset)
+ {
+ if ($this->exists($offset)) {
+ return $this->elements[$offset];
+ }
+
+ return null;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function offsetSet($offset, $value): void
+ {
+ $this->elements[$offset] = $value;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function offsetUnset($offset): void
+ {
+ if ($this->exists($offset)) {
+ unset($this->elements[$offset]);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function prepend($element): void
+ {
+ array_unshift($this->elements, $element);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function remove($element): void
+ {
+ if (0 === $this->count()) {
+ return;
+ }
+
+ foreach ($this->elements as $index => $existing) {
+ if ($element === $existing) {
+ unset($this->elements[$index]);
+
+ break;
+ }
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function toArray(): array
+ {
+ return $this->elements;
+ }
+
+ /**
+ * Returns information if given element has valid type
+ *
+ * @param mixed $element Element of collection
+ * @return bool
+ */
+ abstract protected function isValidType($element): bool;
+
+ /**
+ * Prepares elements to initialize the collection.
+ * Feel free to override and prepare elements in your way.
+ *
+ * @param array $elements The elements of collection to prepare
+ * @return array
+ */
+ protected function prepareElements(array $elements): array
+ {
+ return $elements;
+ }
+
+ /**
+ * Returns information if element with given index/key exists
+ *
+ * @param int|string $index The index/key of element
+ * @return bool
+ */
+ private function exists($index): bool
+ {
+ return isset($this->elements[$index]) || array_key_exists($index, $this->elements);
+ }
+
+ /**
+ * Returns elements of collection with valid types
+ *
+ * @param array $elements The elements of collection to verify
+ * @return array
+ */
+ private function getElementsWithValidType(array $elements): array
+ {
+ if (empty($elements)) {
+ return [];
+ }
+
+ $result = [];
+
+ foreach ($elements as $index => $element) {
+ if (!$this->isValidType($element)) {
+ continue;
+ }
+
+ $result[$index] = $element;
+ }
+
+ return $result;
+ }
+}
diff --git a/src/Collection/Collection.php b/src/Collection/Collection.php
deleted file mode 100644
index 6206ce5..0000000
--- a/src/Collection/Collection.php
+++ /dev/null
@@ -1,36 +0,0 @@
-
- * @copyright Meritoo
- */
-class Collection implements Countable, ArrayAccess, IteratorAggregate
-{
- use CollectionTrait;
-
- /**
- * Class constructor
- *
- * @param array $elements (optional) The elements of collection
- */
- public function __construct(array $elements = [])
- {
- $this->elements = $elements;
- }
-}
diff --git a/src/Collection/DateTimeCollection.php b/src/Collection/DateTimeCollection.php
new file mode 100644
index 0000000..f31c4f1
--- /dev/null
+++ b/src/Collection/DateTimeCollection.php
@@ -0,0 +1,27 @@
+
+ * @copyright Meritoo
+ */
+class DateTimeCollection extends BaseCollection
+{
+ protected function isValidType($element): bool
+ {
+ return $element instanceof DateTime;
+ }
+}
diff --git a/src/Traits/Collection/CountableTrait.php b/src/Collection/IntegerCollection.php
similarity index 56%
rename from src/Traits/Collection/CountableTrait.php
rename to src/Collection/IntegerCollection.php
index 4579d40..d284f71 100644
--- a/src/Traits/Collection/CountableTrait.php
+++ b/src/Collection/IntegerCollection.php
@@ -6,21 +6,20 @@
* file that was distributed with this source code.
*/
-namespace Meritoo\Common\Traits\Collection;
+declare(strict_types=1);
+
+namespace Meritoo\Common\Collection;
/**
- * Trait for the Collection required by Countable interface
+ * Collection of integers
*
* @author Meritoo
* @copyright Meritoo
*/
-trait CountableTrait
+class IntegerCollection extends BaseCollection
{
- /**
- * {@inheritdoc}
- */
- public function count()
+ protected function isValidType($element): bool
{
- return count($this->elements);
+ return is_int($element);
}
}
diff --git a/src/Collection/StringCollection.php b/src/Collection/StringCollection.php
new file mode 100644
index 0000000..2d9a191
--- /dev/null
+++ b/src/Collection/StringCollection.php
@@ -0,0 +1,25 @@
+
+ * @copyright Meritoo
+ */
+class StringCollection extends BaseCollection
+{
+ protected function isValidType($element): bool
+ {
+ return is_string($element);
+ }
+}
diff --git a/src/Collection/Templates.php b/src/Collection/Templates.php
new file mode 100644
index 0000000..6555228
--- /dev/null
+++ b/src/Collection/Templates.php
@@ -0,0 +1,72 @@
+
+ * @copyright Meritoo
+ */
+class Templates extends BaseCollection
+{
+ /**
+ * Finds and returns template with given index
+ *
+ * @param string $index Index that contains required template
+ * @return Template
+ * @throws TemplateNotFoundException
+ */
+ public function findTemplate(string $index): Template
+ {
+ $template = $this->getByIndex($index);
+
+ if ($template instanceof Template) {
+ return $template;
+ }
+
+ // Oops, template not found
+ throw TemplateNotFoundException::create($index);
+ }
+
+ /**
+ * Creates and returns the collection from given array
+ *
+ * @param array $templates Pairs of key-value where: key - template's index, value - template's content
+ * @return Templates
+ */
+ public static function fromArray(array $templates): Templates
+ {
+ // No templates. Nothing to do.
+ if (empty($templates)) {
+ return new static();
+ }
+
+ $result = new static();
+
+ foreach ($templates as $index => $template) {
+ $result->add(new Template($template), $index);
+ }
+
+ return $result;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function isValidType($element): bool
+ {
+ return $element instanceof Template;
+ }
+}
diff --git a/src/Contract/Collection/AddableCollectionInterface.php b/src/Contract/Collection/AddableCollectionInterface.php
new file mode 100644
index 0000000..e3e30cb
--- /dev/null
+++ b/src/Contract/Collection/AddableCollectionInterface.php
@@ -0,0 +1,55 @@
+
+ * @copyright Meritoo
+ */
+interface AddableCollectionInterface
+{
+ /**
+ * 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 void
+ */
+ public function add($element, $index = null): void;
+
+ /**
+ * Adds given elements (at the end of collection)
+ *
+ * @param array|CollectionInterface $elements The elements to add
+ * @param bool $useIndexes (optional) If is set to true, indexes of given elements will be
+ * used in this collection. Otherwise - not.
+ * @return void
+ */
+ public function addMultiple(array $elements, bool $useIndexes = false): void;
+
+ /**
+ * Appends given element (adds given element at the end of collection)
+ *
+ * @param mixed $element The element to add at the end
+ * @return void
+ */
+ public function append($element): void;
+
+ /**
+ * Prepends given element (adds given element at the beginning of collection)
+ *
+ * @param mixed $element The element to add at the beginning
+ * @return void
+ */
+ public function prepend($element): void;
+}
diff --git a/src/Contract/Collection/ClearableCollectionInterface.php b/src/Contract/Collection/ClearableCollectionInterface.php
new file mode 100644
index 0000000..96b6186
--- /dev/null
+++ b/src/Contract/Collection/ClearableCollectionInterface.php
@@ -0,0 +1,27 @@
+
+ * @copyright Meritoo
+ */
+interface ClearableCollectionInterface
+{
+ /**
+ * Removes all elements of the collection
+ *
+ * @return void
+ */
+ public function clear(): void;
+}
diff --git a/src/Contract/Collection/CollectionInterface.php b/src/Contract/Collection/CollectionInterface.php
new file mode 100644
index 0000000..e97ec1e
--- /dev/null
+++ b/src/Contract/Collection/CollectionInterface.php
@@ -0,0 +1,32 @@
+
+ * @copyright Meritoo
+ */
+interface CollectionInterface extends ArrayAccess, IteratorAggregate, AddableCollectionInterface,
+ RemovableCollectionInterface, CountableCollectionInterface, ClearableCollectionInterface,
+ GettableCollectionInterface, VerifiableCollectionInterface, ReducibleCollectionInterface
+{
+ /**
+ * Returns representation of object as array
+ *
+ * @return array
+ */
+ public function toArray(): array;
+}
diff --git a/src/Contract/Collection/CountableCollectionInterface.php b/src/Contract/Collection/CountableCollectionInterface.php
new file mode 100644
index 0000000..063cf07
--- /dev/null
+++ b/src/Contract/Collection/CountableCollectionInterface.php
@@ -0,0 +1,23 @@
+
+ * @copyright Meritoo
+ */
+interface CountableCollectionInterface extends Countable
+{
+}
diff --git a/src/Contract/Collection/GettableCollectionInterface.php b/src/Contract/Collection/GettableCollectionInterface.php
new file mode 100644
index 0000000..5b2ca54
--- /dev/null
+++ b/src/Contract/Collection/GettableCollectionInterface.php
@@ -0,0 +1,58 @@
+
+ * @copyright Meritoo
+ */
+interface GettableCollectionInterface
+{
+ /**
+ * Returns element with given index
+ *
+ * @param mixed $index Index / key of element to return
+ * @return mixed
+ */
+ public function getByIndex($index);
+
+ /**
+ * Returns first element
+ *
+ * @return mixed
+ */
+ public function getFirst();
+
+ /**
+ * Returns last element
+ *
+ * @return mixed
+ */
+ public function getLast();
+
+ /**
+ * Returns element next after given element
+ *
+ * @param mixed $element The element whose next element should be returned
+ * @return mixed
+ */
+ public function getNext($element);
+
+ /**
+ * Returns element preceding given element
+ *
+ * @param mixed $element The element whose previous element should be returned
+ * @return mixed
+ */
+ public function getPrevious($element);
+}
diff --git a/src/Contract/Collection/ReducibleCollectionInterface.php b/src/Contract/Collection/ReducibleCollectionInterface.php
new file mode 100644
index 0000000..d2b2584
--- /dev/null
+++ b/src/Contract/Collection/ReducibleCollectionInterface.php
@@ -0,0 +1,29 @@
+
+ * @copyright Meritoo
+ */
+interface ReducibleCollectionInterface
+{
+ /**
+ * Returns new instance of this collection with limited elements
+ *
+ * @param int $max Maximum elements to return
+ * @param int $offset (optional) Position of element from which limitation should start
+ * @return $this
+ */
+ public function limit(int $max, int $offset = 0): self;
+}
diff --git a/src/Contract/Collection/RemovableCollectionInterface.php b/src/Contract/Collection/RemovableCollectionInterface.php
new file mode 100644
index 0000000..d0a95fa
--- /dev/null
+++ b/src/Contract/Collection/RemovableCollectionInterface.php
@@ -0,0 +1,28 @@
+
+ * @copyright Meritoo
+ */
+interface RemovableCollectionInterface
+{
+ /**
+ * Removes given element
+ *
+ * @param mixed $element The element to remove
+ * @return void
+ */
+ public function remove($element): void;
+}
diff --git a/src/Contract/Collection/VerifiableCollectionInterface.php b/src/Contract/Collection/VerifiableCollectionInterface.php
new file mode 100644
index 0000000..98e7a67
--- /dev/null
+++ b/src/Contract/Collection/VerifiableCollectionInterface.php
@@ -0,0 +1,51 @@
+
+ * @copyright Meritoo
+ */
+interface VerifiableCollectionInterface
+{
+ /**
+ * Returns information if given element exists in collection
+ *
+ * @param mixed $element The element to verify
+ * @return bool
+ */
+ public function has($element): bool;
+
+ /**
+ * Returns information if collection is empty (has not any element)
+ *
+ * @return bool
+ */
+ public function isEmpty(): bool;
+
+ /**
+ * Returns information if given element is the first element in collection
+ *
+ * @param mixed $element The element to verify
+ * @return bool
+ */
+ public function isFirst($element): bool;
+
+ /**
+ * Returns information if given element is the last element in collection
+ *
+ * @param mixed $element The element to verify
+ * @return bool
+ */
+ public function isLast($element): bool;
+}
diff --git a/src/Contract/Renderable/RenderableInterface.php b/src/Contract/Renderable/RenderableInterface.php
new file mode 100644
index 0000000..12581b0
--- /dev/null
+++ b/src/Contract/Renderable/RenderableInterface.php
@@ -0,0 +1,31 @@
+
+ * @copyright Meritoo
+ */
+interface RenderableInterface
+{
+ /**
+ * Renders this object using given templates
+ *
+ * @param Templates $templates Collection/storage of templates that will be required while rendering this and
+ * related objects, e.g. children of this object
+ * @return string
+ */
+ public function render(Templates $templates): string;
+}
diff --git a/src/Exception/Base/UnknownTypeException.php b/src/Exception/Base/UnknownTypeException.php
index 43abda2..7354524 100644
--- a/src/Exception/Base/UnknownTypeException.php
+++ b/src/Exception/Base/UnknownTypeException.php
@@ -28,13 +28,13 @@ abstract class UnknownTypeException extends Exception
* @param string $typeName Name of the something
* @return UnknownTypeException
*/
- public static function create($unknownType, BaseType $typeInstance, $typeName)
+ public static function create($unknownType, BaseType $typeInstance, string $typeName): UnknownTypeException
{
$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.';
+ .' of these types: %s.';
$allTypes = $typeInstance->getAll();
- $types = Arrays::values2string($allTypes, '', ', ');
+ $types = Arrays::values2string($allTypes, '', ', ') ?? '[types not found]';
$message = sprintf($template, $unknownType, $typeName, $types);
return new static($message);
diff --git a/src/Exception/Bundle/IncorrectBundleNameException.php b/src/Exception/Bundle/IncorrectBundleNameException.php
index 2c34199..6e7506a 100644
--- a/src/Exception/Bundle/IncorrectBundleNameException.php
+++ b/src/Exception/Bundle/IncorrectBundleNameException.php
@@ -27,7 +27,7 @@ class IncorrectBundleNameException extends Exception
public static function create($bundleName)
{
$template = 'Name of bundle \'%s\' is incorrect. It should start with big letter and end with "Bundle". Is'
- . ' there everything ok?';
+ .' there everything ok?';
$message = sprintf($template, $bundleName);
diff --git a/src/Exception/File/EmptyFileException.php b/src/Exception/File/EmptyFileException.php
index 4ff9441..fea0600 100644
--- a/src/Exception/File/EmptyFileException.php
+++ b/src/Exception/File/EmptyFileException.php
@@ -8,13 +8,15 @@
namespace Meritoo\Common\Exception\File;
+use Exception;
+
/**
* An exception used while file with given path is empty (has no content)
*
* @author Meritoo
* @copyright Meritoo
*/
-class EmptyFileException extends \Exception
+class EmptyFileException extends Exception
{
/**
* Creates exception
diff --git a/src/Exception/File/EmptyFilePathException.php b/src/Exception/File/EmptyFilePathException.php
index 33333f5..51ca44d 100644
--- a/src/Exception/File/EmptyFilePathException.php
+++ b/src/Exception/File/EmptyFilePathException.php
@@ -8,18 +8,22 @@
namespace Meritoo\Common\Exception\File;
+use Exception;
+
/**
* An exception used while path of given file is empty
*
* @author Meritoo
* @copyright Meritoo
*/
-class EmptyFilePathException extends \Exception
+class EmptyFilePathException extends Exception
{
/**
* Creates exception
+ *
+ * @return EmptyFilePathException
*/
- public static function create()
+ public static function create(): EmptyFilePathException
{
return new static('Path of the file is empty. Did you provide path of proper file?');
}
diff --git a/src/Exception/File/NotExistingFileException.php b/src/Exception/File/NotExistingFileException.php
index c64a8f8..6ddc2aa 100644
--- a/src/Exception/File/NotExistingFileException.php
+++ b/src/Exception/File/NotExistingFileException.php
@@ -8,13 +8,15 @@
namespace Meritoo\Common\Exception\File;
+use Exception;
+
/**
* An exception used while file with given path does not exist
*
* @author Meritoo
* @copyright Meritoo
*/
-class NotExistingFileException extends \Exception
+class NotExistingFileException extends Exception
{
/**
* Creates exception
diff --git a/src/Exception/Reflection/CannotResolveClassNameException.php b/src/Exception/Reflection/CannotResolveClassNameException.php
index dee9dde..faaf4d0 100644
--- a/src/Exception/Reflection/CannotResolveClassNameException.php
+++ b/src/Exception/Reflection/CannotResolveClassNameException.php
@@ -21,13 +21,12 @@ class CannotResolveClassNameException extends Exception
/**
* Creates exception
*
- * @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.
+ * @param string $source Source of name of the class or trait
+ * @param bool $forClass (optional) If is set to true, message of this exception for class is prepared. Otherwise
+ * - for trait.
* @return CannotResolveClassNameException
*/
- public static function create($source, $forClass = true)
+ public static function create(string $source, bool $forClass = true): CannotResolveClassNameException
{
$forWho = 'trait';
$value = '';
@@ -37,7 +36,7 @@ class CannotResolveClassNameException extends Exception
}
if (is_scalar($source)) {
- $value = sprintf(' %s', (string)$source);
+ $value = sprintf(' %s', $source);
}
$template = 'Name of %s from given \'%s\'%s cannot be resolved. Is there everything ok?';
diff --git a/src/Exception/Reflection/ClassWithoutConstructorException.php b/src/Exception/Reflection/ClassWithoutConstructorException.php
new file mode 100644
index 0000000..b67a44a
--- /dev/null
+++ b/src/Exception/Reflection/ClassWithoutConstructorException.php
@@ -0,0 +1,34 @@
+
+ * @copyright Meritoo
+ */
+class ClassWithoutConstructorException extends Exception
+{
+ /**
+ * Creates exception
+ *
+ * @param string $className Fully-qualified name of class that hasn't constructor
+ * @return ClassWithoutConstructorException
+ */
+ public static function create(string $className): ClassWithoutConstructorException
+ {
+ $template = 'Oops, class \'%s\' hasn\'t constructor. Did you use proper class?';
+ $message = sprintf($template, $className);
+
+ return new static($message);
+ }
+}
diff --git a/src/Exception/Reflection/MissingChildClassesException.php b/src/Exception/Reflection/MissingChildClassesException.php
index 27183ff..9a367b3 100644
--- a/src/Exception/Reflection/MissingChildClassesException.php
+++ b/src/Exception/Reflection/MissingChildClassesException.php
@@ -26,12 +26,12 @@ class MissingChildClassesException extends Exception
* strings, object or string.
* @return MissingChildClassesException
*/
- public static function create($parentClass)
+ public static function create($parentClass): MissingChildClassesException
{
$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?';
+ .' class), but the child classes are missing. Did you forget to extend this class?';
- $parentClassName = Reflection::getClassName($parentClass);
+ $parentClassName = Reflection::getClassName($parentClass) ?? '[unknown class]';
$message = sprintf($template, $parentClassName);
return new static($message);
diff --git a/src/Exception/Reflection/NotExistingPropertyException.php b/src/Exception/Reflection/NotExistingPropertyException.php
index 4b7484f..c5b10ff 100644
--- a/src/Exception/Reflection/NotExistingPropertyException.php
+++ b/src/Exception/Reflection/NotExistingPropertyException.php
@@ -8,22 +8,24 @@
namespace Meritoo\Common\Exception\Reflection;
+use Exception;
+
/**
* An exception used while property does not exist in instance of class
*
* @author Meritoo
* @copyright Meritoo
*/
-class NotExistingPropertyException extends \Exception
+class NotExistingPropertyException extends Exception
{
/**
* Creates exception
*
- * @param mixed $object Object that should contains given property
- * @param string $property Name of the property
+ * @param mixed $object Object that should contains given property
+ * @param null|string $property Name of the property
* @return NotExistingPropertyException
*/
- public static function create($object, $property)
+ public static function create($object, ?string $property): NotExistingPropertyException
{
$template = 'Property \'%s\' does not exist in instance of class \'%s\'. Did you use proper name of property?';
$message = sprintf($template, $property, get_class($object));
diff --git a/src/Exception/Reflection/TooManyChildClassesException.php b/src/Exception/Reflection/TooManyChildClassesException.php
index f06dab2..dea2970 100644
--- a/src/Exception/Reflection/TooManyChildClassesException.php
+++ b/src/Exception/Reflection/TooManyChildClassesException.php
@@ -27,12 +27,12 @@ class TooManyChildClassesException extends Exception
* @param array $childClasses Child classes
* @return TooManyChildClassesException
*/
- public static function create($parentClass, array $childClasses)
+ public static function create($parentClass, array $childClasses): TooManyChildClassesException
{
$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?";
+ ." class was found:\n- %s\n\nWhy did you create more than one classes that extend '%s' class?";
- $parentClassName = Reflection::getClassName($parentClass);
+ $parentClassName = Reflection::getClassName($parentClass) ?? '[unknown class]';
$message = sprintf($template, $parentClassName, implode("\n- ", $childClasses), $parentClassName);
return new static($message);
diff --git a/src/Exception/Regex/IncorrectColorHexLengthException.php b/src/Exception/Regex/IncorrectColorHexLengthException.php
index 86af0a3..9dcca58 100644
--- a/src/Exception/Regex/IncorrectColorHexLengthException.php
+++ b/src/Exception/Regex/IncorrectColorHexLengthException.php
@@ -8,13 +8,15 @@
namespace Meritoo\Common\Exception\Regex;
+use Exception;
+
/**
* An exception used while length of given hexadecimal value of color is incorrect
*
* @author Meritoo
* @copyright Meritoo
*/
-class IncorrectColorHexLengthException extends \Exception
+class IncorrectColorHexLengthException extends Exception
{
/**
* Creates exception
@@ -25,7 +27,7 @@ class IncorrectColorHexLengthException extends \Exception
public static function create($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?';
+ .' Is there everything ok?';
$message = sprintf($template, $color, strlen($color));
diff --git a/src/Exception/Regex/InvalidColorHexValueException.php b/src/Exception/Regex/InvalidColorHexValueException.php
index 69b1682..1523be0 100644
--- a/src/Exception/Regex/InvalidColorHexValueException.php
+++ b/src/Exception/Regex/InvalidColorHexValueException.php
@@ -8,13 +8,15 @@
namespace Meritoo\Common\Exception\Regex;
+use Exception;
+
/**
* An exception used while given hexadecimal value of color is invalid
*
* @author Meritoo
* @copyright Meritoo
*/
-class InvalidColorHexValueException extends \Exception
+class InvalidColorHexValueException extends Exception
{
/**
* Creates exception
diff --git a/src/Exception/Regex/InvalidHtmlAttributesException.php b/src/Exception/Regex/InvalidHtmlAttributesException.php
index cac3480..4504fd2 100644
--- a/src/Exception/Regex/InvalidHtmlAttributesException.php
+++ b/src/Exception/Regex/InvalidHtmlAttributesException.php
@@ -8,13 +8,15 @@
namespace Meritoo\Common\Exception\Regex;
+use Exception;
+
/**
* An exception used while html attributes are invalid
*
* @author Meritoo
* @copyright Meritoo
*/
-class InvalidHtmlAttributesException extends \Exception
+class InvalidHtmlAttributesException extends Exception
{
/**
* Creates exception
diff --git a/src/Exception/Regex/InvalidUrlException.php b/src/Exception/Regex/InvalidUrlException.php
index 080fcf7..4d47d1d 100644
--- a/src/Exception/Regex/InvalidUrlException.php
+++ b/src/Exception/Regex/InvalidUrlException.php
@@ -8,13 +8,15 @@
namespace Meritoo\Common\Exception\Regex;
+use Exception;
+
/**
* An exception used while url is invalid
*
* @author Meritoo
* @copyright Meritoo
*/
-class InvalidUrlException extends \Exception
+class InvalidUrlException extends Exception
{
/**
* Creates exception
diff --git a/src/Exception/Type/UnknownDatePartTypeException.php b/src/Exception/Type/UnknownDatePartTypeException.php
index 8155a50..29e1d5a 100644
--- a/src/Exception/Type/UnknownDatePartTypeException.php
+++ b/src/Exception/Type/UnknownDatePartTypeException.php
@@ -26,11 +26,8 @@ class UnknownDatePartTypeException extends UnknownTypeException
* @param string $value Incorrect value
* @return UnknownDatePartTypeException
*/
- public static function createException($unknownDatePart, $value)
+ public static function createException(string $unknownDatePart, string $value): UnknownDatePartTypeException
{
- /* @var UnknownDatePartTypeException $exception */
- $exception = parent::create($unknownDatePart, new DatePartType(), sprintf('date part (with value %s)', $value));
-
- return $exception;
+ return parent::create($unknownDatePart, new DatePartType(), sprintf('date part (with value %s)', $value));
}
}
diff --git a/src/Exception/Type/UnknownOopVisibilityTypeException.php b/src/Exception/Type/UnknownOopVisibilityTypeException.php
index f8eb21d..6463362 100644
--- a/src/Exception/Type/UnknownOopVisibilityTypeException.php
+++ b/src/Exception/Type/UnknownOopVisibilityTypeException.php
@@ -25,11 +25,8 @@ class UnknownOopVisibilityTypeException extends UnknownTypeException
* @param string $unknownType Unknown visibility of a property, a method or (as of PHP 7.1.0) a constant
* @return UnknownOopVisibilityTypeException
*/
- public static function createException($unknownType)
+ public static function createException(string $unknownType): UnknownOopVisibilityTypeException
{
- /* @var UnknownOopVisibilityTypeException $exception */
- $exception = parent::create($unknownType, new OopVisibilityType(), 'OOP-related visibility');
-
- return $exception;
+ return parent::create($unknownType, new OopVisibilityType(), 'OOP-related visibility');
}
}
diff --git a/src/Exception/ValueObject/InvalidSizeDimensionsException.php b/src/Exception/ValueObject/InvalidSizeDimensionsException.php
index 8f922e1..15f8838 100644
--- a/src/Exception/ValueObject/InvalidSizeDimensionsException.php
+++ b/src/Exception/ValueObject/InvalidSizeDimensionsException.php
@@ -8,13 +8,15 @@
namespace Meritoo\Common\Exception\ValueObject;
+use Exception;
+
/**
* An exception used while dimensions of size, passed to the instance of Size class, are invalid
*
* @author Meritoo
* @copyright Meritoo
*/
-class InvalidSizeDimensionsException extends \Exception
+class InvalidSizeDimensionsException extends Exception
{
/**
* Creates exception
diff --git a/src/Exception/ValueObject/Template/InvalidContentException.php b/src/Exception/ValueObject/Template/InvalidContentException.php
new file mode 100644
index 0000000..c9fb140
--- /dev/null
+++ b/src/Exception/ValueObject/Template/InvalidContentException.php
@@ -0,0 +1,36 @@
+
+ * @copyright Meritoo
+ */
+class InvalidContentException extends Exception
+{
+ /**
+ * Creates an exception
+ *
+ * @param string $content Invalid content of template
+ * @return InvalidContentException
+ */
+ public static function create(string $content): InvalidContentException
+ {
+ $template = 'Content of template \'%s\' is invalid. Did you use string with 1 placeholder at least?';
+ $message = sprintf($template, $content);
+
+ return new static($message);
+ }
+}
diff --git a/src/Exception/ValueObject/Template/MissingPlaceholdersInValuesException.php b/src/Exception/ValueObject/Template/MissingPlaceholdersInValuesException.php
new file mode 100644
index 0000000..af93d18
--- /dev/null
+++ b/src/Exception/ValueObject/Template/MissingPlaceholdersInValuesException.php
@@ -0,0 +1,36 @@
+
+ * @copyright Meritoo
+ */
+class MissingPlaceholdersInValuesException extends Exception
+{
+ /**
+ * Creates an exception
+ *
+ * @param string $content Content of template
+ * @param array $missingPlaceholders Missing placeholders in provided values, iow. placeholders without values
+ * @return MissingPlaceholdersInValuesException
+ */
+ public static function create(string $content, array $missingPlaceholders): MissingPlaceholdersInValuesException
+ {
+ $template = 'Cannot fill template \'%s\', because of missing values for placeholder(s): %s. Did you provide all'
+ .' required values?';
+ $message = sprintf($template, $content, implode(', ', $missingPlaceholders));
+
+ return new static($message);
+ }
+}
diff --git a/src/Exception/ValueObject/Template/TemplateNotFoundException.php b/src/Exception/ValueObject/Template/TemplateNotFoundException.php
new file mode 100644
index 0000000..aee1843
--- /dev/null
+++ b/src/Exception/ValueObject/Template/TemplateNotFoundException.php
@@ -0,0 +1,36 @@
+
+ * @copyright Meritoo
+ */
+class TemplateNotFoundException extends Exception
+{
+ /**
+ * Creates the exception
+ *
+ * @param string $index Index that should contain template, but it was not found
+ * @return TemplateNotFoundException
+ */
+ public static function create(string $index): TemplateNotFoundException
+ {
+ $template = 'Template with \'%s\' index was not found. Did you provide all required templates?';
+ $message = sprintf($template, $index);
+
+ return new static($message);
+ }
+}
diff --git a/src/Traits/Collection/ArrayAccessTrait.php b/src/Traits/Collection/ArrayAccessTrait.php
deleted file mode 100644
index ddb8527..0000000
--- a/src/Traits/Collection/ArrayAccessTrait.php
+++ /dev/null
@@ -1,67 +0,0 @@
-
- * @copyright Meritoo
- */
-trait ArrayAccessTrait
-{
- /**
- * {@inheritdoc}
- */
- public function offsetExists($offset)
- {
- return $this->exists($offset);
- }
-
- /**
- * {@inheritdoc}
- */
- public function offsetGet($offset)
- {
- if ($this->exists($offset)) {
- return $this->elements[$offset];
- }
-
- return null;
- }
-
- /**
- * {@inheritdoc}
- */
- public function offsetSet($offset, $value)
- {
- $this->elements[$offset] = $value;
- }
-
- /**
- * {@inheritdoc}
- */
- public function offsetUnset($offset)
- {
- if ($this->exists($offset)) {
- unset($this->elements[$offset]);
- }
- }
-
- /**
- * 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/Traits/Collection/MainTrait.php b/src/Traits/Collection/MainTrait.php
deleted file mode 100644
index 8c401fa..0000000
--- a/src/Traits/Collection/MainTrait.php
+++ /dev/null
@@ -1,215 +0,0 @@
-
- * @copyright Meritoo
- */
-trait MainTrait
-{
- /**
- * The elements of collection
- *
- * @var array
- */
- private $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 || '' === $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) {
- $this->add($element, $index);
- continue;
- }
-
- $this->add($element);
- }
- }
-
- 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 element with given index
- *
- * @param mixed $index Index / key of the element
- * @return mixed|null
- */
- public function getByIndex($index)
- {
- if (isset($this->elements[$index])) {
- return $this->elements[$index];
- }
-
- return null;
- }
-
- /**
- * Returns representation of object as array
- *
- * @return array
- */
- public function toArray()
- {
- return $this->elements;
- }
-}
diff --git a/src/Traits/CollectionTrait.php b/src/Traits/CollectionTrait.php
deleted file mode 100644
index 8cb0cad..0000000
--- a/src/Traits/CollectionTrait.php
+++ /dev/null
@@ -1,28 +0,0 @@
-
- * @copyright Meritoo
- */
-trait CollectionTrait
-{
- use MainTrait;
- use CountableTrait;
- use ArrayAccessTrait;
- use IteratorAggregateTrait;
-}
diff --git a/src/Traits/CssSelector/FormCssSelector.php b/src/Traits/CssSelector/FormCssSelector.php
index 964ce71..9766814 100644
--- a/src/Traits/CssSelector/FormCssSelector.php
+++ b/src/Traits/CssSelector/FormCssSelector.php
@@ -16,6 +16,24 @@ namespace Meritoo\Common\Traits\CssSelector;
*/
trait FormCssSelector
{
+ /**
+ * Returns selector of field-set using index/position of the field-set
+ *
+ * @param string $formName Name of form (value of the "name" attribute)
+ * @param int $fieldSetIndex Index/Position of the field-set
+ * @return string
+ */
+ public static function getFieldSetByIndexSelector($formName, $fieldSetIndex)
+ {
+ $formSelector = static::getFormByNameSelector($formName);
+
+ if (empty($formSelector) || 0 > $fieldSetIndex) {
+ return '';
+ }
+
+ return sprintf('%s fieldset:nth-of-type(%d)', $formSelector, $fieldSetIndex);
+ }
+
/**
* Returns selector of form based on its name
*
@@ -33,25 +51,6 @@ trait FormCssSelector
return sprintf('form[name="%s"]', $formName);
}
- /**
- * Returns selector of the input field based on its name
- *
- * @param string $formName Name of form (value of the "name" attribute)
- * @param string $fieldName Name of field (value of the "name" attribute)
- * @return string
- */
- public static function getInputByNameSelector($formName, $fieldName)
- {
- $formSelector = static::getFormByNameSelector($formName);
- $fieldName = trim($fieldName);
-
- if (empty($formSelector) || empty($fieldName)) {
- return '';
- }
-
- return sprintf('%s input[name="%s"]', $formSelector, $fieldName);
- }
-
/**
* Returns selector of the input field based on its ID
*
@@ -71,6 +70,25 @@ trait FormCssSelector
return sprintf('%s input#%s', $formSelector, $fieldId);
}
+ /**
+ * Returns selector of the input field based on its name
+ *
+ * @param string $formName Name of form (value of the "name" attribute)
+ * @param string $fieldName Name of field (value of the "name" attribute)
+ * @return string
+ */
+ public static function getInputByNameSelector($formName, $fieldName)
+ {
+ $formSelector = static::getFormByNameSelector($formName);
+ $fieldName = trim($fieldName);
+
+ if (empty($formSelector) || empty($fieldName)) {
+ return '';
+ }
+
+ return sprintf('%s input[name="%s"]', $formSelector, $fieldName);
+ }
+
/**
* Returns selector of label
*
@@ -89,22 +107,4 @@ trait FormCssSelector
return sprintf('%s label[for="%s"]', $formSelector, $fieldId);
}
-
- /**
- * Returns selector of field-set using index/position of the field-set
- *
- * @param string $formName Name of form (value of the "name" attribute)
- * @param int $fieldSetIndex Index/Position of the field-set
- * @return string
- */
- public static function getFieldSetByIndexSelector($formName, $fieldSetIndex)
- {
- $formSelector = static::getFormByNameSelector($formName);
-
- if (empty($formSelector) || 0 > $fieldSetIndex) {
- return '';
- }
-
- return sprintf('%s fieldset:nth-of-type(%d)', $formSelector, $fieldSetIndex);
- }
}
diff --git a/src/Traits/Test/Base/BaseTestCaseTrait.php b/src/Traits/Test/Base/BaseTestCaseTrait.php
index 74eea20..6ed450b 100644
--- a/src/Traits/Test/Base/BaseTestCaseTrait.php
+++ b/src/Traits/Test/Base/BaseTestCaseTrait.php
@@ -6,15 +6,19 @@
* file that was distributed with this source code.
*/
+declare(strict_types=1);
+
namespace Meritoo\Common\Traits\Test\Base;
use DateTime;
use Generator;
+use Meritoo\Common\Exception\Reflection\ClassWithoutConstructorException;
use Meritoo\Common\Exception\Type\UnknownOopVisibilityTypeException;
use Meritoo\Common\Type\OopVisibilityType;
use Meritoo\Common\Utilities\Miscellaneous;
use ReflectionClass;
use ReflectionMethod;
+use RuntimeException;
use stdClass;
/**
@@ -32,44 +36,15 @@ trait BaseTestCaseTrait
*/
private static $testsDataDirPath = 'data/tests';
- /**
- * Provides an empty value
- *
- * @return Generator
- */
- public function provideEmptyValue()
- {
- yield[''];
- yield[' '];
- yield[null];
- yield[0];
- yield[false];
- yield[[]];
- }
-
- /**
- * Provides an empty scalar value
- *
- * @return Generator
- */
- public function provideEmptyScalarValue()
- {
- yield[''];
- yield[' '];
- yield[null];
- yield[0];
- yield[false];
- }
-
/**
* Provides boolean value
*
* @return Generator
*/
- public function provideBooleanValue()
+ public function provideBooleanValue(): ?Generator
{
- yield[false];
- yield[true];
+ yield [false];
+ yield [true];
}
/**
@@ -77,12 +52,12 @@ trait BaseTestCaseTrait
*
* @return Generator
*/
- public function provideDateTimeInstance()
+ public function provideDateTimeInstance(): ?Generator
{
- yield[new DateTime()];
- yield[new DateTime('yesterday')];
- yield[new DateTime('now')];
- yield[new DateTime('tomorrow')];
+ yield [new DateTime()];
+ yield [new DateTime('yesterday')];
+ yield [new DateTime('now')];
+ yield [new DateTime('tomorrow')];
}
/**
@@ -90,31 +65,48 @@ trait BaseTestCaseTrait
*
* @return Generator
*/
- public function provideDateTimeRelativeFormat()
+ public function provideDateTimeRelativeFormat(): ?Generator
{
- 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'];
+ 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"
+ * Provides an empty scalar value
*
* @return Generator
*/
- public function provideNotExistingFilePath()
+ public function provideEmptyScalarValue(): ?Generator
{
- yield['lets-test.doc'];
- yield['lorem/ipsum.jpg'];
- yield['surprise/me/one/more/time.txt'];
+ yield [''];
+ yield [' '];
+ yield [null];
+ yield [0];
+ yield [false];
+ }
+
+ /**
+ * Provides an empty value
+ *
+ * @return Generator
+ */
+ public function provideEmptyValue(): ?Generator
+ {
+ yield [''];
+ yield [' '];
+ yield [null];
+ yield [0];
+ yield [false];
+ yield [[]];
}
/**
@@ -122,19 +114,114 @@ trait BaseTestCaseTrait
*
* @return Generator
*/
- public function provideNonScalarValue()
+ public function provideNonScalarValue(): ?Generator
{
- yield[
- [],
- ];
+ yield [[]];
+ yield [null];
+ yield [new stdClass()];
+ }
- yield[
- null,
- ];
+ /**
+ * Provides path of not existing file, e.g. "lorem/ipsum.jpg"
+ *
+ * @return Generator
+ */
+ public function provideNotExistingFilePath(): ?Generator
+ {
+ yield ['lets-test.doc'];
+ yield ['lorem/ipsum.jpg'];
+ yield ['surprise/me/one/more/time.txt'];
+ }
- yield[
- new stdClass(),
- ];
+ /**
+ * Verifies visibility and arguments of class constructor
+ *
+ * @param string $className Fully-qualified name 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 ClassWithoutConstructorException
+ */
+ protected static function assertConstructorVisibilityAndArguments(
+ string $className,
+ string $visibilityType,
+ int $argumentsCount = 0,
+ int $requiredArgumentsCount = 0
+ ): void {
+ $reflection = new ReflectionClass($className);
+ $method = $reflection->getConstructor();
+
+ if (null === $method) {
+ throw ClassWithoutConstructorException::create($className);
+ }
+
+ static::assertMethodVisibility($method, $visibilityType);
+ static::assertMethodArgumentsCount($method, $argumentsCount, $requiredArgumentsCount);
+ }
+
+ /**
+ * Asserts that class with given namespace has no constructor
+ *
+ * @param string $className Fully-qualified name of class that contains constructor to verify
+ */
+ protected static function assertHasNoConstructor(string $className): void
+ {
+ $reflection = new ReflectionClass($className);
+ $constructor = $reflection->getConstructor();
+
+ static::assertNull($constructor);
+ }
+
+ /**
+ * Verifies count of method's arguments
+ *
+ * @param ReflectionMethod $method Name of method or just the method to verify
+ * @param int $argumentsCount (optional) Expected count/amount of arguments of the verified method
+ * @param int $requiredCount (optional) Expected count/amount of required arguments of the verified
+ * method
+ * @throws RuntimeException
+ */
+ protected static function assertMethodArgumentsCount(
+ ReflectionMethod $method,
+ int $argumentsCount = 0,
+ int $requiredCount = 0
+ ): void {
+ static::assertSame($argumentsCount, $method->getNumberOfParameters());
+ static::assertSame($requiredCount, $method->getNumberOfRequiredParameters());
+ }
+
+ /**
+ * Verifies visibility of method
+ *
+ * @param ReflectionMethod $method Name of method or just the method to verify
+ * @param string $visibilityType Expected visibility of verified method. One of OopVisibilityType
+ * class constants.
+ * @throws UnknownOopVisibilityTypeException
+ * @throws RuntimeException
+ */
+ protected static function assertMethodVisibility(ReflectionMethod $method, string $visibilityType): void
+ {
+ // Type of visibility is not correct?
+ if (!OopVisibilityType::isCorrectType($visibilityType)) {
+ throw UnknownOopVisibilityTypeException::createException($visibilityType);
+ }
+
+ 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;
+ }
}
/**
@@ -145,7 +232,7 @@ trait BaseTestCaseTrait
* @param string $directoryPath (optional) Path of directory containing the file
* @return string
*/
- public function getFilePathForTesting($fileName, $directoryPath = '')
+ protected function getFilePathForTesting(string $fileName, string $directoryPath = ''): string
{
$rootPath = Miscellaneous::getProjectRootPath();
@@ -159,118 +246,12 @@ trait BaseTestCaseTrait
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
- */
- protected static function assertConstructorVisibilityAndArguments(
- $classNamespace,
- $visibilityType,
- $argumentsCount = 0,
- $requiredArgumentsCount = 0
- ) {
- /*
- * Let's grab the constructor
- */
- $reflection = new ReflectionClass($classNamespace);
- $method = $reflection->getConstructor();
-
- 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)
+ protected static function setTestsDataDirPath(string $testsDataDirPath): void
{
static::$testsDataDirPath = $testsDataDirPath;
}
diff --git a/src/Traits/Test/Base/BaseTypeTestCaseTrait.php b/src/Traits/Test/Base/BaseTypeTestCaseTrait.php
index 5633c8d..7c1d85f 100644
--- a/src/Traits/Test/Base/BaseTypeTestCaseTrait.php
+++ b/src/Traits/Test/Base/BaseTypeTestCaseTrait.php
@@ -6,6 +6,8 @@
* file that was distributed with this source code.
*/
+declare(strict_types=1);
+
namespace Meritoo\Common\Traits\Test\Base;
use Generator;
@@ -19,10 +21,17 @@ use Meritoo\Common\Type\Base\BaseType;
*/
trait BaseTypeTestCaseTrait
{
+ /**
+ * Provides type to verify and information if it's correct
+ *
+ * @return Generator
+ */
+ abstract public function provideTypeToVerify(): Generator;
+
/**
* Verifies availability of all types
*/
- public function testAvailabilityOfAllTypes()
+ public function testAvailabilityOfAllTypes(): void
{
$available = $this->getTestedTypeInstance()->getAll();
$all = $this->getAllExpectedTypes();
@@ -33,34 +42,27 @@ trait BaseTypeTestCaseTrait
/**
* 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
+ * @param bool $isCorrect Information if processed type is correct
+ * @param bool $expected Expected information if processed type is correct
*
* @dataProvider provideTypeToVerify
*/
- public function testIfGivenTypeIsCorrect($type, $expected)
+ public function testIfGivenTypeIsCorrect(bool $isCorrect, bool $expected): void
{
- static::assertEquals($expected, $this->getTestedTypeInstance()->isCorrectType($type));
+ static::assertEquals($expected, $isCorrect);
}
- /**
- * 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();
+ abstract protected function getAllExpectedTypes(): array;
+
+ /**
+ * Returns instance of the tested type
+ *
+ * @return BaseType
+ */
+ abstract protected function getTestedTypeInstance(): BaseType;
}
diff --git a/src/Traits/ValueObject/HumanTrait.php b/src/Traits/ValueObject/HumanTrait.php
index b8b7cd8..71d586a 100644
--- a/src/Traits/ValueObject/HumanTrait.php
+++ b/src/Traits/ValueObject/HumanTrait.php
@@ -6,8 +6,12 @@
* file that was distributed with this source code.
*/
+declare(strict_types=1);
+
namespace Meritoo\Common\Traits\ValueObject;
+use DateTime;
+
/**
* Methods and properties related to human
*
@@ -33,26 +37,26 @@ trait HumanTrait
/**
* Email address
*
- * @var string
+ * @var null|string
*/
protected $email;
/**
* Birth date
*
- * @var \DateTime
+ * @var null|DateTime
*/
protected $birthDate;
/**
* Class constructor
*
- * @param string $firstName First name
- * @param string $lastName Last name
- * @param string $email (optional) Email address
- * @param \DateTime $birthDate (optional) Birth date
+ * @param string $firstName First name
+ * @param string $lastName Last name
+ * @param null|string $email (optional) Email address. Default: null.
+ * @param null|DateTime $birthDate (optional) Birth date. Default: null.
*/
- public function __construct($firstName, $lastName, $email = null, \DateTime $birthDate = null)
+ public function __construct(string $firstName, string $lastName, ?string $email = null, ?DateTime $birthDate = null)
{
$this->firstName = $firstName;
$this->lastName = $lastName;
@@ -68,12 +72,34 @@ trait HumanTrait
public function __toString()
{
$template = '%s';
+ $email = '';
if ('' !== $this->email && null !== $this->email) {
$template .= ' <%s>';
+ $email = $this->email;
}
- return sprintf($template, $this->getFullName(), $this->email);
+ return sprintf($template, $this->getFullName(), $email);
+ }
+
+ /**
+ * Returns birth date
+ *
+ * @return null|DateTime
+ */
+ public function getBirthDate(): ?DateTime
+ {
+ return $this->birthDate;
+ }
+
+ /**
+ * Returns email address
+ *
+ * @return null|string
+ */
+ public function getEmail(): ?string
+ {
+ return $this->email;
}
/**
@@ -81,48 +107,19 @@ trait HumanTrait
*
* @return string
*/
- public function getFirstName()
+ public function getFirstName(): string
{
return $this->firstName;
}
- /**
- * Returns last name
- *
- * @return string
- */
- public function getLastName()
- {
- return $this->lastName;
- }
-
- /**
- * Returns email address
- *
- * @return string|null
- */
- public function getEmail()
- {
- return $this->email;
- }
-
- /**
- * Returns birth date
- *
- * @return \DateTime|null
- */
- public function getBirthDate()
- {
- return $this->birthDate;
- }
-
/**
* Returns the full name
*
- * @param bool $firstNameFirst (optional) If is set to true, first name is the first part. Otherwise - last name.
+ * @param bool $firstNameFirst (optional) If is set to true, first name is the first part (default behaviour).
+ * Otherwise - name.
* @return string
*/
- public function getFullName($firstNameFirst = true)
+ public function getFullName(bool $firstNameFirst = true): string
{
$beginning = $this->lastName;
$finish = $this->firstName;
@@ -134,4 +131,14 @@ trait HumanTrait
return trim(sprintf('%s %s', $beginning, $finish));
}
+
+ /**
+ * Returns last name
+ *
+ * @return string
+ */
+ public function getLastName(): string
+ {
+ return $this->lastName;
+ }
}
diff --git a/src/Type/Base/BaseType.php b/src/Type/Base/BaseType.php
index ec8dafa..26706d4 100644
--- a/src/Type/Base/BaseType.php
+++ b/src/Type/Base/BaseType.php
@@ -22,7 +22,7 @@ abstract class BaseType
/**
* All types
*
- * @var array
+ * @var null|array
*/
private $all;
@@ -31,7 +31,7 @@ abstract class BaseType
*
* @return array
*/
- public function getAll()
+ public function getAll(): array
{
if (null === $this->all) {
$this->all = Reflection::getConstants($this);
@@ -43,11 +43,11 @@ abstract class BaseType
/**
* Returns information if given type is correct
*
- * @param mixed $type The type to check
+ * @param null|string $type The type to check
* @return bool
*/
- public function isCorrectType($type)
+ public static function isCorrectType(?string $type): bool
{
- return in_array($type, $this->getAll(), true);
+ return in_array($type, (new static())->getAll());
}
}
diff --git a/src/Type/DatePartType.php b/src/Type/DatePartType.php
index dfa91c4..e6d8b2b 100644
--- a/src/Type/DatePartType.php
+++ b/src/Type/DatePartType.php
@@ -23,40 +23,40 @@ class DatePartType extends BaseType
*
* @var string
*/
- const DAY = 'day';
+ public const DAY = 'day';
/**
* The "hour" date part
*
* @var string
*/
- const HOUR = 'hour';
+ public const HOUR = 'hour';
/**
* The "minute" date part
*
* @var string
*/
- const MINUTE = 'minute';
+ public const MINUTE = 'minute';
/**
* The "month" date part
*
* @var string
*/
- const MONTH = 'month';
+ public const MONTH = 'month';
/**
* The "second" date part
*
* @var string
*/
- const SECOND = 'second';
+ public const SECOND = 'second';
/**
* The "year" date part
*
* @var string
*/
- const YEAR = 'year';
+ public const YEAR = 'year';
}
diff --git a/src/Type/DatePeriod.php b/src/Type/DatePeriod.php
index abfe4db..7fb1fc0 100644
--- a/src/Type/DatePeriod.php
+++ b/src/Type/DatePeriod.php
@@ -24,113 +24,134 @@ class DatePeriod extends BaseType
/**
* The period constant: last month
*
- * @var int
+ * @var string
*/
- const LAST_MONTH = 4;
+ public const LAST_MONTH = '4';
/**
* The period constant: last week
*
- * @var int
+ * @var string
*/
- const LAST_WEEK = 1;
+ public const LAST_WEEK = '1';
/**
* The period constant: last year
*
- * @var int
+ * @var string
*/
- const LAST_YEAR = 7;
+ public const LAST_YEAR = '7';
/**
* The period constant: next month
*
- * @var int
+ * @var string
*/
- const NEXT_MONTH = 6;
+ public const NEXT_MONTH = '6';
/**
* The period constant: next week
*
- * @var int
+ * @var string
*/
- const NEXT_WEEK = 3;
+ public const NEXT_WEEK = '3';
/**
* The period constant: next year
*
- * @var int
+ * @var string
*/
- const NEXT_YEAR = 9;
+ public const NEXT_YEAR = '9';
/**
* The period constant: this month
*
- * @var int
+ * @var string
*/
- const THIS_MONTH = 5;
+ public const THIS_MONTH = '5';
/**
* The period constant: this week
*
- * @var int
+ * @var string
*/
- const THIS_WEEK = 2;
+ public const THIS_WEEK = '2';
/**
* The period constant: this year
*
- * @var int
+ * @var string
*/
- const THIS_YEAR = 8;
+ public const THIS_YEAR = '8';
/**
* The start date of period
*
- * @var DateTime
+ * @var null|DateTime
*/
private $startDate;
/**
* The end date of period
*
- * @var DateTime
+ * @var null|DateTime
*/
private $endDate;
/**
* Class constructor
*
- * @param DateTime $startDate (optional) The start date of period
- * @param DateTime $endDate (optional) The end date of period
+ * @param null|DateTime $startDate (optional) The start date of period
+ * @param null|DateTime $endDate (optional) The end date of period
*/
- public function __construct(DateTime $startDate = null, DateTime $endDate = null)
+ public function __construct(?DateTime $startDate = null, ?DateTime $endDate = null)
{
$this->startDate = $startDate;
$this->endDate = $endDate;
}
+ /**
+ * Returns the end date of period
+ *
+ * @return null|DateTime
+ */
+ public function getEndDate(): ?DateTime
+ {
+ return $this->endDate;
+ }
+
+ /**
+ * Sets the end date of period
+ *
+ * @param null|DateTime $endDate (optional) The end date of period. Default: null.
+ * @return $this
+ */
+ public function setEndDate(?DateTime $endDate = null): self
+ {
+ $this->endDate = $endDate;
+
+ return $this;
+ }
+
/**
* 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.
+ * @param bool $startDate (optional) If is set to true, start date will be formatted (default behaviour).
+ * Otherwise - end date.
* @return string
*/
- public function getFormattedDate($format, $startDate = true)
+ public function getFormattedDate(string $format, bool $startDate = true): string
{
$date = $this->getEndDate();
- /*
- * Start date should be formatted?
- */
+ // Start date should be formatted?
if ($startDate) {
$date = $this->getStartDate();
}
- /*
- * Unknown date or format is invalid?
- */
+ // Unknown date or format is invalid?
+ // Nothing to do
if (null === $date || !Date::isValidDateFormat($format)) {
return '';
}
@@ -138,35 +159,12 @@ class DatePeriod extends BaseType
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
+ * @return null|DateTime
*/
- public function getStartDate()
+ public function getStartDate(): ?DateTime
{
return $this->startDate;
}
@@ -174,10 +172,10 @@ class DatePeriod extends BaseType
/**
* Sets the start date of period
*
- * @param DateTime $startDate (optional) The start date of period
+ * @param null|DateTime $startDate (optional) The start date of period. Default: null.
* @return $this
*/
- public function setStartDate(DateTime $startDate = null)
+ public function setStartDate(?DateTime $startDate = null): self
{
$this->startDate = $startDate;
diff --git a/src/Type/OopVisibilityType.php b/src/Type/OopVisibilityType.php
index 1929710..1299eea 100644
--- a/src/Type/OopVisibilityType.php
+++ b/src/Type/OopVisibilityType.php
@@ -17,21 +17,21 @@ class OopVisibilityType extends BaseType
/**
* The "private" visibility of OOP
*
- * @var int
+ * @var string
*/
- const IS_PRIVATE = 3;
+ public const IS_PRIVATE = '3';
/**
* The "protected" visibility of OOP
*
- * @var int
+ * @var string
*/
- const IS_PROTECTED = 2;
+ public const IS_PROTECTED = '2';
/**
* The "public" visibility of OOP
*
- * @var int
+ * @var string
*/
- const IS_PUBLIC = 1;
+ public const IS_PUBLIC = '1';
}
diff --git a/src/Utilities/Arrays.php b/src/Utilities/Arrays.php
index f994950..5c82257 100644
--- a/src/Utilities/Arrays.php
+++ b/src/Utilities/Arrays.php
@@ -21,794 +21,104 @@ class Arrays
*
* @var string
*/
- const POSITION_KEY_NAME = 'position';
+ public const POSITION_KEY_NAME = 'position';
/**
- * Converts given array's column to string.
- * Recursive call is made for multi-dimensional arrays.
+ * Returns information if keys / indexes of given array are integers, in other words if the array contains
+ * zero-based keys / indexes
*
- * @param array $array Data to be converted
- * @param string|int $arrayColumnKey (optional) Column name. Default: "".
- * @param string $separator (optional) Separator used between values. Default: ",".
- * @return string|null
- */
- public static function values2string(array $array, $arrayColumnKey = '', $separator = ',')
- {
- /*
- * No elements?
- * Nothing to do
- */
- if (empty($array)) {
- return null;
- }
-
- $values = [];
-
- foreach ($array as $key => $value) {
- $appendMe = null;
-
- if (is_array($value)) {
- $appendMe = self::values2string($value, $arrayColumnKey, $separator);
- } elseif (empty($arrayColumnKey)) {
- $appendMe = $value;
- } elseif ($key === $arrayColumnKey) {
- $appendMe = $array[$arrayColumnKey];
- }
-
- /*
- * Part to append is unknown?
- * Let's go to next part
- */
- if (null === $appendMe) {
- continue;
- }
-
- $values[] = $appendMe;
- }
-
- /*
- * No values found?
- * Nothing to do
- */
- if (empty($values)) {
- return null;
- }
-
- return implode($separator, $values);
- }
-
- /**
- * Converts given array to string with keys, e.g. abc=1&def=2 or abc="1" def="2"
- *
- * @param array $array Data to be converted
- * @param string $separator (optional) Separator used between name-value pairs. Default: ",".
- * @param string $valuesKeysSeparator (optional) Separator used between name and value. Default: "=".
- * @param string $valuesWrapper (optional) Wrapper used to wrap values, e.g. double-quote: key="value".
- * Default: "".
- * @return string|null
- */
- public static function valuesKeys2string(
- array $array,
- $separator = ',',
- $valuesKeysSeparator = '=',
- $valuesWrapper = ''
- ) {
- /*
- * No elements?
- * Nothing to do
- */
- if (empty($array)) {
- return null;
- }
-
- $result = '';
-
- foreach ($array as $key => $value) {
- if (!empty($result)) {
- $result .= $separator;
- }
-
- if (!empty($valuesWrapper)) {
- $value = sprintf('%s%s%s', $valuesWrapper, $value, $valuesWrapper);
- }
-
- $result .= $key . $valuesKeysSeparator . $value;
- }
-
- return $result;
- }
-
- /**
- * Converts given array's rows to csv string
- *
- * @param array $array Data to be converted. It have to be an array that represents database table.
- * @param string $separator (optional) Separator used between values. Default: ",".
- * @return string|null
- */
- public static function values2csv(array $array, $separator = ',')
- {
- /*
- * No elements?
- * Nothing to do
- */
- if (empty($array)) {
- return null;
- }
-
- $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 $key => $value) {
- $row[$key] = html_entity_decode($value);
- }
-
- $rows[] = implode($separator, $row);
- }
- }
-
- if (empty($rows)) {
- return '';
- }
-
- return implode($lineSeparator, $rows);
- }
-
- /**
- * 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).
+ * @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 (default behaviour).
* @return bool
*/
- public static function isFirstElement(array $array, $element, $firstLevelOnly = true)
+ public static function areAllKeysIntegers(array $array, $firstLevelOnly = false)
{
- $firstElement = self::getFirstElement($array, $firstLevelOnly);
+ $pattern = '\d+';
- return $element === $firstElement;
+ return self::areAllKeysMatchedByPattern($array, $pattern, $firstLevelOnly);
}
/**
- * Returns the first element of given array
+ * Returns information if keys / indexes of given array are matched by given pattern
*
- * 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).
+ * @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 isLastElement(array $array, $element, $firstLevelOnly = true)
+ public static function areAllKeysMatchedByPattern(array $array, string $pattern, bool $firstLevelOnly = false): bool
{
- $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
- */
+ // 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 Data to get the breadcrumb
- * @param string $separator (optional) Separator used to stick the elements. Default: "/".
- * @return string|null
- */
- public static function getLastElementBreadCrumb(array $array, $separator = '/')
- {
- /*
- * No elements?
- * Nothing to do
- */
- if (empty($array)) {
- return null;
- }
-
- $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;
- }
-
- $result = '';
- $counter = 0;
-
- $arrayCount = count($array);
- $arrayPrepared = self::quoteStrings($array);
- $isMultiDimensional = self::isMultiDimensional($arrayPrepared);
-
- /*
- * 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 (empty($jsVariableName) && $isMultiDimensional) {
- $jsVariableName = 'autoGeneratedVariable';
- }
-
- if (!empty($jsVariableName) && is_string($jsVariableName)) {
- $result .= sprintf('var %s = ', $jsVariableName);
- }
-
- $result .= 'new Array(';
-
- if ($preserveIndexes || $isMultiDimensional) {
- $result .= $arrayCount;
- $result .= ');';
- }
-
- foreach ($arrayPrepared as $index => $value) {
- ++$counter;
-
- if (is_array($value)) {
- $variable = $index;
-
- if (is_int($index)) {
- $variable = 'value_' . $variable;
- }
-
- $value = self::array2JavaScript($value, $variable, $preserveIndexes);
-
- if (null !== $value && '' !== $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) {
- $result .= "\n";
- }
-
- $result .= $value . "\n";
- $result .= sprintf('%s[%s] = %s;', $jsVariableName, Miscellaneous::quoteValue($index), $variable);
-
- if ($counter !== $arrayCount) {
- $result .= "\n";
- }
- }
- } elseif ($preserveIndexes) {
- if (!empty($jsVariableName)) {
- $index = Miscellaneous::quoteValue($index);
- $result .= sprintf("\n%s[%s] = %s;", $jsVariableName, $index, $value);
- }
- } else {
- $format = '%s';
-
- if ($counter < $arrayCount) {
- $format .= ', ';
- }
-
- $result .= sprintf($format, $value);
- }
- }
-
- if (!$preserveIndexes && !$isMultiDimensional) {
- $result .= ');';
- }
-
- return $result;
- }
-
- /**
- * Quotes (adds quotes) to elements that are strings and returns new array (with quoted elements)
- *
- * @param array $array The array to check for string values
- * @return array|null
- */
- public static function quoteStrings(array $array)
- {
- /*
- * No elements?
- * Nothing to do
- */
- if (empty($array)) {
- return null;
- }
-
- $result = [];
-
- foreach ($array as $index => $value) {
- if (is_array($value)) {
- $value = self::quoteStrings($value);
- } elseif (is_string($value)) {
- if (!Regex::isQuoted($value)) {
- $value = '\'' . $value . '\'';
- }
- }
-
- $result[$index] = $value;
- }
-
- return $result;
- }
-
- /**
- * 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, -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)
- {
- /*
- * No elements?
- * Nothing to do
- */
- if (empty($array)) {
- return null;
- }
-
- $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)
- {
- /*
- * No elements or the element does not exist?
- * Nothing to do
- */
- if (empty($array) || !in_array($item, $array, true)) {
return false;
}
/*
- * Flip the array to make it looks like: value => key
+ * I suppose that all are keys are matched
+ * and then I have to look for keys that don't matches
*/
- $arrayFlipped = array_flip($array);
+ $areMatched = true;
- /*
- * 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 &$array, $needle, $before = true)
- {
- if (!empty($array)) {
- if (!$before) {
- $array = array_reverse($array, true);
- }
-
- foreach ($array as $key => &$value) {
- $remove = false;
- $isArray = is_array($value);
-
- if ($isArray) {
- self::removeElements($value, $needle, $before);
-
- if ($isArray && empty($value)) {
- $remove = true;
- }
- } elseif ($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|null
- *
- * 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)
- {
- /*
- * No elements?
- * Nothing to do
- */
- if (empty($array)) {
- return null;
- }
-
- $replaced = [];
+ // Building the pattern
+ $rawPattern = $pattern;
+ $pattern = sprintf('|%s|', $rawPattern);
foreach ($array as $key => $value) {
/*
- * The value it's an array?
- * Let's replace keys with values in this array first
+ * 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 (is_array($value)) {
- $replaced[$key] = self::setKeysAsValues($value, $ignoreDuplicatedValues);
- continue;
+ if (!preg_match($pattern, $key)) {
+ $areMatched = false;
+
+ break;
}
/*
- * 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)
+ * The not matching key was not found and the value is an array?
+ * Let's begin recursive looking for result
*/
- if (!$ignoreDuplicatedValues && isset($replaced[$value])) {
- $existing = self::makeArray($replaced[$value]);
-
- $replaced[$value] = array_merge($existing, [
- $key,
- ]);
-
- continue;
+ if ($areMatched && is_array($value) && !$firstLevelOnly) {
+ $areMatched = self::areAllKeysMatchedByPattern($value, $rawPattern, $firstLevelOnly);
}
+ }
+ return $areMatched;
+ }
+
+ /**
+ * 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) {
/*
- * Standard behaviour
+ * 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
*/
- $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);
+ if ((!is_array($element) && $strictNull && null !== $element) || !empty($element)) {
+ return false;
}
}
- 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.
- * Default: "|".
- * @param string $valuesKeysSeparator (optional) Separator used between name and value in the string. Default: ":".
- * @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;
+ return true;
}
/**
@@ -851,16 +161,457 @@ class Arrays
return $result;
}
+ /**
+ * 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.
+ * Default: "autoGeneratedVariable".
+ * @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 (default behaviour).
+ * @return null|string
+ */
+ public static function array2JavaScript(
+ array $array,
+ string $jsVariableName = '',
+ bool $preserveIndexes = false
+ ): ?string {
+ // No elements? Nothing to do
+ if (empty($array)) {
+ return null;
+ }
+
+ $result = '';
+ $counter = 0;
+
+ $arrayCount = count($array);
+ $arrayPrepared = self::quoteStrings($array);
+ $isMultiDimensional = false;
+
+ if (null !== $arrayPrepared) {
+ $isMultiDimensional = self::isMultiDimensional($arrayPrepared);
+ }
+
+ /*
+ * 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 (empty($jsVariableName) && $isMultiDimensional) {
+ $jsVariableName = 'autoGeneratedVariable';
+ }
+
+ if (!empty($jsVariableName)) {
+ $result .= sprintf('var %s = ', $jsVariableName);
+ }
+
+ $result .= 'new Array(';
+
+ if ($preserveIndexes || $isMultiDimensional) {
+ $result .= $arrayCount;
+ $result .= ');';
+ }
+
+ if (null !== $arrayPrepared) {
+ foreach ($arrayPrepared as $index => $value) {
+ ++$counter;
+
+ if (is_array($value)) {
+ $variable = $index;
+
+ if (is_int($index)) {
+ $variable = 'value_'.$variable;
+ }
+
+ $value = self::array2JavaScript($value, $variable, $preserveIndexes);
+
+ if (null !== $value && '' !== $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) {
+ $result .= "\n";
+ }
+
+ $result .= $value."\n";
+ $result .= sprintf('%s[%s] = %s;', $jsVariableName, Miscellaneous::quoteValue($index), $variable);
+
+ if ($counter !== $arrayCount) {
+ $result .= "\n";
+ }
+ }
+ } elseif ($preserveIndexes) {
+ if (!empty($jsVariableName)) {
+ $index = Miscellaneous::quoteValue($index);
+ $result .= sprintf("\n%s[%s] = %s;", $jsVariableName, $index, $value);
+ }
+ } else {
+ $format = '%s';
+
+ if ($counter < $arrayCount) {
+ $format .= ', ';
+ }
+
+ $result .= sprintf($format, $value);
+ }
+ }
+ }
+
+ if (!$preserveIndexes && !$isMultiDimensional) {
+ $result .= ');';
+ }
+
+ return $result;
+ }
+
+ /**
+ * 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, bool $valuesOnly = false): array
+ {
+ $result = [];
+
+ /*
+ * 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);
+ }
+ } elseif (!$array2HasKey || $value !== $array2[$key]) {
+ /*
+ * We are here, because:
+ * a) 2nd array hasn't key from 1st array
+ * OR
+ * b) key exists in both, 1st and 2nd array, but values are different
+ */
+ $difference = $value;
+ }
+
+ if (null !== $difference) {
+ $result[] = $difference;
+ }
+
+ // The key exists in 2nd array?
+ } elseif ($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;
+ }
+
+ $result[$key] = $diff;
+ } elseif ($value !== $array2[$key]) {
+ // Value is different than in 2nd array?
+ // OKay, I've got difference
+ $result[$key] = $value;
+ }
+ } else {
+ // OKay, I've got difference
+ $result[$key] = $value;
+ }
+ }
+
+ return $result;
+ }
+
+ public static function containsEmptyStringsOnly(array $array): bool
+ {
+ if (empty($array)) {
+ return false;
+ }
+
+ return '' === trim(implode('', $array));
+ }
+
+ /**
+ * 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 null|array
+ */
+ public static function getAllValuesOfKey(array $array, $key)
+ {
+ // No elements? Nothing to do
+ 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)) {
+ $merged = array_merge($values, $recursiveValues);
+ $values = $merged;
+ }
+ }
+ }
+
+ return $values;
+ }
+
+ /**
+ * 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): int
+ {
+ // No elements? Nothing to do
+ if (empty($array)) {
+ return 0;
+ }
+
+ $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;
+ }
+
+ public static function getElementsFromLevel(array $array, int $level, ?string $childrenKey = null): ?array
+ {
+ if (empty($array) || $level <= 0) {
+ return null;
+ }
+
+ $result = [];
+
+ foreach ($array as $key => $value) {
+ // This is the expected level (the deepest). Comparing with 1, because level will be decreased by 1 (later),
+ // and finally we will get the latest/deepest level that equals 1.
+ if ($level === 1) {
+ // No key of children (next level) provided or this is the same key as processed?
+ // We've got the expected value
+ if ($childrenKey === null || $key === $childrenKey) {
+ $result[] = $value;
+ }
+
+ continue;
+ }
+
+ // There is no deeper level
+ if (!is_array($value)) {
+ continue;
+ }
+
+ // Let's dive one level down/deeper
+ $elements = self::getElementsFromLevel($value, $level - 1, $childrenKey);
+
+ if ($elements === null) {
+ continue;
+ }
+
+ // I have to load each element separately to avoid issue with incorrectly nested values
+ foreach ($elements as $element) {
+ $result[] = $element;
+ }
+ }
+
+ return $result;
+ }
+
+ /**
+ * 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, bool $firstLevelOnly = true)
+ {
+ // No elements? Nothing to do
+ if (empty($array)) {
+ return null;
+ }
+
+ $firstKey = static::getFirstKey($array);
+ $result = $array[$firstKey];
+
+ if (!$firstLevelOnly && is_array($result)) {
+ $result = static::getFirstElement($result, $firstLevelOnly);
+ }
+
+ return $result;
+ }
+
+ /**
+ * 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 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 null|bool|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 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, bool $firstLevelOnly = true)
+ {
+ // No elements? Nothing to do
+ if (empty($array)) {
+ return null;
+ }
+
+ $last = end($array);
+
+ if (!$firstLevelOnly && is_array($last)) {
+ $last = static::getLastElement($last, $firstLevelOnly);
+ }
+
+ return $last;
+ }
+
+ /**
+ * Returns breadcrumb (a path) to the last element of array
+ *
+ * @param array $array Data to get the breadcrumb
+ * @param string $separator (optional) Separator used to stick the elements. Default: "/".
+ * @return null|string
+ */
+ public static function getLastElementBreadCrumb(array $array, $separator = '/')
+ {
+ // No elements? Nothing to do
+ if (empty($array)) {
+ return null;
+ }
+
+ $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 paths of the last elements
*
- * @param array $array The array with elements
- * @param string $separator (optional) Separator used between elements. 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). Default: "".
- * @return array|null
+ * @param array $array The array with elements
+ * @param string $separator (optional) Separator used between elements. Default: ".".
+ * @param string $parentPath (optional) Path of the parent element. Default: "".
+ * @param array $stopIfMatchedBy (optional) Patterns of keys or paths when 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). Default: [].
+ * @return null|array
*
* Examples - $stopIfMatchedBy argument:
* a) "\d+"
@@ -869,21 +620,18 @@ class Arrays
* "\d+",
* ];
*/
- public static function getLastElementsPaths(array $array, $separator = '.', $parentPath = '', $stopIfMatchedBy = '')
- {
- /*
- * No elements?
- * Nothing to do
- */
+ public static function getLastElementsPaths(
+ array $array,
+ string $separator = '.',
+ string $parentPath = '',
+ array $stopIfMatchedBy = []
+ ): ?array {
+ // No elements? Nothing to do
if (empty($array)) {
return null;
}
- if (!empty($stopIfMatchedBy)) {
- $stopIfMatchedBy = self::makeArray($stopIfMatchedBy);
- }
-
- $paths = [];
+ $result = [];
foreach ($array as $key => $value) {
$path = $key;
@@ -910,6 +658,7 @@ class Arrays
if (preg_match($pattern, $key) || preg_match($pattern, $path)) {
$stopRecursion = true;
+
break;
}
}
@@ -917,109 +666,174 @@ class Arrays
/*
* The value is passed to the returned array if:
+ * - the process is stopped, recursive is not used
+ * or
* - it's not an array
* or
- * - the process is stopped, recursive is not used
+ * - it's an array, but empty
*/
- if (!$valueIsArray || ($valueIsArray && empty($value)) || $stopRecursion) {
- $paths[$path] = $value;
+ if ($stopRecursion || !$valueIsArray || self::isEmptyArray($value)) {
+ $result[$path] = $value;
+
continue;
}
- /*
- * Let's iterate through the next level, using recursive
- */
- if ($valueIsArray) {
- $recursivePaths = self::getLastElementsPaths($value, $separator, $path, $stopIfMatchedBy);
- $paths += $recursivePaths;
+ // Let's iterate through the next level, using recursive
+ $recursivePaths = self::getLastElementsPaths($value, $separator, $path, $stopIfMatchedBy);
+
+ if (null !== $recursivePaths) {
+ $result += $recursivePaths;
}
}
- return $paths;
+ return $result;
}
/**
- * Makes and returns an array for given variable
+ * Returns last key of array
*
- * @param mixed $variable Variable that should be an array
- * @return array
+ * @param array $array The array to get the last key of
+ * @return mixed
*/
- public static function makeArray($variable)
+ public static function getLastKey(array $array)
{
- 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 $array, $pattern, $firstLevelOnly = false)
- {
- /*
- * No elements?
- * Nothing to do
- */
+ // No elements? Nothing to do
if (empty($array)) {
- return false;
+ return null;
}
- /*
- * I suppose that all are keys are matched
- * and then I have to look for keys that don't matches
- */
- $areMatched = true;
+ $keys = array_keys($array);
- /*
- * 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;
+ return end($keys);
}
/**
- * Returns information if keys / indexes of given array are integers, in other words if the array contains
- * zero-based keys / indexes
+ * Returns the last row of array
*
- * @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 (default behaviour).
- * @return bool
+ * @param array $array The array to get the last row of
+ * @return mixed
*/
- public static function areAllKeysIntegers(array $array, $firstLevelOnly = false)
+ public static function getLastRow(array $array): ?array
{
- $pattern = '\d+';
+ // No elements? Nothing to do
+ if (empty($array)) {
+ return null;
+ }
- return self::areAllKeysMatchedByPattern($array, $pattern, $firstLevelOnly);
+ $result = [];
+ $last = end($array);
+
+ if (is_array($last)) {
+ // We've got an array, so looking for the last row of array will be done recursively
+ $result = static::getLastRow($last);
+
+ /*
+ * The last row is not an array or it's an empty array?
+ * Let's use the previous candidate
+ */
+ if (!is_array($result) || static::isEmptyArray($result)) {
+ $result = $last;
+ }
+ }
+
+ return $result;
+ }
+
+ /**
+ * 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 count / amount of elements that are not array
+ *
+ * @param array $array The array to count
+ * @return null|int
+ */
+ public static function getNonArrayElementsCount(array $array): ?int
+ {
+ // No elements? Nothing to do
+ if (empty($array)) {
+ return null;
+ }
+
+ $count = 0;
+
+ foreach ($array as $value) {
+ if (is_array($value)) {
+ $count += (int) self::getNonArrayElementsCount($value);
+
+ continue;
+ }
+
+ ++$count;
+ }
+
+ return $count;
+ }
+
+ /**
+ * Returns non-empty values, e.g. without "" (empty string), null or []
+ *
+ * @param array $values The values to filter
+ * @return null|array
+ */
+ public static function getNonEmptyValues(array $values): ?array
+ {
+ // No values? Nothing to do
+ if (empty($values)) {
+ return null;
+ }
+
+ return array_filter($values, static function ($value): bool {
+ $nonEmptyScalar = is_scalar($value) && '' !== $value;
+ $nonEmptyArray = self::isNotEmptyArray($value);
+
+ return $nonEmptyScalar || $nonEmptyArray || is_object($value);
+ });
+ }
+
+ /**
+ * Returns non-empty values concatenated by given separator
+ *
+ * @param array $values The values to filter
+ * @param string $separator (optional) Separator used to implode the values. Default: ", ".
+ * @return null|string
+ */
+ public static function getNonEmptyValuesAsString(array $values, string $separator = ', '): ?string
+ {
+ // No elements? Nothing to do
+ if (empty($values)) {
+ return null;
+ }
+
+ $nonEmpty = self::getNonEmptyValues($values);
+
+ // No values? Nothing to do
+ if (empty($nonEmpty)) {
+ return '';
+ }
+
+ return implode($separator, $nonEmpty);
+ }
+
+ /**
+ * 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);
}
/**
@@ -1053,10 +867,7 @@ class Arrays
*/
public static function getValueByKeysPath(array $array, array $keys)
{
- /*
- * No elements?
- * Nothing to do
- */
+ // No elements? Nothing to do
if (empty($array)) {
return null;
}
@@ -1079,6 +890,170 @@ class Arrays
return $value;
}
+ /**
+ * 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 null|string
+ */
+ public static function implodeSmart(array $array, $separator)
+ {
+ // No elements? Nothing to do
+ if (empty($array)) {
+ return null;
+ }
+
+ 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, -1);
+ }
+ }
+
+ return implode($separator, $array);
+ }
+
+ /**
+ * Returns an array with incremented indexes / keys
+ *
+ * @param array $array The array which indexes / keys should be incremented
+ * @param null|int $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 null|array
+ */
+ public static function incrementIndexes(array $array, ?int $startIndex = null, int $incrementStep = 1): ?array
+ {
+ // No elements? Nothing to do
+ if (empty($array)) {
+ return null;
+ }
+
+ $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 = (int) $oldIndex + $incrementStep;
+ $array[$newIndex] = $value;
+ }
+ }
+ }
+
+ return $array;
+ }
+
+ /**
+ * Returns information if given value is an array and is empty
+ *
+ * @param mixed $value The value to verify
+ * @return bool
+ */
+ public static function isEmptyArray($value): bool
+ {
+ return is_array($value) && empty($value);
+ }
+
+ /**
+ * 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, bool $firstLevelOnly = true): bool
+ {
+ $firstElement = static::getFirstElement($array, $firstLevelOnly);
+
+ return $element === $firstElement;
+ }
+
+ /**
+ * 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, bool $firstLevelOnly = true): bool
+ {
+ $lastElement = static::getLastElement($array, $firstLevelOnly);
+
+ return $element === $lastElement;
+ }
+
+ /**
+ * Returns information if given array is a multi dimensional array
+ *
+ * @param array $array The array to verify
+ * @return null|bool
+ */
+ public static function isMultiDimensional(array $array): ?bool
+ {
+ // No elements? Nothing to do
+ if (empty($array)) {
+ return null;
+ }
+
+ return count($array) !== count($array, COUNT_RECURSIVE);
+ }
+
+ /**
+ * Returns information if given value is non-empty array
+ *
+ * @param mixed $value The value to verify
+ * @return bool
+ */
+ public static function isNotEmptyArray($value): bool
+ {
+ return is_array($value) && !empty($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.
@@ -1107,10 +1082,7 @@ class Arrays
*/
public static function issetRecursive(array $array, array $keys)
{
- /*
- * No elements?
- * Nothing to do
- */
+ // No elements? Nothing to do
if (empty($array)) {
return false;
}
@@ -1136,42 +1108,264 @@ class Arrays
}
/**
- * Returns all values of given key.
- * It may be useful when you want to retrieve all values of one column.
+ * Applies ksort() function recursively in the given array
*
- * @param array $array The array which should contain values of the key
- * @param string $key The key
- * @return array|null
+ * @param array $array The array to sort
+ * @param int $sortFlags (optional) Options of ksort() function
+ * @return null|array
*/
- public static function getAllValuesOfKey(array $array, $key)
+ public static function ksortRecursive(array &$array, $sortFlags = SORT_REGULAR)
{
- /*
- * No elements?
- * Nothing to do
- */
+ // No elements? Nothing to do
if (empty($array)) {
return null;
}
- $values = [];
-
- foreach ($array as $index => $value) {
- if ($index === $key) {
- $values[] = $value;
- continue;
- }
+ $effect = &$array;
+ ksort($effect, $sortFlags);
+ foreach ($effect as &$value) {
if (is_array($value)) {
- $recursiveValues = self::getAllValuesOfKey($value, $key);
-
- if (!empty($recursiveValues)) {
- $merged = array_merge($values, $recursiveValues);
- $values = $merged;
- }
+ ksort($value, $sortFlags);
}
}
- return $values;
+ return $effect;
+ }
+
+ /**
+ * Makes and returns an array for given variable
+ *
+ * @param mixed $variable Variable that should be an array
+ * @return array
+ */
+ public static function makeArray($variable): array
+ {
+ if (is_array($variable)) {
+ return $variable;
+ }
+
+ return [$variable];
+ }
+
+ /**
+ * Quotes (adds quotes) to elements that are strings and returns new array (with quoted elements)
+ *
+ * @param array $array The array to check for string values
+ * @return null|array
+ */
+ public static function quoteStrings(array $array): ?array
+ {
+ // No elements? Nothing to do
+ if (empty($array)) {
+ return null;
+ }
+
+ $result = [];
+
+ foreach ($array as $index => $value) {
+ if (is_array($value)) {
+ $value = self::quoteStrings($value);
+ } elseif (is_string($value) && !Regex::isQuoted($value)) {
+ $value = '\''.$value.'\'';
+ }
+
+ $result[$index] = $value;
+ }
+
+ return $result;
+ }
+
+ /**
+ * 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 array|bool
+ */
+ public static function removeElement(array $array, $item)
+ {
+ // No elements or the element does not exist? Nothing to do
+ if (empty($array) || !in_array($item, $array, true)) {
+ 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 &$array, $needle, $before = true): void
+ {
+ if (!empty($array)) {
+ if (!$before) {
+ $array = array_reverse($array, true);
+ }
+
+ foreach ($array as $key => &$value) {
+ $remove = false;
+ $isArray = is_array($value);
+
+ if ($isArray) {
+ self::removeElements($value, $needle, $before);
+
+ if (empty($value)) {
+ $remove = true;
+ }
+ } elseif ($value === $needle) {
+ break;
+ } else {
+ $remove = true;
+ }
+
+ if ($remove) {
+ unset($array[$key]);
+ }
+ }
+
+ if (!$before) {
+ $array = array_reverse($array, true);
+ }
+ }
+ }
+
+ /**
+ * Removes marginal element (first or last) from given array
+ *
+ * @param array $array The array which should be shortened
+ * @param bool $last (optional) If is set to true, last element is removed (default behaviour). Otherwise - first.
+ * @return null|array
+ */
+ public static function removeMarginalElement(array $array, bool $last = true): ?array
+ {
+ // No elements? Nothing to do
+ if (empty($array)) {
+ return null;
+ }
+
+ $key = self::getFirstKey($array);
+
+ if ($last) {
+ $key = self::getLastKey($array);
+ }
+
+ unset($array[$key]);
+
+ return $array;
+ }
+
+ /**
+ * Replaces array keys that match given pattern with new key name
+ *
+ * @param array $array Array which keys should be replaced
+ * @param string $oldKeyPattern Regular expression of the old key
+ * @param string $newKey Name of the new key
+ * @return null|array
+ */
+ public static function replaceKeys(array $array, string $oldKeyPattern, string $newKey): ?array
+ {
+ if (empty($array)) {
+ return null;
+ }
+
+ $effect = [];
+
+ foreach ($array as $key => $value) {
+ if (preg_match($oldKeyPattern, $key)) {
+ $key = $newKey;
+ }
+
+ if (is_array($value)) {
+ $value = self::replaceKeys($value, $oldKeyPattern, $newKey);
+ }
+
+ $effect[$key] = $value;
+ }
+
+ return $effect;
+ }
+
+ /**
+ * 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 null|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)
+ {
+ // No elements? Nothing to do
+ if (empty($array)) {
+ return null;
+ }
+
+ $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;
}
/**
@@ -1184,14 +1378,11 @@ class Arrays
* @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|null
+ * @return null|array
*/
public static function setPositions(array $array, $keyName = self::POSITION_KEY_NAME, $startPosition = null)
{
- /*
- * No elements?
- * Nothing to do
- */
+ // No elements? Nothing to do
if (empty($array)) {
return null;
}
@@ -1212,40 +1403,6 @@ class Arrays
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)
- {
- /*
- * No elements?
- * Nothing to do
- */
- if (empty($array)) {
- return [];
- }
-
- $result = [];
-
- foreach ($array as $key => $value) {
- if (is_array($value)) {
- $result[$key] = self::trimRecursive($value);
- continue;
- }
-
- if (is_string($value)) {
- $value = trim($value);
- }
-
- $result[$key] = $value;
- }
-
- return $result;
- }
-
/**
* Sorts an array by keys given in second array as values.
* Keys which are not in array with order are pushed after sorted elements.
@@ -1287,14 +1444,11 @@ class Arrays
*
* @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
+ * @return null|array
*/
public static function sortByCustomKeysOrder(array $array, array $keysOrder)
{
- /*
- * No elements?
- * Nothing to do
- */
+ // No elements? Nothing to do
if (empty($array)) {
return null;
}
@@ -1328,261 +1482,45 @@ class Arrays
}
/**
- * Returns smartly imploded string
+ * Converts given string with special separators to array
*
- * 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.
+ * Example:
+ * ~ string:
+ * "light:jasny|dark:ciemny"
*
- * @param array $array The array with elements to implode
- * @param string $separator Separator used to stick together elements of given array
- * @return string|null
+ * ~ 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.
+ * Default: "|".
+ * @param string $valuesKeysSeparator (optional) Separator used between name and value in the string. Default: ":".
+ * @return null|array
*/
- public static function implodeSmart(array $array, $separator)
- {
- /*
- * No elements?
- * Nothing to do
- */
- if (empty($array)) {
+ public static function string2array(
+ string $string,
+ string $separator = '|',
+ string $valuesKeysSeparator = ':'
+ ): ?array {
+ // Empty string? Nothing to do
+ if (empty($string)) {
return null;
}
- foreach ($array as &$element) {
- if (is_array($element)) {
- $element = self::implodeSmart($element, $separator);
- }
+ $array = [];
+ $exploded = explode($separator, $string);
- if (Regex::startsWith($element, $separator)) {
- $element = substr($element, 1);
- }
+ foreach ($exploded as $item) {
+ $exploded2 = explode($valuesKeysSeparator, $item);
- if (Regex::endsWith($element, $separator)) {
- $element = substr($element, 0, -1);
- }
- }
+ if (2 === count($exploded2)) {
+ $key = trim($exploded2[0]);
+ $value = trim($exploded2[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);
- }
- } elseif (!$array2HasKey || ($array2HasKey && $value !== $array2[$key])) {
- /*
- * We are here, because:
- * a) 2nd array hasn't key from 1st array
- * OR
- * b) key exists in both, 1st and 2nd array, but values are different
- */
- $difference = $value;
- }
-
- if (null !== $difference) {
- $effect[] = $difference;
- }
-
- /*
- * The key exists in 2nd array?
- */
- } elseif ($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;
- } elseif ($value !== $array2[$key]) {
- /*
- * Value is different than in 2nd array?
- * OKay, I've got difference
- */
- $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|null
- */
- public static function incrementIndexes(array $array, $startIndex = null, $incrementStep = 1)
- {
- /*
- * No elements?
- * Nothing to do
- */
- if (empty($array)) {
- return null;
- }
-
- $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;
- }
+ $array[$key] = $value;
}
}
@@ -1590,135 +1528,160 @@ class Arrays
}
/**
- * Returns next element of given array related to given element
+ * Trims string values of given array and returns the new array
*
- * @param array $array The array with elements
- * @param mixed $element Element for who next element should be returned
- * @return null|mixed
+ * @param array $array The array which values should be trimmed
+ * @return array
*/
- public static function getNextElement(array $array, $element)
+ public static function trimRecursive(array $array)
{
- return self::getNeighbour($array, $element);
+ // No elements? Nothing to do
+ if (empty($array)) {
+ return [];
+ }
+
+ $result = [];
+
+ foreach ($array as $key => $value) {
+ if (is_array($value)) {
+ $result[$key] = self::trimRecursive($value);
+
+ continue;
+ }
+
+ if (is_string($value)) {
+ $value = trim($value);
+ }
+
+ $result[$key] = $value;
+ }
+
+ return $result;
}
/**
- * Returns previous element of given array related to given element
+ * Converts given array's rows to csv string
*
- * @param array $array The array with elements
- * @param mixed $element Element for who previous element should be returned
- * @return null|mixed
+ * @param array $array Data to be converted. It have to be an array that represents database table.
+ * @param string $separator (optional) Separator used between values. Default: ",".
+ * @return null|string
*/
- public static function getPreviousElement(array $array, $element)
+ public static function values2csv(array $array, string $separator = ','): ?string
{
- 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
- */
+ // No elements? Nothing to do
if (empty($array)) {
return null;
}
- return count($array) !== count($array, COUNT_RECURSIVE);
- }
+ $rows = [];
+ $lineSeparator = "\n";
- /**
- * 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)
- {
- /*
- * No elements?
- * Nothing to do
- */
- if (empty($array)) {
- return 0;
- }
+ 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.
+ */
- $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;
+ if (is_array($row) && !empty($row)) {
+ foreach ($row as $key => $value) {
+ $row[$key] = html_entity_decode($value);
}
+
+ $rows[] = implode($separator, $row);
}
}
- return $dimensionsCount;
- }
-
- /**
- * Returns non-empty values, e.g. without "" (empty string), null or []
- *
- * @param array $values The values to filter
- * @return array|null
- */
- public static function getNonEmptyValues(array $values)
- {
- /*
- * No values?
- * Nothing to do
- */
- if (empty($values)) {
- return null;
- }
-
- return array_filter($values, function ($value) {
- $nonEmptyScalar = is_scalar($value) && '' !== $value;
- $nonEmptyArray = is_array($value) && !empty($value);
-
- return $nonEmptyScalar || $nonEmptyArray || is_object($value);
- });
- }
-
- /**
- * Returns non-empty values concatenated by given separator
- *
- * @param array $values The values to filter
- * @param string $separator (optional) Separator used to implode the values. Default: ", ".
- * @return string|null
- */
- public static function getNonEmptyValuesAsString(array $values, $separator = ', ')
- {
- /*
- * No elements?
- * Nothing to do
- */
- if (empty($values)) {
- return null;
- }
-
- $nonEmpty = self::getNonEmptyValues($values);
-
- /*
- * No values?
- * Nothing to do
- */
- if (empty($nonEmpty)) {
+ if (empty($rows)) {
return '';
}
- return implode($separator, $nonEmpty);
+ return implode($lineSeparator, $rows);
+ }
+
+ /**
+ * Converts given array's column to string.
+ * Recursive call is made for multi-dimensional arrays.
+ *
+ * @param array $array Data to be converted
+ * @param int|string $arrayColumnKey (optional) Column name. Default: "".
+ * @param string $separator (optional) Separator used between values. Default: ",".
+ * @return null|string
+ */
+ public static function values2string(array $array, $arrayColumnKey = '', $separator = ',')
+ {
+ // No elements? Nothing to do
+ if (empty($array)) {
+ return null;
+ }
+
+ $values = [];
+
+ foreach ($array as $key => $value) {
+ $appendMe = null;
+
+ if (is_array($value)) {
+ $appendMe = self::values2string($value, $arrayColumnKey, $separator);
+ } elseif (empty($arrayColumnKey)) {
+ $appendMe = $value;
+ } elseif ($key === $arrayColumnKey) {
+ $appendMe = $array[$arrayColumnKey];
+ }
+
+ /*
+ * Part to append is unknown?
+ * Let's go to next part
+ */
+ if (null === $appendMe) {
+ continue;
+ }
+
+ $values[] = $appendMe;
+ }
+
+ // No values found? Nothing to do
+ if (empty($values)) {
+ return null;
+ }
+
+ return implode($separator, $values);
+ }
+
+ /**
+ * Converts given array to string with keys, e.g. abc=1&def=2 or abc="1" def="2"
+ *
+ * @param array $array Data to be converted
+ * @param string $separator (optional) Separator used between name-value pairs. Default: ",".
+ * @param string $valuesKeysSeparator (optional) Separator used between name and value. Default: "=".
+ * @param string $valuesWrapper (optional) Wrapper used to wrap values, e.g. double-quote: key="value".
+ * Default: "".
+ * @return null|string
+ */
+ public static function valuesKeys2string(
+ array $array,
+ $separator = ',',
+ $valuesKeysSeparator = '=',
+ $valuesWrapper = ''
+ ) {
+ // No elements? Nothing to do
+ if (empty($array)) {
+ return null;
+ }
+
+ $result = '';
+
+ foreach ($array as $key => $value) {
+ if (!empty($result)) {
+ $result .= $separator;
+ }
+
+ if (!empty($valuesWrapper)) {
+ $value = sprintf('%s%s%s', $valuesWrapper, $value, $valuesWrapper);
+ }
+
+ $result .= $key.$valuesKeysSeparator.$value;
+ }
+
+ return $result;
}
/**
@@ -1727,14 +1690,11 @@ class Arrays
* @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
+ * @return null|mixed
*/
- private static function getNeighbour(array $array, $element, $next = true)
+ private static function getNeighbour(array $array, $element, bool $next = true)
{
- /*
- * No elements?
- * Nothing to do
- */
+ // No elements? Nothing to do
if (empty($array)) {
return null;
}
@@ -1753,7 +1713,7 @@ class Arrays
*
* Nothing to do
*/
- if ($noPrevious || $noNext || empty($array) || !in_array($element, $array, true)) {
+ if ($noPrevious || $noNext || !in_array($element, $array, true)) {
return null;
}
@@ -1770,9 +1730,7 @@ class Arrays
return null;
}
- /*
- * Looking for key of the neighbour (next or previous element)
- */
+ // Looking for key of the neighbour (next or previous element)
if ($next) {
++$indexOfKey;
} else {
diff --git a/src/Utilities/Bootstrap4CssSelector.php b/src/Utilities/Bootstrap4CssSelector.php
index 6933274..35d12d1 100644
--- a/src/Utilities/Bootstrap4CssSelector.php
+++ b/src/Utilities/Bootstrap4CssSelector.php
@@ -46,6 +46,23 @@ class Bootstrap4CssSelector
return sprintf('%s %s', $labelSelector, $errorContainerSelector);
}
+ /**
+ * Returns selector of field's group
+ *
+ * @param string $formName Name of form (value of the "name" attribute)
+ * @return string
+ */
+ public static function getFieldGroupSelector($formName)
+ {
+ $formSelector = CssSelector::getFormByNameSelector($formName);
+
+ if (empty($formSelector)) {
+ return '';
+ }
+
+ return sprintf('%s .form-group', $formSelector);
+ }
+
/**
* Returns selector of radio-button's validation error
*
@@ -65,21 +82,4 @@ class Bootstrap4CssSelector
return sprintf('%s legend.col-form-label %s', $fieldSetSelector, $errorContainerSelector);
}
-
- /**
- * Returns selector of field's group
- *
- * @param string $formName Name of form (value of the "name" attribute)
- * @return string
- */
- public static function getFieldGroupSelector($formName)
- {
- $formSelector = CssSelector::getFormByNameSelector($formName);
-
- if (empty($formSelector)) {
- return '';
- }
-
- return sprintf('%s .form-group', $formSelector);
- }
}
diff --git a/src/Utilities/Bundle.php b/src/Utilities/Bundle.php
index 105d8d9..691787c 100644
--- a/src/Utilities/Bundle.php
+++ b/src/Utilities/Bundle.php
@@ -21,62 +21,50 @@ class Bundle
/**
* Returns path of given bundle to view / template with given extension
*
- * @param string $viewPath Path of the view / template, e.g. "MyDirectory/my-template"
+ * @param string $viewPath Path of the view / template, e.g. "MyDirectory/my-template". Extension is not required.
* @param string $bundleName Full name of the bundle, e.g. "MyExtraBundle"
* @param string $extension (optional) Extension of the view / template (default: "html.twig")
+ * @return null|string
* @throws IncorrectBundleNameException
- * @return string|null
*/
- public static function getBundleViewPath($viewPath, $bundleName, $extension = 'html.twig')
- {
- /*
- * Unknown path, extension of the view / template or name of the bundle?
- * Nothing to do
- */
+ public static function getBundleViewPath(
+ string $viewPath,
+ string $bundleName,
+ string $extension = 'html.twig'
+ ): ?string {
+ // Nothing to do, because at least one unknown argument provided
if (empty($viewPath) || empty($bundleName) || empty($extension)) {
return null;
}
- /*
- * Given name of bundle is invalid?
- */
+ // Oops, given name of bundle is invalid
if (!Regex::isValidBundleName($bundleName)) {
throw IncorrectBundleNameException::create($bundleName);
}
- /*
- * Path of the view / template doesn't end with given extension?
- */
+ // Make sure that path of the view / template ends with given extension
if (!Regex::endsWith($viewPath, $extension)) {
$viewPath = sprintf('%s.%s', $viewPath, $extension);
}
- /*
- * Prepare short name of bundle and path of view / template with "/" (instead of ":")
- */
- $shortBundleName = static::getShortBundleName($bundleName);
- $viewPath = str_replace(':', '/', $viewPath);
+ // Prepare short name of bundle and path of view / template with "/" (instead of ":")
+ $shortName = static::getShortBundleName($bundleName);
+ $path = str_replace(':', '/', $viewPath);
- return sprintf('@%s/%s', $shortBundleName, $viewPath);
+ return sprintf('@%s/%s', $shortName, $path);
}
/**
* Returns short name of bundle (without "Bundle")
*
* @param string $fullBundleName Full name of the bundle, e.g. "MyExtraBundle"
+ * @return null|string
* @throws IncorrectBundleNameException
- * @return string|null
*/
- public static function getShortBundleName($fullBundleName)
+ public static function getShortBundleName(string $fullBundleName): ?string
{
- /*
- * Given name of bundle is invalid?
- */
+ // Oops, given name of bundle is invalid
if (!Regex::isValidBundleName($fullBundleName)) {
- if (!is_string($fullBundleName)) {
- $fullBundleName = gettype($fullBundleName);
- }
-
throw new IncorrectBundleNameException($fullBundleName);
}
diff --git a/src/Utilities/Composer.php b/src/Utilities/Composer.php
index 28e91c7..24ee2ce 100644
--- a/src/Utilities/Composer.php
+++ b/src/Utilities/Composer.php
@@ -8,8 +8,6 @@
namespace Meritoo\Common\Utilities;
-use stdClass;
-
/**
* Useful Composer-related methods (only static functions)
*
@@ -23,23 +21,18 @@ class Composer
*
* @var string
*/
- const FILE_NAME_MAIN = 'composer.json';
+ public const FILE_NAME_MAIN = 'composer.json';
/**
* Returns value from composer.json file
*
* @param string $composerJsonPath Path of composer.json file
* @param string $nodeName Name of node who value should be returned
- * @return string|null
+ * @return null|string
*/
- public static function getValue($composerJsonPath, $nodeName)
+ public static function getValue(string $composerJsonPath, string $nodeName): ?string
{
- $composerJsonString = is_string($composerJsonPath);
- $composerJsonReadable = false;
-
- if ($composerJsonString) {
- $composerJsonReadable = is_readable($composerJsonPath);
- }
+ $composerJsonReadable = is_readable($composerJsonPath);
/*
* Provided path or name of node are invalid?
@@ -48,12 +41,12 @@ class Composer
*
* Nothing to do
*/
- if (!$composerJsonString || !is_string($nodeName) || !$composerJsonReadable || empty($nodeName)) {
+ if (!$composerJsonReadable || empty($nodeName)) {
return null;
}
$content = file_get_contents($composerJsonPath);
- $data = json_decode($content);
+ $data = json_decode($content, false);
/*
* Unknown data from the composer.json file or there is no node with given name?
@@ -63,7 +56,6 @@ class Composer
return null;
}
- /* @var stdClass $data */
return $data->{$nodeName};
}
}
diff --git a/src/Utilities/Date.php b/src/Utilities/Date.php
index b6f33c4..0f501b0 100644
--- a/src/Utilities/Date.php
+++ b/src/Utilities/Date.php
@@ -29,7 +29,7 @@ class Date
*
* @var string
*/
- const DATE_DIFFERENCE_UNIT_DAYS = 'days';
+ public const DATE_DIFFERENCE_UNIT_DAYS = 'days';
/**
* The 'hours' unit of date difference.
@@ -37,7 +37,7 @@ class Date
*
* @var string
*/
- const DATE_DIFFERENCE_UNIT_HOURS = 'hours';
+ public const DATE_DIFFERENCE_UNIT_HOURS = 'hours';
/**
* The 'minutes' unit of date difference.
@@ -45,7 +45,7 @@ class Date
*
* @var string
*/
- const DATE_DIFFERENCE_UNIT_MINUTES = 'minutes';
+ public const DATE_DIFFERENCE_UNIT_MINUTES = 'minutes';
/**
* The 'months' unit of date difference.
@@ -53,7 +53,7 @@ class Date
*
* @var string
*/
- const DATE_DIFFERENCE_UNIT_MONTHS = 'months';
+ public const DATE_DIFFERENCE_UNIT_MONTHS = 'months';
/**
* The 'years' unit of date difference.
@@ -61,131 +61,16 @@ class Date
*
* @var string
*/
- const DATE_DIFFERENCE_UNIT_YEARS = 'years';
-
- /**
- * Returns date's period (that contains start and end date) for given period
- *
- * @param int $period The period, type of period. One of DatePeriod class constants, e.g. DatePeriod::LAST_WEEK.
- * @throws Exception
- * @return null|DatePeriod
- */
- public static function getDatesForPeriod($period)
- {
- /*
- * Type of period is incorrect?
- * Nothing to do
- */
- if (!(new DatePeriod())->isCorrectType($period)) {
- return null;
- }
-
- $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);
-
- if (null !== $lastMonth) {
- $dateStart = $lastMonth->getEndDate();
- $dateStart->add(new DateInterval('P1D'));
- }
-
- if (null !== $nextMonth) {
- $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();
-
- $yearPeriod = [
- DatePeriod::LAST_YEAR,
- DatePeriod::NEXT_YEAR,
- ];
-
- if (in_array($period, $yearPeriod, true)) {
- $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;
- }
-
- /*
- * Start or end date is unknown?
- * Nothing to do
- */
- if (null === $dateStart || null === $dateEnd) {
- return null;
- }
-
- $dateStart->setTime(0, 0);
- $dateEnd->setTime(23, 59, 59);
-
- return new DatePeriod($dateStart, $dateEnd);
- }
+ public const DATE_DIFFERENCE_UNIT_YEARS = 'years';
/**
* 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
+ * @return null|string
*/
- public static function generateRandomTime($format = 'H:i:s')
+ public static function generateRandomTime($format = 'H:i:s'): ?string
{
$dateTime = new DateTime();
@@ -213,9 +98,7 @@ class Date
$seconds[] = $i;
}
- /*
- * Prepare random time (hour, minute and second)
- */
+ // Prepare random time (hour, minute and second)
$hour = $hours[array_rand($hours)];
$minute = $minutes[array_rand($minutes)];
$second = $seconds[array_rand($seconds)];
@@ -223,7 +106,7 @@ class Date
return $dateTime
->setTime($hour, $minute, $second)
->format($format)
- ;
+ ;
}
/**
@@ -231,113 +114,33 @@ class Date
*
* @return int
*/
- public static function getCurrentDayOfWeek()
+ public static function getCurrentDayOfWeek(): int
{
$now = new DateTime();
- $year = $now->format('Y');
- $month = $now->format('m');
- $day = $now->format('d');
+ $year = (int) $now->format('Y');
+ $month = (int) $now->format('m');
+ $day = (int) $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
- *
- * @throws UnknownDatePartTypeException
- * @return int
- */
- public static function getDayOfWeek($year, $month, $day)
- {
- $year = (int)$year;
- $month = (int)$month;
- $day = (int)$day;
-
- /*
- * Oops, incorrect year
- */
- if ($year <= 0) {
- throw UnknownDatePartTypeException::createException(DatePartType::YEAR, $year);
- }
-
- /*
- * Oops, incorrect month
- */
- if ($month < 1 || $month > 12) {
- throw UnknownDatePartTypeException::createException(DatePartType::MONTH, $month);
- }
-
- /*
- * Oops, incorrect day
- */
- if ($day < 1 || $day > 31) {
- throw UnknownDatePartTypeException::createException(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()
+ public static function getCurrentDayOfWeekName(): string
{
$now = new DateTime();
- $year = $now->format('Y');
- $month = $now->format('m');
- $day = $now->format('d');
+ $year = (int) $now->format('Y');
+ $month = (int) $now->format('m');
+ $day = (int) $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.
*
@@ -353,8 +156,8 @@ class Date
* 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 DateTime|string $dateStart The start date
+ * @param DateTime|string $dateEnd The end date
* @param string $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.
@@ -398,26 +201,26 @@ class Date
self::DATE_DIFFERENCE_UNIT_MINUTES,
];
- if (null === $differenceUnit || self::DATE_DIFFERENCE_UNIT_YEARS === $differenceUnit) {
+ $differenceYear = self::DATE_DIFFERENCE_UNIT_YEARS === $differenceUnit;
+ $differenceMonth = self::DATE_DIFFERENCE_UNIT_MONTHS === $differenceUnit;
+ $differenceMinutes = self::DATE_DIFFERENCE_UNIT_MINUTES === $differenceUnit;
+
+ if (null === $differenceUnit || $differenceYear) {
$diff = $end->diff($start);
- /*
- * Difference between dates in years should be returned only?
- */
- if (self::DATE_DIFFERENCE_UNIT_YEARS === $differenceUnit) {
+ // Difference between dates in years should be returned only?
+ if ($differenceYear) {
return $diff->y;
}
$difference[self::DATE_DIFFERENCE_UNIT_YEARS] = $diff->y;
}
- if (null === $differenceUnit || self::DATE_DIFFERENCE_UNIT_MONTHS === $differenceUnit) {
+ if (null === $differenceUnit || $differenceMonth) {
$diff = $end->diff($start);
- /*
- * Difference between dates in months should be returned only?
- */
- if (self::DATE_DIFFERENCE_UNIT_MONTHS === $differenceUnit) {
+ // Difference between dates in months should be returned only?
+ if ($differenceMonth) {
return $diff->m;
}
@@ -425,58 +228,44 @@ class Date
}
if (null === $differenceUnit || in_array($differenceUnit, $relatedUnits, true)) {
- $days = (int)floor($dateDiff / $daySeconds);
+ $days = (int) floor($dateDiff / $daySeconds);
- /*
- * Difference between dates in days should be returned only?
- */
+ // Difference between dates in days should be returned only?
if (self::DATE_DIFFERENCE_UNIT_DAYS === $differenceUnit) {
return $days;
}
- /*
- * All units should be returned?
- */
+ // All units should be returned?
if (null === $differenceUnit) {
$difference[self::DATE_DIFFERENCE_UNIT_DAYS] = $days;
}
- /*
- * Calculation for later usage
- */
+ // Calculation for later usage
$daysInSeconds = $days * $daySeconds;
}
if (null === $differenceUnit || in_array($differenceUnit, $relatedUnits, true)) {
- $hours = (int)floor(($dateDiff - $daysInSeconds) / $hourSeconds);
+ $hours = (int) floor(($dateDiff - $daysInSeconds) / $hourSeconds);
- /*
- * Difference between dates in hours should be returned only?
- */
+ // Difference between dates in hours should be returned only?
if (self::DATE_DIFFERENCE_UNIT_HOURS === $differenceUnit) {
return $hours;
}
- /*
- * All units should be returned?
- */
+ // All units should be returned?
if (null === $differenceUnit) {
$difference[self::DATE_DIFFERENCE_UNIT_HOURS] = $hours;
}
- /*
- * Calculation for later usage
- */
+ // Calculation for later usage
$hoursInSeconds = $hours * $hourSeconds;
}
- if (null === $differenceUnit || self::DATE_DIFFERENCE_UNIT_MINUTES === $differenceUnit) {
- $minutes = (int)floor(($dateDiff - $daysInSeconds - $hoursInSeconds) / 60);
+ if (null === $differenceUnit || $differenceMinutes) {
+ $minutes = (int) floor(($dateDiff - $daysInSeconds - $hoursInSeconds) / 60);
- /*
- * Difference between dates in minutes should be returned only?
- */
- if (self::DATE_DIFFERENCE_UNIT_MINUTES === $differenceUnit) {
+ // Difference between dates in minutes should be returned only?
+ if ($differenceMinutes) {
return $minutes;
}
@@ -486,91 +275,6 @@ class Date
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.
- * @throws Exception
- * @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 (optional) Beginning of the random date. If not provided, current date will
- * be used (default behaviour).
- * @param int $start (optional) Start of random partition. If not provided, 1 will be used
- * (default behaviour).
- * @param int $end (optional) End of random partition. If not provided, 100 will be used
- * (default behaviour).
- * @param string $intervalTemplate (optional) Template used to build date interval. The placeholder is replaced
- * with next, iterated value. If not provided, "P%sD" will be used (default
- * behaviour).
- * @throws Exception
- * @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, mt_rand($start, $end)));
-
- return $randomDate->add($randomInterval);
- }
-
/**
* Returns the DateTime object for given value.
* If the DateTime object cannot be created, false is returned.
@@ -583,7 +287,7 @@ class Date
* @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. Default: "Y-m-d".
- * @return DateTime|bool
+ * @return bool|DateTime
*/
public static function getDateTime($value, $allowCompoundFormats = false, $dateFormat = 'Y-m-d')
{
@@ -658,12 +362,10 @@ class Date
* 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;
- }
+ elseif ($dateFromFormat->format($dateFormat) === $value) {
+ return $date;
}
- } catch (\Exception $exception) {
+ } catch (Exception $exception) {
if (!$allowCompoundFormats) {
return false;
}
@@ -675,15 +377,284 @@ class Date
*/
$dateString = (new DateTime())->format($value);
- if ($dateString !== (string)$value) {
+ if ($dateString !== (string) $value) {
return new DateTime($dateString);
}
- } catch (\Exception $exception) {
+ } catch (Exception $exception) {
}
return false;
}
+ /**
+ * 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
+ * @throws Exception
+ */
+ public static function getDatesCollection(DateTime $startDate, $datesCount, $intervalTemplate = 'P%dD'): array
+ {
+ $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 date's period (that contains start and end date) for given period
+ *
+ * @param string $period The period, type of period. One of DatePeriod class constants, e.g. DatePeriod::LAST_WEEK.
+ * @return null|DatePeriod
+ * @throws Exception
+ */
+ public static function getDatesForPeriod(string $period): ?DatePeriod
+ {
+ /*
+ * Type of period is incorrect?
+ * Nothing to do
+ */
+ if (!DatePeriod::isCorrectType($period)) {
+ return null;
+ }
+
+ $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);
+
+ if (null !== $lastMonth) {
+ $dateStart = $lastMonth->getEndDate();
+
+ if (null !== $dateStart) {
+ $dateStart->add(new DateInterval('P1D'));
+ }
+ }
+
+ if (null !== $nextMonth) {
+ $dateEnd = $nextMonth->getStartDate();
+
+ if (null !== $dateEnd) {
+ $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();
+
+ $yearPeriod = [
+ DatePeriod::LAST_YEAR,
+ DatePeriod::NEXT_YEAR,
+ ];
+
+ if (in_array($period, $yearPeriod, true)) {
+ $yearDifference = 1;
+
+ if (DatePeriod::LAST_YEAR === $period) {
+ $yearDifference *= -1;
+ }
+
+ $modifyString = sprintf('%s year', $yearDifference);
+ $dateStart->modify($modifyString);
+ $dateEnd->modify($modifyString);
+ }
+
+ $year = (int) $dateStart->format('Y');
+ $dateStart->setDate($year, 1, 1);
+ $dateEnd->setDate($year, 12, 31);
+
+ break;
+ }
+
+ /*
+ * Start or end date is unknown?
+ * Nothing to do
+ */
+ if (null === $dateStart || null === $dateEnd) {
+ return null;
+ }
+
+ $dateStart->setTime(0, 0);
+ $dateEnd->setTime(23, 59, 59);
+
+ return new DatePeriod($dateStart, $dateEnd);
+ }
+
+ /**
+ * Returns day of week (number 0 to 6, 0 - sunday, 6 - saturday).
+ * Based on the Zeller's algorithm (https://en.wikipedia.org/wiki/Perpetual_calendar).
+ *
+ * @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(int $year, int $month, int $day): int
+ {
+ static::validateYear($year);
+ static::validateMonth($month);
+ static::validateDay($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 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): string
+ {
+ $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 random date based on given start date
+ *
+ * @param DateTime $startDate (optional) Beginning of the random date. If not provided, current date will
+ * be used (default behaviour).
+ * @param int $start (optional) Start of random partition. If not provided, 1 will be used
+ * (default behaviour).
+ * @param int $end (optional) End of random partition. If not provided, 100 will be used
+ * (default behaviour).
+ * @param string $intervalTemplate (optional) Template used to build date interval. The placeholder is replaced
+ * with next, iterated value. If not provided, "P%sD" will be used (default
+ * behaviour).
+ * @return DateTime
+ * @throws Exception
+ */
+ public static function getRandomDate(
+ DateTime $startDate = null,
+ $start = 1,
+ $end = 100,
+ $intervalTemplate = 'P%sD'
+ ): DateTime {
+ 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, random_int($start, $end)));
+
+ return $randomDate->add($randomInterval);
+ }
+
/**
* Returns information if given value is valid date
*
@@ -693,7 +664,7 @@ class Date
* month", "yyyy"). Otherwise - not and every incorrect value is refused.
* @return bool
*/
- public static function isValidDate($value, $allowCompoundFormats = false)
+ public static function isValidDate($value, $allowCompoundFormats = false): bool
{
return self::getDateTime($value, $allowCompoundFormats) instanceof DateTime;
}
@@ -704,38 +675,77 @@ class Date
* @param string $format The validated format of date
* @return bool
*/
- public static function isValidDateFormat($format)
+ public static function isValidDateFormat($format): bool
{
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
- */
+ // 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
- */
+ // Validate the format used to create the datetime
$fromFormat = DateTime::createFromFormat($format, $formatted);
- /*
- * It's instance of DateTime?
- * The format is valid
- */
+ // It's instance of DateTime?
+ // The format is valid
if ($fromFormat instanceof DateTime) {
return true;
}
return $fromFormat instanceof DateTime;
}
+
+ /**
+ * Verifies/validates given day
+ *
+ * @param int $day Day to verify/validate
+ * @throws UnknownDatePartTypeException
+ */
+ private static function validateDay(int $day): void
+ {
+ // Oops, given day is incorrect
+ if ($day >= 1 && $day <= 31) {
+ return;
+ }
+
+ throw UnknownDatePartTypeException::createException(DatePartType::DAY, $day);
+ }
+
+ /**
+ * Verifies/validates given month
+ *
+ * @param int $month Month to verify/validate
+ * @throws UnknownDatePartTypeException
+ */
+ private static function validateMonth(int $month): void
+ {
+ // Oops, given month is incorrect
+ if ($month >= 1 && $month <= 12) {
+ return;
+ }
+
+ throw UnknownDatePartTypeException::createException(DatePartType::MONTH, $month);
+ }
+
+ /**
+ * Verifies/validates given year
+ *
+ * @param int $year Year to verify/validate
+ * @throws UnknownDatePartTypeException
+ */
+ private static function validateYear(int $year): void
+ {
+ // Oops, given year is incorrect
+ if ($year >= 0) {
+ return;
+ }
+
+ throw UnknownDatePartTypeException::createException(DatePartType::YEAR, $year);
+ }
}
diff --git a/src/Utilities/Locale.php b/src/Utilities/Locale.php
index 770c01b..b7f7787 100644
--- a/src/Utilities/Locale.php
+++ b/src/Utilities/Locale.php
@@ -16,51 +16,6 @@ namespace Meritoo\Common\Utilities;
*/
class Locale
{
- /**
- * Sets locale for given category using given language and country code
- *
- * @param int $category Named constant specifying the category of the functions affected by the locale
- * setting. It's the same constant as required by setlocale() function.
- * @param string $languageCode Language code, in ISO 639-1 format. Short form of the locale, e.g. "fr".
- * @param string $countryCode (optional) Country code, in ISO 3166-1 alpha-2 format, e.g. "FR"
- * @return false|string
- *
- * Available categories (values of $category argument):
- * - LC_ALL for all of the below
- * - LC_COLLATE for string comparison, see strcoll()
- * - LC_CTYPE for character classification and conversion, for example strtoupper()
- * - LC_MONETARY for localeconv()
- * - LC_NUMERIC for decimal separator (See also localeconv())
- * - LC_TIME for date and time formatting with strftime()
- * - LC_MESSAGES for system responses (available if PHP was compiled with libintl)
- */
- public static function setLocale($category, $languageCode, $countryCode = '')
- {
- $category = (int)$category;
-
- if (is_string($languageCode)) {
- $languageCode = trim($languageCode);
- }
-
- $availableCategories = [
- LC_ALL,
- LC_COLLATE,
- LC_CTYPE,
- LC_MONETARY,
- LC_NUMERIC,
- LC_TIME,
- LC_MESSAGES,
- ];
-
- if (empty($languageCode) || !in_array($category, $availableCategories, true)) {
- return false;
- }
-
- $localeLongForm = self::getLongForm($languageCode, $countryCode);
-
- return setlocale($category, $localeLongForm);
- }
-
/**
* Returns locale for given category
*
@@ -123,4 +78,49 @@ class Locale
return sprintf('%s_%s%s', $languageCode, strtoupper($countryCode), $encoding);
}
+
+ /**
+ * Sets locale for given category using given language and country code
+ *
+ * @param int $category Named constant specifying the category of the functions affected by the locale
+ * setting. It's the same constant as required by setlocale() function.
+ * @param string $languageCode Language code, in ISO 639-1 format. Short form of the locale, e.g. "fr".
+ * @param string $countryCode (optional) Country code, in ISO 3166-1 alpha-2 format, e.g. "FR"
+ * @return false|string
+ *
+ * Available categories (values of $category argument):
+ * - LC_ALL for all of the below
+ * - LC_COLLATE for string comparison, see strcoll()
+ * - LC_CTYPE for character classification and conversion, for example strtoupper()
+ * - LC_MONETARY for localeconv()
+ * - LC_NUMERIC for decimal separator (See also localeconv())
+ * - LC_TIME for date and time formatting with strftime()
+ * - LC_MESSAGES for system responses (available if PHP was compiled with libintl)
+ */
+ public static function setLocale($category, $languageCode, $countryCode = '')
+ {
+ $category = (int) $category;
+
+ if (is_string($languageCode)) {
+ $languageCode = trim($languageCode);
+ }
+
+ $availableCategories = [
+ LC_ALL,
+ LC_COLLATE,
+ LC_CTYPE,
+ LC_MONETARY,
+ LC_NUMERIC,
+ LC_TIME,
+ LC_MESSAGES,
+ ];
+
+ if (empty($languageCode) || !in_array($category, $availableCategories, true)) {
+ return false;
+ }
+
+ $localeLongForm = self::getLongForm($languageCode, $countryCode);
+
+ return setlocale($category, $localeLongForm);
+ }
}
diff --git a/src/Utilities/MimeTypes.php b/src/Utilities/MimeTypes.php
index 2c02b10..f300738 100644
--- a/src/Utilities/MimeTypes.php
+++ b/src/Utilities/MimeTypes.php
@@ -8,6 +8,9 @@
namespace Meritoo\Common\Utilities;
+use finfo;
+use RuntimeException;
+
/**
* Useful methods for mime types of files
*
@@ -22,663 +25,680 @@ class MimeTypes
* @var array
*/
private static $mimeTypes = [
- '7z' => 'application/x-7z-compressed',
- 'ez' => 'application/andrew-inset',
- 'atom' => 'application/atom+xml',
- 'atomcat' => 'application/atomcat+xml',
- 'atomsvc' => 'application/atomsvc+xml',
- 'ccxml' => 'application/ccxml+xml',
- 'davmount' => 'application/davmount+xml',
- 'ecma' => 'application/ecmascript',
- 'pfr' => 'application/font-tdpfr',
- 'stk' => 'application/hyperstudio',
- 'js' => 'application/javascript',
- 'json' => 'application/json',
- 'hqx' => 'application/mac-binhex40',
- 'cpt' => 'application/mac-compactpro',
- 'mrc' => 'application/marc',
- 'ma' => 'application/mathematica',
- 'nb' => 'application/mathematica',
- 'mb' => 'application/mathematica',
- 'mathml' => 'application/mathml+xml',
- 'mbox' => 'application/mbox',
- 'mscml' => 'application/mediaservercontrol+xml',
- 'mp4s' => 'application/mp4',
- 'dot' => 'application/msword',
- 'doc' => 'application/msword',
+ '7z' => 'application/x-7z-compressed',
+ 'ez' => 'application/andrew-inset',
+ 'atom' => 'application/atom+xml',
+ 'atomcat' => 'application/atomcat+xml',
+ 'atomsvc' => 'application/atomsvc+xml',
+ 'ccxml' => 'application/ccxml+xml',
+ 'davmount' => 'application/davmount+xml',
+ 'ecma' => 'application/ecmascript',
+ 'pfr' => 'application/font-tdpfr',
+ 'stk' => 'application/hyperstudio',
+ 'js' => 'application/javascript',
+ 'json' => 'application/json',
+ 'hqx' => 'application/mac-binhex40',
+ 'cpt' => 'application/mac-compactpro',
+ 'mrc' => 'application/marc',
+ 'ma' => 'application/mathematica',
+ 'nb' => 'application/mathematica',
+ 'mb' => 'application/mathematica',
+ 'mathml' => 'application/mathml+xml',
+ 'mbox' => 'application/mbox',
+ 'mscml' => 'application/mediaservercontrol+xml',
+ 'mp4s' => 'application/mp4',
+ 'dot' => 'application/msword',
+ 'doc' => 'application/msword',
/*
* MS Office system file format MIME types
* http://technet.microsoft.com/en-us/library/ee309278%28office.12%29.aspx
*/
- 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
- 'mxf' => 'application/mxf',
- 'bin' => 'application/octet-stream',
- 'dms' => 'application/octet-stream',
- 'lha' => 'application/octet-stream',
- 'lzh' => 'application/octet-stream',
- 'class' => 'application/octet-stream',
- 'so' => 'application/octet-stream',
- 'iso' => 'application/octet-stream',
- 'dmg' => 'application/octet-stream',
- 'dist' => 'application/octet-stream',
- 'distz' => 'application/octet-stream',
- 'pkg' => 'application/octet-stream',
- 'bpk' => 'application/octet-stream',
- 'dump' => 'application/octet-stream',
- 'elc' => 'application/octet-stream',
- 'scpt' => 'application/octet-stream',
- 'oda' => 'application/oda',
- 'ogg' => 'application/ogg',
- 'pdf' => 'application/pdf',
- 'pgp' => 'application/pgp-encrypted',
- 'asc' => 'application/pgp-signature',
- 'sig' => 'application/pgp-signature',
- 'prf' => 'application/pics-rules',
- 'p10' => 'application/pkcs10',
- 'p7m' => 'application/pkcs7-mime',
- 'p7c' => 'application/pkcs7-mime',
- 'p7s' => 'application/pkcs7-signature',
- 'cer' => 'application/pkix-cert',
- 'crl' => 'application/pkix-crl',
- 'pkipath' => 'application/pkix-pkipath',
- 'pki' => 'application/pkixcmp',
- 'pls' => 'application/pls+xml',
- 'ai' => 'application/postscript',
- 'eps' => 'application/postscript',
- 'ps' => 'application/postscript',
- 'cww' => 'application/prs.cww',
- 'rdf' => 'application/rdf+xml',
- 'rif' => 'application/reginfo+xml',
- 'rnc' => 'application/relax-ng-compact-syntax',
- 'rl' => 'application/resource-lists+xml',
- 'rs' => 'application/rls-services+xml',
- 'rsd' => 'application/rsd+xml',
- 'rss' => 'application/rss+xml',
- 'rtf' => 'application/rtf',
- 'sbml' => 'application/sbml+xml',
- 'sdp' => 'application/sdp',
- 'setpay' => 'application/set-payment-initiation',
- 'setreg' => 'application/set-registration-initiation',
- 'shf' => 'application/shf+xml',
- 'smi' => 'application/smil+xml',
- 'smil' => 'application/smil+xml',
- 'gram' => 'application/srgs',
- 'grxml' => 'application/srgs+xml',
- 'ssml' => 'application/ssml+xml',
- 'plb' => 'application/vnd.3gpp.pic-bw-large',
- 'psb' => 'application/vnd.3gpp.pic-bw-small',
- 'pvb' => 'application/vnd.3gpp.pic-bw-var',
- 'pwn' => 'application/vnd.3m.post-it-notes',
- 'aso' => 'application/vnd.accpac.simply.aso',
- 'imp' => 'application/vnd.accpac.simply.imp',
- 'acu' => 'application/vnd.acucobol',
- 'atc' => 'application/vnd.acucorp',
- 'acutc' => 'application/vnd.acucorp',
- 'xdp' => 'application/vnd.adobe.xdp+xml',
- 'xfdf' => 'application/vnd.adobe.xfdf',
- 'ami' => 'application/vnd.amiga.ami',
- 'cii' => 'application/vnd.anser-web-certificate-issue-initiation',
- 'fti' => 'application/vnd.anser-web-funds-transfer-initiation',
- 'atx' => 'application/vnd.antix.game-component',
- 'mpkg' => 'application/vnd.apple.installer+xml',
- 'aep' => 'application/vnd.audiograph',
- 'mpm' => 'application/vnd.blueice.multipass',
- 'bmi' => 'application/vnd.bmi',
- 'rep' => 'application/vnd.businessobjects',
- 'cdxml' => 'application/vnd.chemdraw+xml',
- 'mmd' => 'application/vnd.chipnuts.karaoke-mmd',
- 'cdy' => 'application/vnd.cinderella',
- 'cla' => 'application/vnd.claymore',
- 'c4g' => 'application/vnd.clonk.c4group',
- 'c4d' => 'application/vnd.clonk.c4group',
- 'c4f' => 'application/vnd.clonk.c4group',
- 'c4p' => 'application/vnd.clonk.c4group',
- 'c4u' => 'application/vnd.clonk.c4group',
- 'csp' => 'application/vnd.commonspace',
- 'cst' => 'application/vnd.commonspace',
- 'cdbcmsg' => 'application/vnd.contact.cmsg',
- 'cmc' => 'application/vnd.cosmocaller',
- 'clkx' => 'application/vnd.crick.clicker',
- 'clkk' => 'application/vnd.crick.clicker.keyboard',
- 'clkp' => 'application/vnd.crick.clicker.palette',
- 'clkt' => 'application/vnd.crick.clicker.template',
- 'clkw' => 'application/vnd.crick.clicker.wordbank',
- 'wbs' => 'application/vnd.criticaltools.wbs+xml',
- 'pml' => 'application/vnd.ctc-posml',
- 'ppd' => 'application/vnd.cups-ppd',
- 'curl' => 'application/vnd.curl',
- 'rdz' => 'application/vnd.data-vision.rdz',
- 'dna' => 'application/vnd.dna',
- 'mlp' => 'application/vnd.dolby.mlp',
- 'dpg' => 'application/vnd.dpgraph',
- 'dfac' => 'application/vnd.dreamfactory',
- 'mag' => 'application/vnd.ecowin.chart',
- 'nml' => 'application/vnd.enliven',
- 'esf' => 'application/vnd.epson.esf',
- 'msf' => 'application/vnd.epson.msf',
- 'qam' => 'application/vnd.epson.quickanime',
- 'slt' => 'application/vnd.epson.salt',
- 'ssf' => 'application/vnd.epson.ssf',
- 'es3' => 'application/vnd.eszigno3+xml',
- 'et3' => 'application/vnd.eszigno3+xml',
- 'ez2' => 'application/vnd.ezpix-album',
- 'ez3' => 'application/vnd.ezpix-package',
- 'fdf' => 'application/vnd.fdf',
- 'gph' => 'application/vnd.flographit',
- 'ftc' => 'application/vnd.fluxtime.clip',
- 'fm' => 'application/vnd.framemaker',
- 'frame' => 'application/vnd.framemaker',
- 'maker' => 'application/vnd.framemaker',
- 'fnc' => 'application/vnd.frogans.fnc',
- 'ltf' => 'application/vnd.frogans.ltf',
- 'fsc' => 'application/vnd.fsc.weblaunch',
- 'oas' => 'application/vnd.fujitsu.oasys',
- 'oa2' => 'application/vnd.fujitsu.oasys2',
- 'oa3' => 'application/vnd.fujitsu.oasys3',
- 'fg5' => 'application/vnd.fujitsu.oasysgp',
- 'bh2' => 'application/vnd.fujitsu.oasysprs',
- 'ddd' => 'application/vnd.fujixerox.ddd',
- 'xdw' => 'application/vnd.fujixerox.docuworks',
- 'xbd' => 'application/vnd.fujixerox.docuworks.binder',
- 'fzs' => 'application/vnd.fuzzysheet',
- 'txd' => 'application/vnd.genomatix.tuxedo',
- 'kml' => 'application/vnd.google-earth.kml+xml',
- 'kmz' => 'application/vnd.google-earth.kmz',
- 'gqf' => 'application/vnd.grafeq',
- 'gqs' => 'application/vnd.grafeq',
- 'gac' => 'application/vnd.groove-account',
- 'ghf' => 'application/vnd.groove-help',
- 'gim' => 'application/vnd.groove-identity-message',
- 'grv' => 'application/vnd.groove-injector',
- 'gtm' => 'application/vnd.groove-tool-message',
- 'tpl' => 'application/vnd.groove-tool-template',
- 'vcg' => 'application/vnd.groove-vcard',
- 'zmm' => 'application/vnd.handheld-entertainment+xml',
- 'hbci' => 'application/vnd.hbci',
- 'les' => 'application/vnd.hhe.lesson-player',
- 'hpgl' => 'application/vnd.hp-hpgl',
- 'hpid' => 'application/vnd.hp-hpid',
- 'hps' => 'application/vnd.hp-hps',
- 'jlt' => 'application/vnd.hp-jlyt',
- 'pcl' => 'application/vnd.hp-pcl',
- 'pclxl' => 'application/vnd.hp-pclxl',
- 'x3d' => 'application/vnd.hzn-3d-crossword',
- 'mpy' => 'application/vnd.ibm.minipay',
- 'afp' => 'application/vnd.ibm.modcap',
- 'listafp' => 'application/vnd.ibm.modcap',
- 'list3820' => 'application/vnd.ibm.modcap',
- 'irm' => 'application/vnd.ibm.rights-management',
- 'sc' => 'application/vnd.ibm.secure-container',
- 'igl' => 'application/vnd.igloader',
- 'ivp' => 'application/vnd.immervision-ivp',
- 'ivu' => 'application/vnd.immervision-ivu',
- 'xpw' => 'application/vnd.intercon.formnet',
- 'xpx' => 'application/vnd.intercon.formnet',
- 'qbo' => 'application/vnd.intu.qbo',
- 'qfx' => 'application/vnd.intu.qfx',
+ 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
+ 'mxf' => 'application/mxf',
+ 'bin' => 'application/octet-stream',
+ 'dms' => 'application/octet-stream',
+ 'lha' => 'application/octet-stream',
+ 'lzh' => 'application/octet-stream',
+ 'class' => 'application/octet-stream',
+ 'so' => 'application/octet-stream',
+ 'iso' => 'application/octet-stream',
+ 'dmg' => 'application/octet-stream',
+ 'dist' => 'application/octet-stream',
+ 'distz' => 'application/octet-stream',
+ 'pkg' => 'application/octet-stream',
+ 'bpk' => 'application/octet-stream',
+ 'dump' => 'application/octet-stream',
+ 'elc' => 'application/octet-stream',
+ 'scpt' => 'application/octet-stream',
+ 'oda' => 'application/oda',
+ 'ogg' => 'application/ogg',
+ 'pdf' => 'application/pdf',
+ 'pgp' => 'application/pgp-encrypted',
+ 'asc' => 'application/pgp-signature',
+ 'sig' => 'application/pgp-signature',
+ 'prf' => 'application/pics-rules',
+ 'p10' => 'application/pkcs10',
+ 'p7m' => 'application/pkcs7-mime',
+ 'p7c' => 'application/pkcs7-mime',
+ 'p7s' => 'application/pkcs7-signature',
+ 'cer' => 'application/pkix-cert',
+ 'crl' => 'application/pkix-crl',
+ 'pkipath' => 'application/pkix-pkipath',
+ 'pki' => 'application/pkixcmp',
+ 'pls' => 'application/pls+xml',
+ 'ai' => 'application/postscript',
+ 'eps' => 'application/postscript',
+ 'ps' => 'application/postscript',
+ 'cww' => 'application/prs.cww',
+ 'rdf' => 'application/rdf+xml',
+ 'rif' => 'application/reginfo+xml',
+ 'rnc' => 'application/relax-ng-compact-syntax',
+ 'rl' => 'application/resource-lists+xml',
+ 'rs' => 'application/rls-services+xml',
+ 'rsd' => 'application/rsd+xml',
+ 'rss' => 'application/rss+xml',
+ 'rtf' => 'application/rtf',
+ 'sbml' => 'application/sbml+xml',
+ 'sdp' => 'application/sdp',
+ 'setpay' => 'application/set-payment-initiation',
+ 'setreg' => 'application/set-registration-initiation',
+ 'shf' => 'application/shf+xml',
+ 'smi' => 'application/smil+xml',
+ 'smil' => 'application/smil+xml',
+ 'gram' => 'application/srgs',
+ 'grxml' => 'application/srgs+xml',
+ 'ssml' => 'application/ssml+xml',
+ 'plb' => 'application/vnd.3gpp.pic-bw-large',
+ 'psb' => 'application/vnd.3gpp.pic-bw-small',
+ 'pvb' => 'application/vnd.3gpp.pic-bw-var',
+ 'pwn' => 'application/vnd.3m.post-it-notes',
+ 'aso' => 'application/vnd.accpac.simply.aso',
+ 'imp' => 'application/vnd.accpac.simply.imp',
+ 'acu' => 'application/vnd.acucobol',
+ 'atc' => 'application/vnd.acucorp',
+ 'acutc' => 'application/vnd.acucorp',
+ 'xdp' => 'application/vnd.adobe.xdp+xml',
+ 'xfdf' => 'application/vnd.adobe.xfdf',
+ 'ami' => 'application/vnd.amiga.ami',
+ 'cii' => 'application/vnd.anser-web-certificate-issue-initiation',
+ 'fti' => 'application/vnd.anser-web-funds-transfer-initiation',
+ 'atx' => 'application/vnd.antix.game-component',
+ 'mpkg' => 'application/vnd.apple.installer+xml',
+ 'aep' => 'application/vnd.audiograph',
+ 'mpm' => 'application/vnd.blueice.multipass',
+ 'bmi' => 'application/vnd.bmi',
+ 'rep' => 'application/vnd.businessobjects',
+ 'cdxml' => 'application/vnd.chemdraw+xml',
+ 'mmd' => 'application/vnd.chipnuts.karaoke-mmd',
+ 'cdy' => 'application/vnd.cinderella',
+ 'cla' => 'application/vnd.claymore',
+ 'c4g' => 'application/vnd.clonk.c4group',
+ 'c4d' => 'application/vnd.clonk.c4group',
+ 'c4f' => 'application/vnd.clonk.c4group',
+ 'c4p' => 'application/vnd.clonk.c4group',
+ 'c4u' => 'application/vnd.clonk.c4group',
+ 'csp' => 'application/vnd.commonspace',
+ 'cst' => 'application/vnd.commonspace',
+ 'cdbcmsg' => 'application/vnd.contact.cmsg',
+ 'cmc' => 'application/vnd.cosmocaller',
+ 'clkx' => 'application/vnd.crick.clicker',
+ 'clkk' => 'application/vnd.crick.clicker.keyboard',
+ 'clkp' => 'application/vnd.crick.clicker.palette',
+ 'clkt' => 'application/vnd.crick.clicker.template',
+ 'clkw' => 'application/vnd.crick.clicker.wordbank',
+ 'wbs' => 'application/vnd.criticaltools.wbs+xml',
+ 'pml' => 'application/vnd.ctc-posml',
+ 'ppd' => 'application/vnd.cups-ppd',
+ 'curl' => 'application/vnd.curl',
+ 'rdz' => 'application/vnd.data-vision.rdz',
+ 'dna' => 'application/vnd.dna',
+ 'mlp' => 'application/vnd.dolby.mlp',
+ 'dpg' => 'application/vnd.dpgraph',
+ 'dfac' => 'application/vnd.dreamfactory',
+ 'mag' => 'application/vnd.ecowin.chart',
+ 'nml' => 'application/vnd.enliven',
+ 'esf' => 'application/vnd.epson.esf',
+ 'msf' => 'application/vnd.epson.msf',
+ 'qam' => 'application/vnd.epson.quickanime',
+ 'slt' => 'application/vnd.epson.salt',
+ 'ssf' => 'application/vnd.epson.ssf',
+ 'es3' => 'application/vnd.eszigno3+xml',
+ 'et3' => 'application/vnd.eszigno3+xml',
+ 'ez2' => 'application/vnd.ezpix-album',
+ 'ez3' => 'application/vnd.ezpix-package',
+ 'fdf' => 'application/vnd.fdf',
+ 'gph' => 'application/vnd.flographit',
+ 'ftc' => 'application/vnd.fluxtime.clip',
+ 'fm' => 'application/vnd.framemaker',
+ 'frame' => 'application/vnd.framemaker',
+ 'maker' => 'application/vnd.framemaker',
+ 'fnc' => 'application/vnd.frogans.fnc',
+ 'ltf' => 'application/vnd.frogans.ltf',
+ 'fsc' => 'application/vnd.fsc.weblaunch',
+ 'oas' => 'application/vnd.fujitsu.oasys',
+ 'oa2' => 'application/vnd.fujitsu.oasys2',
+ 'oa3' => 'application/vnd.fujitsu.oasys3',
+ 'fg5' => 'application/vnd.fujitsu.oasysgp',
+ 'bh2' => 'application/vnd.fujitsu.oasysprs',
+ 'ddd' => 'application/vnd.fujixerox.ddd',
+ 'xdw' => 'application/vnd.fujixerox.docuworks',
+ 'xbd' => 'application/vnd.fujixerox.docuworks.binder',
+ 'fzs' => 'application/vnd.fuzzysheet',
+ 'txd' => 'application/vnd.genomatix.tuxedo',
+ 'kml' => 'application/vnd.google-earth.kml+xml',
+ 'kmz' => 'application/vnd.google-earth.kmz',
+ 'gqf' => 'application/vnd.grafeq',
+ 'gqs' => 'application/vnd.grafeq',
+ 'gac' => 'application/vnd.groove-account',
+ 'ghf' => 'application/vnd.groove-help',
+ 'gim' => 'application/vnd.groove-identity-message',
+ 'grv' => 'application/vnd.groove-injector',
+ 'gtm' => 'application/vnd.groove-tool-message',
+ 'tpl' => 'application/vnd.groove-tool-template',
+ 'vcg' => 'application/vnd.groove-vcard',
+ 'zmm' => 'application/vnd.handheld-entertainment+xml',
+ 'hbci' => 'application/vnd.hbci',
+ 'les' => 'application/vnd.hhe.lesson-player',
+ 'hpgl' => 'application/vnd.hp-hpgl',
+ 'hpid' => 'application/vnd.hp-hpid',
+ 'hps' => 'application/vnd.hp-hps',
+ 'jlt' => 'application/vnd.hp-jlyt',
+ 'pcl' => 'application/vnd.hp-pcl',
+ 'pclxl' => 'application/vnd.hp-pclxl',
+ 'x3d' => 'application/vnd.hzn-3d-crossword',
+ 'mpy' => 'application/vnd.ibm.minipay',
+ 'afp' => 'application/vnd.ibm.modcap',
+ 'listafp' => 'application/vnd.ibm.modcap',
+ 'list3820' => 'application/vnd.ibm.modcap',
+ 'irm' => 'application/vnd.ibm.rights-management',
+ 'sc' => 'application/vnd.ibm.secure-container',
+ 'igl' => 'application/vnd.igloader',
+ 'ivp' => 'application/vnd.immervision-ivp',
+ 'ivu' => 'application/vnd.immervision-ivu',
+ 'xpw' => 'application/vnd.intercon.formnet',
+ 'xpx' => 'application/vnd.intercon.formnet',
+ 'qbo' => 'application/vnd.intu.qbo',
+ 'qfx' => 'application/vnd.intu.qfx',
'rcprofile' => 'application/vnd.ipunplugged.rcprofile',
- 'irp' => 'application/vnd.irepository.package+xml',
- 'xpr' => 'application/vnd.is-xpr',
- 'jam' => 'application/vnd.jam',
- 'rms' => 'application/vnd.jcp.javame.midlet-rms',
- 'jisp' => 'application/vnd.jisp',
- 'ktz' => 'application/vnd.kahootz',
- 'ktr' => 'application/vnd.kahootz',
- 'karbon' => 'application/vnd.kde.karbon',
- 'chrt' => 'application/vnd.kde.kchart',
- 'kfo' => 'application/vnd.kde.kformula',
- 'flw' => 'application/vnd.kde.kivio',
- 'kon' => 'application/vnd.kde.kontour',
- 'kpr' => 'application/vnd.kde.kpresenter',
- 'kpt' => 'application/vnd.kde.kpresenter',
- 'ksp' => 'application/vnd.kde.kspread',
- 'kwd' => 'application/vnd.kde.kword',
- 'kwt' => 'application/vnd.kde.kword',
- 'htke' => 'application/vnd.kenameaapp',
- 'kia' => 'application/vnd.kidspiration',
- 'kne' => 'application/vnd.kinar',
- 'knp' => 'application/vnd.kinar',
- 'skp' => 'application/vnd.koan',
- 'skd' => 'application/vnd.koan',
- 'skt' => 'application/vnd.koan',
- 'skm' => 'application/vnd.koan',
- 'lbd' => 'application/vnd.llamagraphics.life-balance.desktop',
- 'lbe' => 'application/vnd.llamagraphics.life-balance.exchange+xml',
- '123' => 'application/vnd.lotus-1-2-3',
- 'apr' => 'application/vnd.lotus-approach',
- 'pre' => 'application/vnd.lotus-freelance',
- 'nsf' => 'application/vnd.lotus-notes',
- 'org' => 'application/vnd.lotus-organizer',
- 'scm' => 'application/vnd.lotus-screencam',
- 'lwp' => 'application/vnd.lotus-wordpro',
- 'portpkg' => 'application/vnd.macports.portpkg',
- 'mcd' => 'application/vnd.mcd',
- 'mc1' => 'application/vnd.medcalcdata',
- 'cdkey' => 'application/vnd.mediastation.cdkey',
- 'mwf' => 'application/vnd.mfer',
- 'mfm' => 'application/vnd.mfmp',
- 'flo' => 'application/vnd.micrografx.flo',
- 'igx' => 'application/vnd.micrografx.igx',
- 'mif' => 'application/vnd.mif',
- 'daf' => 'application/vnd.mobius.daf',
- 'dis' => 'application/vnd.mobius.dis',
- 'mbk' => 'application/vnd.mobius.mbk',
- 'mqy' => 'application/vnd.mobius.mqy',
- 'msl' => 'application/vnd.mobius.msl',
- 'plc' => 'application/vnd.mobius.plc',
- 'txf' => 'application/vnd.mobius.txf',
- 'mpn' => 'application/vnd.mophun.application',
- 'mpc' => 'application/vnd.mophun.certificate',
- 'xul' => 'application/vnd.mozilla.xul+xml',
- 'cil' => 'application/vnd.ms-artgalry',
- 'asf' => 'application/vnd.ms-asf',
- 'cab' => 'application/vnd.ms-cab-compressed',
- 'xls' => 'application/vnd.ms-excel',
- 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
- 'xlm' => 'application/vnd.ms-excel',
- 'xla' => 'application/vnd.ms-excel',
- 'xlc' => 'application/vnd.ms-excel',
- 'xlt' => 'application/vnd.ms-excel',
- 'xlw' => 'application/vnd.ms-excel',
- 'eot' => 'application/vnd.ms-fontobject',
- 'chm' => 'application/vnd.ms-htmlhelp',
- 'ims' => 'application/vnd.ms-ims',
- 'lrm' => 'application/vnd.ms-lrm',
- 'ppt' => 'application/vnd.ms-powerpoint',
- 'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
- 'pps' => 'application/vnd.ms-powerpoint',
- 'pot' => 'application/vnd.ms-powerpoint',
- 'mpp' => 'application/vnd.ms-project',
- 'mpt' => 'application/vnd.ms-project',
- 'wps' => 'application/vnd.ms-works',
- 'wks' => 'application/vnd.ms-works',
- 'wcm' => 'application/vnd.ms-works',
- 'wdb' => 'application/vnd.ms-works',
- 'wpl' => 'application/vnd.ms-wpl',
- 'xps' => 'application/vnd.ms-xpsdocument',
- 'mseq' => 'application/vnd.mseq',
- 'mus' => 'application/vnd.musician',
- 'nlu' => 'application/vnd.neurolanguage.nlu',
- 'nnd' => 'application/vnd.noblenet-directory',
- 'nns' => 'application/vnd.noblenet-sealer',
- 'nnw' => 'application/vnd.noblenet-web',
- 'ngdat' => 'application/vnd.nokia.n-gage.data',
- 'n-gage' => 'application/vnd.nokia.n-gage.symbian.install',
- 'rpst' => 'application/vnd.nokia.radio-preset',
- 'rpss' => 'application/vnd.nokia.radio-presets',
- 'edm' => 'application/vnd.novadigm.edm',
- 'edx' => 'application/vnd.novadigm.edx',
- 'ext' => 'application/vnd.novadigm.ext',
- 'odc' => 'application/vnd.oasis.opendocument.chart',
- 'otc' => 'application/vnd.oasis.opendocument.chart-template',
- 'odf' => 'application/vnd.oasis.opendocument.formula',
- 'otf' => 'application/vnd.oasis.opendocument.formula-template',
- 'odg' => 'application/vnd.oasis.opendocument.graphics',
- 'otg' => 'application/vnd.oasis.opendocument.graphics-template',
- 'odi' => 'application/vnd.oasis.opendocument.image',
- 'oti' => 'application/vnd.oasis.opendocument.image-template',
- 'odp' => 'application/vnd.oasis.opendocument.presentation',
- 'otp' => 'application/vnd.oasis.opendocument.presentation-template',
- 'ods' => 'application/vnd.oasis.opendocument.spreadsheet',
- 'ots' => 'application/vnd.oasis.opendocument.spreadsheet-template',
- 'odt' => 'application/vnd.oasis.opendocument.text',
- 'otm' => 'application/vnd.oasis.opendocument.text-master',
- 'ott' => 'application/vnd.oasis.opendocument.text-template',
- 'oth' => 'application/vnd.oasis.opendocument.text-web',
- 'xo' => 'application/vnd.olpc-sugar',
- 'dd2' => 'application/vnd.oma.dd2+xml',
- 'oxt' => 'application/vnd.openofficeorg.extension',
- 'dp' => 'application/vnd.osgi.dp',
- 'prc' => 'application/vnd.palm',
- 'pdb' => 'application/vnd.palm',
- 'pqa' => 'application/vnd.palm',
- 'oprc' => 'application/vnd.palm',
- 'str' => 'application/vnd.pg.format',
- 'ei6' => 'application/vnd.pg.osasli',
- 'efif' => 'application/vnd.picsel',
- 'plf' => 'application/vnd.pocketlearn',
- 'pbd' => 'application/vnd.powerbuilder6',
- 'box' => 'application/vnd.previewsystems.box',
- 'mgz' => 'application/vnd.proteus.magazine',
- 'qps' => 'application/vnd.publishare-delta-tree',
- 'ptid' => 'application/vnd.pvi.ptid1',
- 'qxd' => 'application/vnd.quark.quarkxpress',
- 'qxt' => 'application/vnd.quark.quarkxpress',
- 'qwd' => 'application/vnd.quark.quarkxpress',
- 'qwt' => 'application/vnd.quark.quarkxpress',
- 'qxl' => 'application/vnd.quark.quarkxpress',
- 'qxb' => 'application/vnd.quark.quarkxpress',
- 'mxl' => 'application/vnd.recordare.musicxml',
- 'rm' => 'application/vnd.rn-realmedia',
- 'see' => 'application/vnd.seemail',
- 'sema' => 'application/vnd.sema',
- 'semd' => 'application/vnd.semd',
- 'semf' => 'application/vnd.semf',
- 'ifm' => 'application/vnd.shana.informed.formdata',
- 'itp' => 'application/vnd.shana.informed.formtemplate',
- 'iif' => 'application/vnd.shana.informed.interchange',
- 'ipk' => 'application/vnd.shana.informed.package',
- 'twd' => 'application/vnd.simtech-mindmapper',
- 'twds' => 'application/vnd.simtech-mindmapper',
- 'mmf' => 'application/vnd.smaf',
- 'sdkm' => 'application/vnd.solent.sdkm+xml',
- 'sdkd' => 'application/vnd.solent.sdkm+xml',
- 'dxp' => 'application/vnd.spotfire.dxp',
- 'sfs' => 'application/vnd.spotfire.sfs',
- 'sus' => 'application/vnd.sus-calendar',
- 'susp' => 'application/vnd.sus-calendar',
- 'svd' => 'application/vnd.svd',
- 'xsm' => 'application/vnd.syncml+xml',
- 'bdm' => 'application/vnd.syncml.dm+wbxml',
- 'xdm' => 'application/vnd.syncml.dm+xml',
- 'tao' => 'application/vnd.tao.intent-module-archive',
- 'tmo' => 'application/vnd.tmobile-livetv',
- 'tpt' => 'application/vnd.trid.tpt',
- 'mxs' => 'application/vnd.triscape.mxs',
- 'tra' => 'application/vnd.trueapp',
- 'ufd' => 'application/vnd.ufdl',
- 'ufdl' => 'application/vnd.ufdl',
- 'utz' => 'application/vnd.uiq.theme',
- 'umj' => 'application/vnd.umajin',
- 'unityweb' => 'application/vnd.unity',
- 'uoml' => 'application/vnd.uoml+xml',
- 'vcx' => 'application/vnd.vcx',
- 'vsd' => 'application/vnd.visio',
- 'vst' => 'application/vnd.visio',
- 'vss' => 'application/vnd.visio',
- 'vsw' => 'application/vnd.visio',
- 'vis' => 'application/vnd.visionary',
- 'vsf' => 'application/vnd.vsf',
- 'wbxml' => 'application/vnd.wap.wbxml',
- 'wmlc' => 'application/vnd.wap.wmlc',
- 'wmlsc' => 'application/vnd.wap.wmlscriptc',
- 'wtb' => 'application/vnd.webturbo',
- 'wpd' => 'application/vnd.wordperfect',
- 'wqd' => 'application/vnd.wqd',
- 'stf' => 'application/vnd.wt.stf',
- 'xar' => 'application/vnd.xara',
- 'xfdl' => 'application/vnd.xfdl',
- 'hvd' => 'application/vnd.yamaha.hv-dic',
- 'hvs' => 'application/vnd.yamaha.hv-script',
- 'hvp' => 'application/vnd.yamaha.hv-voice',
- 'saf' => 'application/vnd.yamaha.smaf-audio',
- 'spf' => 'application/vnd.yamaha.smaf-phrase',
- 'cmp' => 'application/vnd.yellowriver-custom-menu',
- 'zaz' => 'application/vnd.zzazz.deck+xml',
- 'vxml' => 'application/voicexml+xml',
- 'hlp' => 'application/winhlp',
- 'wsdl' => 'application/wsdl+xml',
- 'wspolicy' => 'application/wspolicy+xml',
- 'ace' => 'application/x-ace-compressed',
- 'bcpio' => 'application/x-bcpio',
- 'torrent' => 'application/x-bittorrent',
- 'bz' => 'application/x-bzip',
- 'bz2' => 'application/x-bzip2',
- 'boz' => 'application/x-bzip2',
- 'vcd' => 'application/x-cdlink',
- 'chat' => 'application/x-chat',
- 'pgn' => 'application/x-chess-pgn',
- 'cpio' => 'application/x-cpio',
- 'csh' => 'application/x-csh',
- 'dcr' => 'application/x-director',
- 'dir' => 'application/x-director',
- 'dxr' => 'application/x-director',
- 'fgd' => 'application/x-director',
- 'dvi' => 'application/x-dvi',
- 'spl' => 'application/x-futuresplash',
- 'gtar' => 'application/x-gtar',
- 'hdf' => 'application/x-hdf',
- 'jnlp' => 'application/x-java-jnlp-file',
- 'latex' => 'application/x-latex',
- 'wmd' => 'application/x-ms-wmd',
- 'wmz' => 'application/x-ms-wmz',
- 'mdb' => 'application/x-msaccess',
- 'obd' => 'application/x-msbinder',
- 'crd' => 'application/x-mscardfile',
- 'clp' => 'application/x-msclip',
- 'exe' => 'application/x-msdownload',
- 'dll' => 'application/x-msdownload',
- 'com' => 'application/x-msdownload',
- 'bat' => 'application/x-msdownload',
- 'msi' => 'application/x-msdownload',
- 'mvb' => 'application/x-msmediaview',
- 'm13' => 'application/x-msmediaview',
- 'm14' => 'application/x-msmediaview',
- 'wmf' => 'application/x-msmetafile',
- 'mny' => 'application/x-msmoney',
- 'pub' => 'application/x-mspublisher',
- 'scd' => 'application/x-msschedule',
- 'trm' => 'application/x-msterminal',
- 'wri' => 'application/x-mswrite',
- 'nc' => 'application/x-netcdf',
- 'cdf' => 'application/x-netcdf',
- 'p12' => 'application/x-pkcs12',
- 'pfx' => 'application/x-pkcs12',
- 'p7b' => 'application/x-pkcs7-certificates',
- 'spc' => 'application/x-pkcs7-certificates',
- 'p7r' => 'application/x-pkcs7-certreqresp',
- 'rar' => 'application/x-rar-compressed',
- 'sh' => 'application/x-sh',
- 'shar' => 'application/x-shar',
- 'swf' => 'application/x-shockwave-flash',
- 'sit' => 'application/x-stuffit',
- 'sitx' => 'application/x-stuffitx',
- 'sv4cpio' => 'application/x-sv4cpio',
- 'sv4crc' => 'application/x-sv4crc',
- 'tar' => 'application/x-tar',
- 'tcl' => 'application/x-tcl',
- 'tex' => 'application/x-tex',
- 'texinfo' => 'application/x-texinfo',
- 'texi' => 'application/x-texinfo',
- 'ustar' => 'application/x-ustar',
- 'src' => 'application/x-wais-source',
- 'der' => 'application/x-x509-ca-cert',
- 'crt' => 'application/x-x509-ca-cert',
- 'xenc' => 'application/xenc+xml',
- 'xhtml' => 'application/xhtml+xml',
- 'xht' => 'application/xhtml+xml',
- 'xml' => 'application/xml',
- 'xsl' => 'application/xml',
- 'dtd' => 'application/xml-dtd',
- 'xop' => 'application/xop+xml',
- 'xslt' => 'application/xslt+xml',
- 'xspf' => 'application/xspf+xml',
- 'mxml' => 'application/xv+xml',
- 'xhvml' => 'application/xv+xml',
- 'xvml' => 'application/xv+xml',
- 'xvm' => 'application/xv+xml',
- 'zip' => 'application/zip',
- 'au' => 'audio/basic',
- 'snd' => 'audio/basic',
- 'mid' => 'audio/midi',
- 'midi' => 'audio/midi',
- 'kar' => 'audio/midi',
- 'rmi' => 'audio/midi',
- 'mp4a' => 'audio/mp4',
- 'm4a' => 'audio/mp4a-latm',
- 'm4p' => 'audio/mp4a-latm',
- 'mpga' => 'audio/mpeg',
- 'mp2' => 'audio/mpeg',
- 'mp2a' => 'audio/mpeg',
- 'mp3' => 'audio/mpeg',
- 'm2a' => 'audio/mpeg',
- 'm3a' => 'audio/mpeg',
- 'eol' => 'audio/vnd.digital-winds',
- 'lvp' => 'audio/vnd.lucent.voice',
+ 'irp' => 'application/vnd.irepository.package+xml',
+ 'xpr' => 'application/vnd.is-xpr',
+ 'jam' => 'application/vnd.jam',
+ 'rms' => 'application/vnd.jcp.javame.midlet-rms',
+ 'jisp' => 'application/vnd.jisp',
+ 'ktz' => 'application/vnd.kahootz',
+ 'ktr' => 'application/vnd.kahootz',
+ 'karbon' => 'application/vnd.kde.karbon',
+ 'chrt' => 'application/vnd.kde.kchart',
+ 'kfo' => 'application/vnd.kde.kformula',
+ 'flw' => 'application/vnd.kde.kivio',
+ 'kon' => 'application/vnd.kde.kontour',
+ 'kpr' => 'application/vnd.kde.kpresenter',
+ 'kpt' => 'application/vnd.kde.kpresenter',
+ 'ksp' => 'application/vnd.kde.kspread',
+ 'kwd' => 'application/vnd.kde.kword',
+ 'kwt' => 'application/vnd.kde.kword',
+ 'htke' => 'application/vnd.kenameaapp',
+ 'kia' => 'application/vnd.kidspiration',
+ 'kne' => 'application/vnd.kinar',
+ 'knp' => 'application/vnd.kinar',
+ 'skp' => 'application/vnd.koan',
+ 'skd' => 'application/vnd.koan',
+ 'skt' => 'application/vnd.koan',
+ 'skm' => 'application/vnd.koan',
+ 'lbd' => 'application/vnd.llamagraphics.life-balance.desktop',
+ 'lbe' => 'application/vnd.llamagraphics.life-balance.exchange+xml',
+ '123' => 'application/vnd.lotus-1-2-3',
+ 'apr' => 'application/vnd.lotus-approach',
+ 'pre' => 'application/vnd.lotus-freelance',
+ 'nsf' => 'application/vnd.lotus-notes',
+ 'org' => 'application/vnd.lotus-organizer',
+ 'scm' => 'application/vnd.lotus-screencam',
+ 'lwp' => 'application/vnd.lotus-wordpro',
+ 'portpkg' => 'application/vnd.macports.portpkg',
+ 'mcd' => 'application/vnd.mcd',
+ 'mc1' => 'application/vnd.medcalcdata',
+ 'cdkey' => 'application/vnd.mediastation.cdkey',
+ 'mwf' => 'application/vnd.mfer',
+ 'mfm' => 'application/vnd.mfmp',
+ 'flo' => 'application/vnd.micrografx.flo',
+ 'igx' => 'application/vnd.micrografx.igx',
+ 'mif' => 'application/vnd.mif',
+ 'daf' => 'application/vnd.mobius.daf',
+ 'dis' => 'application/vnd.mobius.dis',
+ 'mbk' => 'application/vnd.mobius.mbk',
+ 'mqy' => 'application/vnd.mobius.mqy',
+ 'msl' => 'application/vnd.mobius.msl',
+ 'plc' => 'application/vnd.mobius.plc',
+ 'txf' => 'application/vnd.mobius.txf',
+ 'mpn' => 'application/vnd.mophun.application',
+ 'mpc' => 'application/vnd.mophun.certificate',
+ 'xul' => 'application/vnd.mozilla.xul+xml',
+ 'cil' => 'application/vnd.ms-artgalry',
+ 'asf' => 'application/vnd.ms-asf',
+ 'cab' => 'application/vnd.ms-cab-compressed',
+ 'xls' => 'application/vnd.ms-excel',
+ 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
+ 'xlm' => 'application/vnd.ms-excel',
+ 'xla' => 'application/vnd.ms-excel',
+ 'xlc' => 'application/vnd.ms-excel',
+ 'xlt' => 'application/vnd.ms-excel',
+ 'xlw' => 'application/vnd.ms-excel',
+ 'eot' => 'application/vnd.ms-fontobject',
+ 'chm' => 'application/vnd.ms-htmlhelp',
+ 'ims' => 'application/vnd.ms-ims',
+ 'lrm' => 'application/vnd.ms-lrm',
+ 'ppt' => 'application/vnd.ms-powerpoint',
+ 'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
+ 'pps' => 'application/vnd.ms-powerpoint',
+ 'pot' => 'application/vnd.ms-powerpoint',
+ 'mpp' => 'application/vnd.ms-project',
+ 'mpt' => 'application/vnd.ms-project',
+ 'wps' => 'application/vnd.ms-works',
+ 'wks' => 'application/vnd.ms-works',
+ 'wcm' => 'application/vnd.ms-works',
+ 'wdb' => 'application/vnd.ms-works',
+ 'wpl' => 'application/vnd.ms-wpl',
+ 'xps' => 'application/vnd.ms-xpsdocument',
+ 'mseq' => 'application/vnd.mseq',
+ 'mus' => 'application/vnd.musician',
+ 'nlu' => 'application/vnd.neurolanguage.nlu',
+ 'nnd' => 'application/vnd.noblenet-directory',
+ 'nns' => 'application/vnd.noblenet-sealer',
+ 'nnw' => 'application/vnd.noblenet-web',
+ 'ngdat' => 'application/vnd.nokia.n-gage.data',
+ 'n-gage' => 'application/vnd.nokia.n-gage.symbian.install',
+ 'rpst' => 'application/vnd.nokia.radio-preset',
+ 'rpss' => 'application/vnd.nokia.radio-presets',
+ 'edm' => 'application/vnd.novadigm.edm',
+ 'edx' => 'application/vnd.novadigm.edx',
+ 'ext' => 'application/vnd.novadigm.ext',
+ 'odc' => 'application/vnd.oasis.opendocument.chart',
+ 'otc' => 'application/vnd.oasis.opendocument.chart-template',
+ 'odf' => 'application/vnd.oasis.opendocument.formula',
+ 'otf' => 'application/vnd.oasis.opendocument.formula-template',
+ 'odg' => 'application/vnd.oasis.opendocument.graphics',
+ 'otg' => 'application/vnd.oasis.opendocument.graphics-template',
+ 'odi' => 'application/vnd.oasis.opendocument.image',
+ 'oti' => 'application/vnd.oasis.opendocument.image-template',
+ 'odp' => 'application/vnd.oasis.opendocument.presentation',
+ 'otp' => 'application/vnd.oasis.opendocument.presentation-template',
+ 'ods' => 'application/vnd.oasis.opendocument.spreadsheet',
+ 'ots' => 'application/vnd.oasis.opendocument.spreadsheet-template',
+ 'odt' => 'application/vnd.oasis.opendocument.text',
+ 'otm' => 'application/vnd.oasis.opendocument.text-master',
+ 'ott' => 'application/vnd.oasis.opendocument.text-template',
+ 'oth' => 'application/vnd.oasis.opendocument.text-web',
+ 'xo' => 'application/vnd.olpc-sugar',
+ 'dd2' => 'application/vnd.oma.dd2+xml',
+ 'oxt' => 'application/vnd.openofficeorg.extension',
+ 'dp' => 'application/vnd.osgi.dp',
+ 'prc' => 'application/vnd.palm',
+ 'pdb' => 'application/vnd.palm',
+ 'pqa' => 'application/vnd.palm',
+ 'oprc' => 'application/vnd.palm',
+ 'str' => 'application/vnd.pg.format',
+ 'ei6' => 'application/vnd.pg.osasli',
+ 'efif' => 'application/vnd.picsel',
+ 'plf' => 'application/vnd.pocketlearn',
+ 'pbd' => 'application/vnd.powerbuilder6',
+ 'box' => 'application/vnd.previewsystems.box',
+ 'mgz' => 'application/vnd.proteus.magazine',
+ 'qps' => 'application/vnd.publishare-delta-tree',
+ 'ptid' => 'application/vnd.pvi.ptid1',
+ 'qxd' => 'application/vnd.quark.quarkxpress',
+ 'qxt' => 'application/vnd.quark.quarkxpress',
+ 'qwd' => 'application/vnd.quark.quarkxpress',
+ 'qwt' => 'application/vnd.quark.quarkxpress',
+ 'qxl' => 'application/vnd.quark.quarkxpress',
+ 'qxb' => 'application/vnd.quark.quarkxpress',
+ 'mxl' => 'application/vnd.recordare.musicxml',
+ 'rm' => 'application/vnd.rn-realmedia',
+ 'see' => 'application/vnd.seemail',
+ 'sema' => 'application/vnd.sema',
+ 'semd' => 'application/vnd.semd',
+ 'semf' => 'application/vnd.semf',
+ 'ifm' => 'application/vnd.shana.informed.formdata',
+ 'itp' => 'application/vnd.shana.informed.formtemplate',
+ 'iif' => 'application/vnd.shana.informed.interchange',
+ 'ipk' => 'application/vnd.shana.informed.package',
+ 'twd' => 'application/vnd.simtech-mindmapper',
+ 'twds' => 'application/vnd.simtech-mindmapper',
+ 'mmf' => 'application/vnd.smaf',
+ 'sdkm' => 'application/vnd.solent.sdkm+xml',
+ 'sdkd' => 'application/vnd.solent.sdkm+xml',
+ 'dxp' => 'application/vnd.spotfire.dxp',
+ 'sfs' => 'application/vnd.spotfire.sfs',
+ 'sus' => 'application/vnd.sus-calendar',
+ 'susp' => 'application/vnd.sus-calendar',
+ 'svd' => 'application/vnd.svd',
+ 'xsm' => 'application/vnd.syncml+xml',
+ 'bdm' => 'application/vnd.syncml.dm+wbxml',
+ 'xdm' => 'application/vnd.syncml.dm+xml',
+ 'tao' => 'application/vnd.tao.intent-module-archive',
+ 'tmo' => 'application/vnd.tmobile-livetv',
+ 'tpt' => 'application/vnd.trid.tpt',
+ 'mxs' => 'application/vnd.triscape.mxs',
+ 'tra' => 'application/vnd.trueapp',
+ 'ufd' => 'application/vnd.ufdl',
+ 'ufdl' => 'application/vnd.ufdl',
+ 'utz' => 'application/vnd.uiq.theme',
+ 'umj' => 'application/vnd.umajin',
+ 'unityweb' => 'application/vnd.unity',
+ 'uoml' => 'application/vnd.uoml+xml',
+ 'vcx' => 'application/vnd.vcx',
+ 'vsd' => 'application/vnd.visio',
+ 'vst' => 'application/vnd.visio',
+ 'vss' => 'application/vnd.visio',
+ 'vsw' => 'application/vnd.visio',
+ 'vis' => 'application/vnd.visionary',
+ 'vsf' => 'application/vnd.vsf',
+ 'wbxml' => 'application/vnd.wap.wbxml',
+ 'wmlc' => 'application/vnd.wap.wmlc',
+ 'wmlsc' => 'application/vnd.wap.wmlscriptc',
+ 'wtb' => 'application/vnd.webturbo',
+ 'wpd' => 'application/vnd.wordperfect',
+ 'wqd' => 'application/vnd.wqd',
+ 'stf' => 'application/vnd.wt.stf',
+ 'xar' => 'application/vnd.xara',
+ 'xfdl' => 'application/vnd.xfdl',
+ 'hvd' => 'application/vnd.yamaha.hv-dic',
+ 'hvs' => 'application/vnd.yamaha.hv-script',
+ 'hvp' => 'application/vnd.yamaha.hv-voice',
+ 'saf' => 'application/vnd.yamaha.smaf-audio',
+ 'spf' => 'application/vnd.yamaha.smaf-phrase',
+ 'cmp' => 'application/vnd.yellowriver-custom-menu',
+ 'zaz' => 'application/vnd.zzazz.deck+xml',
+ 'vxml' => 'application/voicexml+xml',
+ 'hlp' => 'application/winhlp',
+ 'wsdl' => 'application/wsdl+xml',
+ 'wspolicy' => 'application/wspolicy+xml',
+ 'ace' => 'application/x-ace-compressed',
+ 'bcpio' => 'application/x-bcpio',
+ 'torrent' => 'application/x-bittorrent',
+ 'bz' => 'application/x-bzip',
+ 'bz2' => 'application/x-bzip2',
+ 'boz' => 'application/x-bzip2',
+ 'vcd' => 'application/x-cdlink',
+ 'chat' => 'application/x-chat',
+ 'pgn' => 'application/x-chess-pgn',
+ 'cpio' => 'application/x-cpio',
+ 'csh' => 'application/x-csh',
+ 'dcr' => 'application/x-director',
+ 'dir' => 'application/x-director',
+ 'dxr' => 'application/x-director',
+ 'fgd' => 'application/x-director',
+ 'dvi' => 'application/x-dvi',
+ 'spl' => 'application/x-futuresplash',
+ 'gtar' => 'application/x-gtar',
+ 'hdf' => 'application/x-hdf',
+ 'jnlp' => 'application/x-java-jnlp-file',
+ 'latex' => 'application/x-latex',
+ 'wmd' => 'application/x-ms-wmd',
+ 'wmz' => 'application/x-ms-wmz',
+ 'mdb' => 'application/x-msaccess',
+ 'obd' => 'application/x-msbinder',
+ 'crd' => 'application/x-mscardfile',
+ 'clp' => 'application/x-msclip',
+ 'exe' => 'application/x-msdownload',
+ 'dll' => 'application/x-msdownload',
+ 'com' => 'application/x-msdownload',
+ 'bat' => 'application/x-msdownload',
+ 'msi' => 'application/x-msdownload',
+ 'mvb' => 'application/x-msmediaview',
+ 'm13' => 'application/x-msmediaview',
+ 'm14' => 'application/x-msmediaview',
+ 'wmf' => 'application/x-msmetafile',
+ 'mny' => 'application/x-msmoney',
+ 'pub' => 'application/x-mspublisher',
+ 'scd' => 'application/x-msschedule',
+ 'trm' => 'application/x-msterminal',
+ 'wri' => 'application/x-mswrite',
+ 'nc' => 'application/x-netcdf',
+ 'cdf' => 'application/x-netcdf',
+ 'p12' => 'application/x-pkcs12',
+ 'pfx' => 'application/x-pkcs12',
+ 'p7b' => 'application/x-pkcs7-certificates',
+ 'spc' => 'application/x-pkcs7-certificates',
+ 'p7r' => 'application/x-pkcs7-certreqresp',
+ 'rar' => 'application/x-rar-compressed',
+ 'sh' => 'application/x-sh',
+ 'shar' => 'application/x-shar',
+ 'swf' => 'application/x-shockwave-flash',
+ 'sit' => 'application/x-stuffit',
+ 'sitx' => 'application/x-stuffitx',
+ 'sv4cpio' => 'application/x-sv4cpio',
+ 'sv4crc' => 'application/x-sv4crc',
+ 'tar' => 'application/x-tar',
+ 'tcl' => 'application/x-tcl',
+ 'tex' => 'application/x-tex',
+ 'texinfo' => 'application/x-texinfo',
+ 'texi' => 'application/x-texinfo',
+ 'ustar' => 'application/x-ustar',
+ 'src' => 'application/x-wais-source',
+ 'der' => 'application/x-x509-ca-cert',
+ 'crt' => 'application/x-x509-ca-cert',
+ 'xenc' => 'application/xenc+xml',
+ 'xhtml' => 'application/xhtml+xml',
+ 'xht' => 'application/xhtml+xml',
+ 'xml' => 'application/xml',
+ 'xsl' => 'application/xml',
+ 'dtd' => 'application/xml-dtd',
+ 'xop' => 'application/xop+xml',
+ 'xslt' => 'application/xslt+xml',
+ 'xspf' => 'application/xspf+xml',
+ 'mxml' => 'application/xv+xml',
+ 'xhvml' => 'application/xv+xml',
+ 'xvml' => 'application/xv+xml',
+ 'xvm' => 'application/xv+xml',
+ 'zip' => 'application/zip',
+ 'au' => 'audio/basic',
+ 'snd' => 'audio/basic',
+ 'mid' => 'audio/midi',
+ 'midi' => 'audio/midi',
+ 'kar' => 'audio/midi',
+ 'rmi' => 'audio/midi',
+ 'mp4a' => 'audio/mp4',
+ 'm4a' => 'audio/mp4a-latm',
+ 'm4p' => 'audio/mp4a-latm',
+ 'mpga' => 'audio/mpeg',
+ 'mp2' => 'audio/mpeg',
+ 'mp2a' => 'audio/mpeg',
+ 'mp3' => 'audio/mpeg',
+ 'm2a' => 'audio/mpeg',
+ 'm3a' => 'audio/mpeg',
+ 'eol' => 'audio/vnd.digital-winds',
+ 'lvp' => 'audio/vnd.lucent.voice',
'ecelp4800' => 'audio/vnd.nuera.ecelp4800',
'ecelp7470' => 'audio/vnd.nuera.ecelp7470',
'ecelp9600' => 'audio/vnd.nuera.ecelp9600',
- 'wav' => 'audio/wav',
- 'aif' => 'audio/x-aiff',
- 'aiff' => 'audio/x-aiff',
- 'aifc' => 'audio/x-aiff',
- 'm3u' => 'audio/x-mpegurl',
- 'wax' => 'audio/x-ms-wax',
- 'wma' => 'audio/x-ms-wma',
- 'ram' => 'audio/x-pn-realaudio',
- 'ra' => 'audio/x-pn-realaudio',
- 'rmp' => 'audio/x-pn-realaudio-plugin',
- 'cdx' => 'chemical/x-cdx',
- 'cif' => 'chemical/x-cif',
- 'cmdf' => 'chemical/x-cmdf',
- 'cml' => 'chemical/x-cml',
- 'csml' => 'chemical/x-csml',
- 'xyz' => 'chemical/x-xyz',
- 'bmp' => 'image/bmp',
- 'cgm' => 'image/cgm',
- 'g3' => 'image/g3fax',
- 'gif' => 'image/gif',
- 'ief' => 'image/ief',
- 'jp2' => 'image/jp2',
- 'jpeg' => 'image/jpeg',
- 'jpe' => 'image/jpeg',
- 'jpg' => 'image/jpeg',
- 'pict' => 'image/pict',
- 'pic' => 'image/pict',
- 'pct' => 'image/pict',
- 'png' => 'image/png',
- 'btif' => 'image/prs.btif',
- 'svg' => 'image/svg+xml',
- 'svgz' => 'image/svg+xml',
- 'tiff' => 'image/tiff',
- 'tif' => 'image/tiff',
- 'psd' => 'image/vnd.adobe.photoshop',
- 'djvu' => 'image/vnd.djvu',
- 'djv' => 'image/vnd.djvu',
- 'dwg' => 'image/vnd.dwg',
- 'dxf' => 'image/vnd.dxf',
- 'fbs' => 'image/vnd.fastbidsheet',
- 'fpx' => 'image/vnd.fpx',
- 'fst' => 'image/vnd.fst',
- 'mmr' => 'image/vnd.fujixerox.edmics-mmr',
- 'rlc' => 'image/vnd.fujixerox.edmics-rlc',
- 'ico' => 'image/vnd.microsoft.icon',
- 'mdi' => 'image/vnd.ms-modi',
- 'npx' => 'image/vnd.net-fpx',
- 'wbmp' => 'image/vnd.wap.wbmp',
- 'xif' => 'image/vnd.xiff',
- 'ras' => 'image/x-cmu-raster',
- 'cmx' => 'image/x-cmx',
- 'pntg' => 'image/x-macpaint',
- 'pnt' => 'image/x-macpaint',
- 'mac' => 'image/x-macpaint',
- 'pcx' => 'image/x-pcx',
- 'pnm' => 'image/x-portable-anymap',
- 'pbm' => 'image/x-portable-bitmap',
- 'pgm' => 'image/x-portable-graymap',
- 'ppm' => 'image/x-portable-pixmap',
- 'qtif' => 'image/x-quicktime',
- 'qti' => 'image/x-quicktime',
- 'rgb' => 'image/x-rgb',
- 'xbm' => 'image/x-xbitmap',
- 'xpm' => 'image/x-xpixmap',
- 'xwd' => 'image/x-xwindowdump',
- 'eml' => 'message/rfc822',
- 'mime' => 'message/rfc822',
- 'igs' => 'model/iges',
- 'iges' => 'model/iges',
- 'msh' => 'model/mesh',
- 'mesh' => 'model/mesh',
- 'silo' => 'model/mesh',
- 'dwf' => 'model/vnd.dwf',
- 'gdl' => 'model/vnd.gdl',
- 'gtw' => 'model/vnd.gtw',
- 'mts' => 'model/vnd.mts',
- 'vtu' => 'model/vnd.vtu',
- 'wrl' => 'model/vrml',
- 'vrml' => 'model/vrml',
- 'ics' => 'text/calendar',
- 'ifb' => 'text/calendar',
- 'css' => 'text/css',
- 'csv' => 'text/csv',
- 'html' => 'text/html',
- 'htm' => 'text/html',
- 'txt' => 'text/plain',
- 'text' => 'text/plain',
- 'conf' => 'text/plain',
- 'def' => 'text/plain',
- 'list' => 'text/plain',
- 'log' => 'text/plain',
- 'in' => 'text/plain',
- 'dsc' => 'text/prs.lines.tag',
- 'rtx' => 'text/richtext',
- 'sgml' => 'text/sgml',
- 'sgm' => 'text/sgml',
- 'tsv' => 'text/tab-separated-values',
- 't' => 'text/troff',
- 'tr' => 'text/troff',
- 'roff' => 'text/troff',
- 'man' => 'text/troff',
- 'me' => 'text/troff',
- 'ms' => 'text/troff',
- 'uri' => 'text/uri-list',
- 'uris' => 'text/uri-list',
- 'urls' => 'text/uri-list',
- 'fly' => 'text/vnd.fly',
- 'flx' => 'text/vnd.fmi.flexstor',
- '3dml' => 'text/vnd.in3d.3dml',
- 'spot' => 'text/vnd.in3d.spot',
- 'jad' => 'text/vnd.sun.j2me.app-descriptor',
- 'wml' => 'text/vnd.wap.wml',
- 'wmls' => 'text/vnd.wap.wmlscript',
- 's' => 'text/x-asm',
- 'asm' => 'text/x-asm',
- 'c' => 'text/x-c',
- 'cc' => 'text/x-c',
- 'cxx' => 'text/x-c',
- 'cpp' => 'text/x-c',
- 'h' => 'text/x-c',
- 'hh' => 'text/x-c',
- 'dic' => 'text/x-c',
- 'f' => 'text/x-fortran',
- 'for' => 'text/x-fortran',
- 'f77' => 'text/x-fortran',
- 'f90' => 'text/x-fortran',
- 'p' => 'text/x-pascal',
- 'pas' => 'text/x-pascal',
- 'java' => 'text/x-java-source',
- 'etx' => 'text/x-setext',
- 'uu' => 'text/x-uuencode',
- 'vcs' => 'text/x-vcalendar',
- 'vcf' => 'text/x-vcard',
- '3gp' => 'video/3gpp',
- '3g2' => 'video/3gpp2',
- 'h261' => 'video/h261',
- 'h263' => 'video/h263',
- 'h264' => 'video/h264',
- 'jpgv' => 'video/jpeg',
- 'jpm' => 'video/jpm',
- 'jpgm' => 'video/jpm',
- 'mj2' => 'video/mj2',
- 'mjp2' => 'video/mj2',
- 'mp4' => 'video/mp4',
- 'mp4v' => 'video/mp4',
- 'mpg4' => 'video/mp4',
- 'm4v' => 'video/mp4',
- 'mpeg' => 'video/mpeg',
- 'mpg' => 'video/mpeg',
- 'mpe' => 'video/mpeg',
- 'm1v' => 'video/mpeg',
- 'm2v' => 'video/mpeg',
- 'qt' => 'video/quicktime',
- 'mov' => 'video/quicktime',
- 'fvt' => 'video/vnd.fvt',
- 'mxu' => 'video/vnd.mpegurl',
- 'm4u' => 'video/vnd.mpegurl',
- 'viv' => 'video/vnd.vivo',
- 'dv' => 'video/x-dv',
- 'dif' => 'video/x-dv',
- 'fli' => 'video/x-fli',
- 'asx' => 'video/x-ms-asf',
- 'wm' => 'video/x-ms-wm',
- 'wmv' => 'video/x-ms-wmv',
- 'wmx' => 'video/x-ms-wmx',
- 'wvx' => 'video/x-ms-wvx',
- 'avi' => 'video/x-msvideo',
- 'movie' => 'video/x-sgi-movie',
- 'ice' => 'x-conference/x-cooltalk',
+ 'wav' => 'audio/wav',
+ 'aif' => 'audio/x-aiff',
+ 'aiff' => 'audio/x-aiff',
+ 'aifc' => 'audio/x-aiff',
+ 'm3u' => 'audio/x-mpegurl',
+ 'wax' => 'audio/x-ms-wax',
+ 'wma' => 'audio/x-ms-wma',
+ 'ram' => 'audio/x-pn-realaudio',
+ 'ra' => 'audio/x-pn-realaudio',
+ 'rmp' => 'audio/x-pn-realaudio-plugin',
+ 'cdx' => 'chemical/x-cdx',
+ 'cif' => 'chemical/x-cif',
+ 'cmdf' => 'chemical/x-cmdf',
+ 'cml' => 'chemical/x-cml',
+ 'csml' => 'chemical/x-csml',
+ 'xyz' => 'chemical/x-xyz',
+ 'bmp' => 'image/bmp',
+ 'cgm' => 'image/cgm',
+ 'g3' => 'image/g3fax',
+ 'gif' => 'image/gif',
+ 'ief' => 'image/ief',
+ 'jp2' => 'image/jp2',
+ 'jpeg' => 'image/jpeg',
+ 'jpe' => 'image/jpeg',
+ 'jpg' => 'image/jpeg',
+ 'pict' => 'image/pict',
+ 'pic' => 'image/pict',
+ 'pct' => 'image/pict',
+ 'png' => 'image/png',
+ 'btif' => 'image/prs.btif',
+ 'svg' => 'image/svg+xml',
+ 'svgz' => 'image/svg+xml',
+ 'tiff' => 'image/tiff',
+ 'tif' => 'image/tiff',
+ 'psd' => 'image/vnd.adobe.photoshop',
+ 'djvu' => 'image/vnd.djvu',
+ 'djv' => 'image/vnd.djvu',
+ 'dwg' => 'image/vnd.dwg',
+ 'dxf' => 'image/vnd.dxf',
+ 'fbs' => 'image/vnd.fastbidsheet',
+ 'fpx' => 'image/vnd.fpx',
+ 'fst' => 'image/vnd.fst',
+ 'mmr' => 'image/vnd.fujixerox.edmics-mmr',
+ 'rlc' => 'image/vnd.fujixerox.edmics-rlc',
+ 'ico' => 'image/vnd.microsoft.icon',
+ 'mdi' => 'image/vnd.ms-modi',
+ 'npx' => 'image/vnd.net-fpx',
+ 'wbmp' => 'image/vnd.wap.wbmp',
+ 'xif' => 'image/vnd.xiff',
+ 'ras' => 'image/x-cmu-raster',
+ 'cmx' => 'image/x-cmx',
+ 'pntg' => 'image/x-macpaint',
+ 'pnt' => 'image/x-macpaint',
+ 'mac' => 'image/x-macpaint',
+ 'pcx' => 'image/x-pcx',
+ 'pnm' => 'image/x-portable-anymap',
+ 'pbm' => 'image/x-portable-bitmap',
+ 'pgm' => 'image/x-portable-graymap',
+ 'ppm' => 'image/x-portable-pixmap',
+ 'qtif' => 'image/x-quicktime',
+ 'qti' => 'image/x-quicktime',
+ 'rgb' => 'image/x-rgb',
+ 'xbm' => 'image/x-xbitmap',
+ 'xpm' => 'image/x-xpixmap',
+ 'xwd' => 'image/x-xwindowdump',
+ 'eml' => 'message/rfc822',
+ 'mime' => 'message/rfc822',
+ 'igs' => 'model/iges',
+ 'iges' => 'model/iges',
+ 'msh' => 'model/mesh',
+ 'mesh' => 'model/mesh',
+ 'silo' => 'model/mesh',
+ 'dwf' => 'model/vnd.dwf',
+ 'gdl' => 'model/vnd.gdl',
+ 'gtw' => 'model/vnd.gtw',
+ 'mts' => 'model/vnd.mts',
+ 'vtu' => 'model/vnd.vtu',
+ 'wrl' => 'model/vrml',
+ 'vrml' => 'model/vrml',
+ 'ics' => 'text/calendar',
+ 'ifb' => 'text/calendar',
+ 'css' => 'text/css',
+ 'csv' => 'text/csv',
+ 'html' => 'text/html',
+ 'htm' => 'text/html',
+ 'txt' => 'text/plain',
+ 'text' => 'text/plain',
+ 'conf' => 'text/plain',
+ 'def' => 'text/plain',
+ 'list' => 'text/plain',
+ 'log' => 'text/plain',
+ 'in' => 'text/plain',
+ 'dsc' => 'text/prs.lines.tag',
+ 'rtx' => 'text/richtext',
+ 'sgml' => 'text/sgml',
+ 'sgm' => 'text/sgml',
+ 'tsv' => 'text/tab-separated-values',
+ 't' => 'text/troff',
+ 'tr' => 'text/troff',
+ 'roff' => 'text/troff',
+ 'man' => 'text/troff',
+ 'me' => 'text/troff',
+ 'ms' => 'text/troff',
+ 'uri' => 'text/uri-list',
+ 'uris' => 'text/uri-list',
+ 'urls' => 'text/uri-list',
+ 'fly' => 'text/vnd.fly',
+ 'flx' => 'text/vnd.fmi.flexstor',
+ '3dml' => 'text/vnd.in3d.3dml',
+ 'spot' => 'text/vnd.in3d.spot',
+ 'jad' => 'text/vnd.sun.j2me.app-descriptor',
+ 'wml' => 'text/vnd.wap.wml',
+ 'wmls' => 'text/vnd.wap.wmlscript',
+ 's' => 'text/x-asm',
+ 'asm' => 'text/x-asm',
+ 'c' => 'text/x-c',
+ 'cc' => 'text/x-c',
+ 'cxx' => 'text/x-c',
+ 'cpp' => 'text/x-c',
+ 'h' => 'text/x-c',
+ 'hh' => 'text/x-c',
+ 'dic' => 'text/x-c',
+ 'f' => 'text/x-fortran',
+ 'for' => 'text/x-fortran',
+ 'f77' => 'text/x-fortran',
+ 'f90' => 'text/x-fortran',
+ 'p' => 'text/x-pascal',
+ 'pas' => 'text/x-pascal',
+ 'java' => 'text/x-java-source',
+ 'etx' => 'text/x-setext',
+ 'uu' => 'text/x-uuencode',
+ 'vcs' => 'text/x-vcalendar',
+ 'vcf' => 'text/x-vcard',
+ '3gp' => 'video/3gpp',
+ '3g2' => 'video/3gpp2',
+ 'h261' => 'video/h261',
+ 'h263' => 'video/h263',
+ 'h264' => 'video/h264',
+ 'jpgv' => 'video/jpeg',
+ 'jpm' => 'video/jpm',
+ 'jpgm' => 'video/jpm',
+ 'mj2' => 'video/mj2',
+ 'mjp2' => 'video/mj2',
+ 'mp4' => 'video/mp4',
+ 'mp4v' => 'video/mp4',
+ 'mpg4' => 'video/mp4',
+ 'm4v' => 'video/mp4',
+ 'mpeg' => 'video/mpeg',
+ 'mpg' => 'video/mpeg',
+ 'mpe' => 'video/mpeg',
+ 'm1v' => 'video/mpeg',
+ 'm2v' => 'video/mpeg',
+ 'qt' => 'video/quicktime',
+ 'mov' => 'video/quicktime',
+ 'fvt' => 'video/vnd.fvt',
+ 'mxu' => 'video/vnd.mpegurl',
+ 'm4u' => 'video/vnd.mpegurl',
+ 'viv' => 'video/vnd.vivo',
+ 'dv' => 'video/x-dv',
+ 'dif' => 'video/x-dv',
+ 'fli' => 'video/x-fli',
+ 'asx' => 'video/x-ms-asf',
+ 'wm' => 'video/x-ms-wm',
+ 'wmv' => 'video/x-ms-wmv',
+ 'wmx' => 'video/x-ms-wmx',
+ 'wvx' => 'video/x-ms-wvx',
+ 'avi' => 'video/x-msvideo',
+ 'movie' => 'video/x-sgi-movie',
+ 'ice' => 'x-conference/x-cooltalk',
];
+ /**
+ * Returns extension for given mime type
+ *
+ * @param string $mimeType The mime type, e.g. "video/mpeg"
+ * @return array|string
+ */
+ public static function getExtension($mimeType)
+ {
+ if (is_string($mimeType) && in_array($mimeType, self::$mimeTypes, true)) {
+ $data = Arrays::setKeysAsValues(self::$mimeTypes, false);
+
+ return $data[$mimeType];
+ }
+
+ return '';
+ }
+
/**
* Returns extensions for given mimes types
*
@@ -706,9 +726,6 @@ class MimeTypes
continue;
}
- /*
- * Extensions should be returned as upper case?
- */
if ($asUpperCase) {
if (is_array($extension)) {
array_walk($extension, function (&$value) {
@@ -726,20 +743,56 @@ class MimeTypes
}
/**
- * Returns extension for given mime type
+ * Returns mime type of given file
*
- * @param string $mimeType The mime type, e.g. "video/mpeg"
- * @return string|array
+ * @param string $filePath Path of the file to check
+ * @return string
+ * @throws RuntimeException
*/
- public static function getExtension($mimeType)
+ public static function getMimeType($filePath)
{
- if (is_string($mimeType) && in_array($mimeType, self::$mimeTypes, true)) {
- $data = Arrays::setKeysAsValues(self::$mimeTypes, false);
-
- return $data[$mimeType];
+ /*
+ * The file does not exist?
+ * Nothing to do
+ */
+ if (!is_string($filePath) || !is_readable($filePath)) {
+ return '';
}
- return '';
+ // 1st possibility: the finfo class
+ if (class_exists('finfo')) {
+ $finfo = new finfo();
+
+ return $finfo->file($filePath, FILEINFO_MIME_TYPE);
+ }
+
+ // 2nd possibility: the mime_content_type function
+ if (function_exists('mime_content_type')) {
+ return mime_content_type($filePath);
+ }
+
+ // Oops, there is no possibility to read the mime type
+ $template = 'Neither \'finfo\' class nor \'mime_content_type\' function exists. There is no way to read the'
+ .' mime type of file \'%s\'.';
+
+ $message = sprintf($template, $filePath);
+
+ throw new RuntimeException($message);
+ }
+
+ /**
+ * Returns information whether the given file type is an image
+ *
+ * @param string $mimeType The mime type of file
+ * @return bool
+ */
+ public static function isImage($mimeType)
+ {
+ if (in_array($mimeType, self::$mimeTypes, true)) {
+ return (bool) preg_match('|^image/.+$|', $mimeType);
+ }
+
+ return false;
}
/**
@@ -754,62 +807,4 @@ class MimeTypes
return self::isImage($mimeType);
}
-
- /**
- * Returns mime type of given file
- *
- * @param string $filePath Path of the file to check
- * @throws \RuntimeException
- * @return string
- */
- public static function getMimeType($filePath)
- {
- /*
- * The file does not exist?
- * Nothing to do
- */
- if (!is_string($filePath) || !is_readable($filePath)) {
- return '';
- }
-
- /*
- * 1st possibility: the finfo class
- */
- if (class_exists('finfo')) {
- $finfo = new \finfo();
-
- return $finfo->file($filePath, FILEINFO_MIME_TYPE);
- }
-
- /*
- * 2nd possibility: the mime_content_type function
- */
- if (function_exists('mime_content_type')) {
- return mime_content_type($filePath);
- }
-
- /*
- * Oops, there is no possibility to read the mime type
- */
- $template = 'Neither \'finfo\' class nor \'mime_content_type\' function exists. There is no way to read the'
- . ' mime type of file \'%s\'.';
-
- $message = sprintf($template, $filePath);
- throw new \RuntimeException($message);
- }
-
- /**
- * Returns information whether the given file type is an image
- *
- * @param string $mimeType The mime type of file
- * @return bool
- */
- public static function isImage($mimeType)
- {
- if (in_array($mimeType, self::$mimeTypes, true)) {
- return (bool)preg_match('|^image/.+$|', $mimeType);
- }
-
- return false;
- }
}
diff --git a/src/Utilities/Miscellaneous.php b/src/Utilities/Miscellaneous.php
index cdc1ef7..f04e3af 100644
--- a/src/Utilities/Miscellaneous.php
+++ b/src/Utilities/Miscellaneous.php
@@ -19,6 +19,285 @@ use Transliterator;
*/
class Miscellaneous
{
+ /**
+ * Breaks long text
+ *
+ * @param string $text The text to check and break
+ * @param int $perLine (optional) Characters count per line. Default: 100.
+ * @param string $separator (optional) Separator that is placed between lines. Default: "
".
+ * @param string $encoding (optional) Character encoding. Used by mb_substr(). Default: "UTF-8".
+ * @param int $proportionalAberration (optional) Proportional aberration for chars (percent value). Default: 20.
+ * @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 (false !== $spacePosition && 0 < $spacePosition) {
+ /** @var int $spacePosition */
+ $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;
+ }
+
+ public static function calculateGreatestCommonDivisor(int $first, int $second): int
+ {
+ if (0 === $second) {
+ return $first;
+ }
+
+ return static::calculateGreatestCommonDivisor($second, $first % $second);
+ }
+
+ /**
+ * 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 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 array|string $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 '';
+ }
+
+ $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;
+ }
+
+ /**
+ * 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 .= '0';
+ }
+
+ return $text;
+ }
+
+ /**
+ * 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;
+ }
+
/**
* Returns directory's content (names of directories and files)
*
@@ -27,7 +306,7 @@ class Miscellaneous
* 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
+ * @return null|array
*/
public static function getDirectoryContent($directoryPath, $recursive = false, $maxFilesCount = null)
{
@@ -75,8 +354,8 @@ class Miscellaneous
continue;
}
- if ($recursive && is_dir($directoryPath . $fileName)) {
- $content = self::getDirectoryContent($directoryPath . $fileName, true, $maxFilesCount - $count);
+ if ($recursive && is_dir($directoryPath.$fileName)) {
+ $content = self::getDirectoryContent($directoryPath.$fileName, true, $maxFilesCount - $count);
}
if (null !== $content) {
@@ -103,74 +382,6 @@ class Miscellaneous
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)
- {
- $fileExtension = self::getFileExtension($fileName, true);
-
- /*
- * File has given extension?
- * Nothing to do
- */
- if ($fileExtension === strtolower($extension)) {
- return $fileName;
- }
-
- return sprintf('%s.%s', $fileName, $extension);
- }
-
/**
* Returns file extension
*
@@ -200,67 +411,18 @@ class Miscellaneous
* @param string $path A path that contains file name
* @return string
*/
- public static function getFileNameFromPath($path)
+ public static function getFileNameFromPath(string $path): string
{
$matches = [];
- $pattern = sprintf('|([^\%s.]+\.[A-Za-z0-9.]+)$|', DIRECTORY_SEPARATOR);
+ $pattern = Regex::getFileNamePattern();
- if ((bool)preg_match($pattern, $path, $matches)) {
- return $matches[1];
+ if ((bool) preg_match($pattern, $path, $matches)) {
+ return $matches[0];
}
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.%s'; // [file's name]-[unique key].[file's extension]
-
- /*
- * Add some uniqueness
- */
- $unique = self::getUniqueString(mt_rand());
-
- /*
- * Finally build and return the unique name
- */
-
- if ($objectId > 0) {
- $template = '%s-%s-%s.%s'; // [file's name]-[unique key]-[object ID].[file's extension]
-
- return sprintf($template, $withoutExtension, $unique, $objectId, $extension);
- }
-
- return sprintf($template, $withoutExtension, $unique, $extension);
- }
-
/**
* Returns file name without extension
*
@@ -271,7 +433,7 @@ class Miscellaneous
{
$matches = [];
- if (is_string($fileName) && (bool)preg_match('|(.+)\.(.+)|', $fileName, $matches)) {
+ if (is_string($fileName) && (bool) preg_match('|(.+)\.(.+)|', $fileName, $matches)) {
return $matches[1];
}
@@ -279,92 +441,291 @@ class Miscellaneous
}
/**
- * Converts value to non-negative integer (element of the set {0, 1, 2, 3, ...})
+ * Returns size (of file or directory) in human readable format
*
- * @param mixed $value Value to convert
- * @param int $negativeReplacement (optional) Replacement for negative value
- * @return int
+ * @param int $sizeInBytes The size in bytes
+ * @return string
*/
- public static function value2NonNegativeInteger($value, $negativeReplacement = 0)
+ public static function getHumanReadableSize($sizeInBytes)
{
- $effect = (int)$value;
+ $units = [
+ 'B',
+ 'KB',
+ 'MB',
+ 'GB',
+ 'TB',
+ 'PB',
+ ];
- if ($effect < 0) {
- return $negativeReplacement;
+ $index = floor(log($sizeInBytes, 1024));
+ $size = round($sizeInBytes / (1024 ** $index), 2);
+ $unit = $units[(int) $index];
+
+ return sprintf('%s %s', $size, $unit);
+ }
+
+ /**
+ * 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.
+ */
+ $validColor = Regex::getValidColorHexValue($color);
+
+ // Grab color's components
+ $red = hexdec(substr($validColor, 0, 2));
+ $green = hexdec(substr($validColor, 2, 2));
+ $blue = hexdec(substr($validColor, 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 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 null|string
+ */
+ public static function getLastElementOfString($string, $separator): ?string
+ {
+ $elements = self::getStringElements($string, $separator);
+
+ if (empty($elements)) {
+ return null;
+ }
+
+ return Arrays::getLastElement($elements);
+ }
+
+ /**
+ * 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 information if given PHP module is compiled and loaded
+ * Returns operating system name PHP is running on
*
- * @param string $phpModuleName PHP module name
- * @return bool
+ * @return string
*/
- public static function isPhpModuleLoaded($phpModuleName)
+ public static function getOperatingSystemNameServer()
{
- $phpModulesArray = get_loaded_extensions();
-
- return in_array($phpModuleName, $phpModulesArray, false);
+ return PHP_OS;
+ /*
+ * Previous version:
+ * return php_uname('s');
+ */
}
/**
- * Converts given string characters to latin characters
+ * Returns project's root path.
+ * Looks for directory that contains composer.json.
*
- * @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 = '-')
+ public static function getProjectRootPath(): string
{
- if (is_string($string)) {
- $string = trim($string);
+ $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);
}
- /*
- * Empty value?
- * Nothing to do
- */
- if (empty($string)) {
- return '';
- }
+ return $projectRootPath;
+ }
- $converter = Transliterator::create('Latin-ASCII;');
+ /**
+ * 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);
- /*
- * Oops, cannot instantiate converter
- * Nothing to do
- */
- if (null === $converter) {
- return '';
- }
+ if (null === $value) {
+ $globalSource = null;
- $converted = $converter->transliterate($string);
+ switch ($globalSourceType) {
+ case INPUT_GET:
+ $globalSource = $_GET;
- /*
- * Make the string lowercase and human-readable
- */
- if ($lowerCaseHuman) {
- $matches = [];
- $matchCount = preg_match_all('|[A-Z]{1}[^A-Z]*|', $converted, $matches);
+ break;
+ case INPUT_POST:
+ $globalSource = $_POST;
- if ($matchCount > 0) {
- $parts = $matches[0];
- $converted = mb_strtolower(implode($replacementChar, $parts));
+ 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];
}
}
- /*
- * Let's replace special characters to spaces
- * ...and finally spaces to $replacementChar
- */
- $replaced = preg_replace('|[^a-zA-Z0-9]|', ' ', $converted);
+ return $value;
+ }
- return preg_replace('| +|', $replacementChar, trim($replaced));
+ /**
+ * 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 $string, string $separator): array
+ {
+ if (empty($string) || empty($separator)) {
+ return [];
+ }
+
+ $matches = [];
+ $pattern = sprintf('|[^\%s]+|', $separator);
+ $matchCount = preg_match_all($pattern, $string, $matches);
+
+ if ($matchCount > 1) {
+ return $matches[0];
+ }
+
+ return [];
+ }
+
+ /**
+ * 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 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 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)
+ {
+ $withoutExtension = self::getFileNameWithoutExtension($originalFileName);
+ $extension = self::getFileExtension($originalFileName, true);
+
+ /*
+ * Let's clear name of file
+ *
+ * Attention.
+ * The name without extension should be cleared 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.%s'; // [file's name]-[unique key].[file's extension]
+
+ // Add some uniqueness
+ $unique = self::getUniqueString(mt_rand());
+
+ // Finally build and return the unique name
+ if ($objectId > 0) {
+ $template = '%s-%s-%s.%s'; // [file's name]-[unique key]-[object ID].[file's extension]
+
+ return sprintf($template, $withoutExtension, $unique, $objectId, $extension);
+ }
+
+ return sprintf($template, $withoutExtension, $unique, $extension);
}
/**
@@ -386,14 +747,295 @@ class Miscellaneous
return $unique;
}
+ /**
+ * 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);
+ }
+
+ return $hexadecimal;
+ }
+
+ return $colorComponent;
+ }
+
+ /**
+ * 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)
+ {
+ $fileExtension = self::getFileExtension($fileName, true);
+
+ /*
+ * File has given extension?
+ * Nothing to do
+ */
+ if ($fileExtension === strtolower($extension)) {
+ return $fileName;
+ }
+
+ return sprintf('%s.%s', $fileName, $extension);
+ }
+
+ /**
+ * Returns information if given value is located in interval between given utmost left and right values
+ *
+ * @param float|int $value Value to verify
+ * @param float|int $left Left utmost value of interval
+ * @param float|int $right Right utmost value of interval
+ * @return bool
+ */
+ public static function isBetween($value, $left, $right)
+ {
+ return $value > $left && $value < $right;
+ }
+
+ /**
+ * Returns information if value is decimal
+ *
+ * @param mixed $value The value to check
+ * @return bool
+ */
+ public static function isDecimal($value)
+ {
+ return is_scalar($value) && is_numeric($value) && floor($value) !== (float) $value;
+ }
+
+ /**
+ * 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']);
+ }
+
+ /**
+ * 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, false);
+ }
+
+ /**
+ * Make a string's first character lowercase
+ *
+ * @param string $text The text to get first character lowercase
+ * @param null|bool $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 lowercaseFirst($text, $restLowercase = null)
+ {
+ if (empty($text)) {
+ return '';
+ }
+
+ $effect = $text;
+
+ if ($restLowercase) {
+ $effect = mb_strtolower($effect);
+ } elseif (false === $restLowercase) {
+ $effect = mb_strtoupper($effect);
+ }
+
+ return lcfirst($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;
+ }
+
+ /**
+ * 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 itself. Otherwise - directory is removed too (default behaviour).
+ * @return null|bool
+ */
+ public static function removeDirectory($directoryPath, $contentOnly = false)
+ {
+ /*
+ * Directory does not exist?
+ * Nothing to do
+ */
+ if (!file_exists($directoryPath)) {
+ return null;
+ }
+
+ /*
+ * It's not a directory?
+ * Let's treat it like file
+ */
+ if (!is_dir($directoryPath)) {
+ return unlink($directoryPath);
+ }
+
+ foreach (scandir($directoryPath, SCANDIR_SORT_ASCENDING) as $item) {
+ if ('.' === $item || '..' === $item) {
+ continue;
+ }
+
+ if (!self::removeDirectory($directoryPath.DIRECTORY_SEPARATOR.$item)) {
+ return false;
+ }
+ }
+
+ // Directory should be removed too?
+ if (!$contentOnly) {
+ return rmdir($directoryPath);
+ }
+
+ return true;
+ }
+
+ /**
+ * 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;
+ }
+
+ /**
+ * Removes marginal character (first or last) from given string
+ *
+ * @param string $string The string which should be shortened
+ * @param bool $last (optional) If is set to true, last element is removed (default behaviour). Otherwise -
+ * first.
+ * @return null|string
+ */
+ public static function removeMarginalCharacter(string $string, bool $last = true): ?string
+ {
+ if (empty($string)) {
+ return null;
+ }
+
+ if ($last) {
+ return substr($string, 0, -1);
+ }
+
+ return substr($string, 1);
+ }
+
+ /**
+ * 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;
+ }
+
/**
* 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
+ * @param array|string $subject The string or an array of strings to search and replace
+ * @param array|string $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
+ * @param array|string $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
@@ -454,11 +1096,11 @@ class Miscellaneous
if ($quoteStrings) {
if ($replacementIsString) {
- $replacement = '\'' . $replacement . '\'';
+ $replacement = '\''.$replacement.'\'';
} elseif ($replacementIsArray) {
foreach ($replacement as &$item) {
if (is_string($item)) {
- $item = '\'' . $item . '\'';
+ $item = '\''.$item.'\'';
}
}
@@ -466,9 +1108,7 @@ class Miscellaneous
}
}
- /*
- * 1st step: replace strings, simple operation with strings
- */
+ // 1st step: replace strings, simple operation with strings
if ($bothAreStrings) {
$effect = str_replace($search, $replacement, $subject);
}
@@ -503,15 +1143,10 @@ class Miscellaneous
$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)
- */
+ // I have to iterate through the subjects, because explode() function expects strings as both arguments
+ // (1st and 2nd)
foreach ($subject as $subSubject) {
$subEffect = '';
@@ -521,9 +1156,7 @@ class Miscellaneous
foreach ($exploded as $key => $item) {
$subEffect .= $item;
- /*
- * The replacement shouldn't be included when the searched string was not found
- */
+ // 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];
}
@@ -531,6 +1164,7 @@ class Miscellaneous
if ($subjectIsArray) {
$effect[] = $subEffect;
+
continue;
}
@@ -541,43 +1175,6 @@ class Miscellaneous
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_OS;
-
- /*
- * Previous version:
- * return php_uname('s');
- */
- }
-
/**
* Returns part of string preserving words
*
@@ -586,21 +1183,22 @@ class Miscellaneous
* @param string $suffix (optional) The suffix to add at the end of string
* @return string
*/
- public static function substringToWord($text, $maxLength, $suffix = '...')
+ public static function substringToWord(string $text, int $maxLength, string $suffix = '...'): string
{
$effect = $text;
+ $encoding = 'utf-8';
- $textLength = mb_strlen($text, 'utf-8');
- $suffixLength = mb_strlen($suffix, 'utf-8');
+ $textLength = mb_strlen($text, $encoding);
+ $suffixLength = mb_strlen($suffix, $encoding);
$maxLength -= $suffixLength;
if ($textLength > $maxLength) {
- $effect = mb_substr($text, 0, $maxLength, 'utf-8');
- $lastSpacePosition = mb_strrpos($effect, ' ', 'utf-8');
+ $effect = mb_substr($text, 0, $maxLength, $encoding);
+ $lastSpacePosition = mb_strrpos($effect, ' ', 0, $encoding);
if (false !== $lastSpacePosition) {
- $effect = mb_substr($effect, 0, $lastSpacePosition, 'utf-8');
+ $effect = mb_substr($effect, 0, $lastSpacePosition, $encoding);
}
$effect .= $suffix;
@@ -610,215 +1208,84 @@ class Miscellaneous
}
/**
- * Breaks long text
+ * Converts given string characters to latin characters
*
- * @param string $text The text to check and break
- * @param int $perLine (optional) Characters count per line. Default: 100.
- * @param string $separator (optional) Separator that is placed between lines. Default: "
".
- * @param string $encoding (optional) Character encoding. Used by mb_substr(). Default: "UTF-8".
- * @param int $proportionalAberration (optional) Proportional aberration for chars (percent value). Default: 20.
+ * @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 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 (false !== $spacePosition && 0 < $spacePosition) {
- /* @var int $spacePosition */
- $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;
- }
+ public static function toLatin($string, $lowerCaseHuman = true, $replacementChar = '-')
+ {
+ if (is_string($string)) {
+ $string = trim($string);
}
- 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 itself. Otherwise - directory is removed too (default behaviour).
- * @return bool|null
- */
- public static function removeDirectory($directoryPath, $contentOnly = false)
- {
/*
- * Directory does not exist?
+ * Empty value?
* Nothing to do
*/
- if (!file_exists($directoryPath)) {
- return null;
- }
-
- /*
- * It's not a directory?
- * Let's treat it like file
- */
- if (!is_dir($directoryPath)) {
- return unlink($directoryPath);
- }
-
- foreach (scandir($directoryPath, SCANDIR_SORT_ASCENDING) as $item) {
- if ('.' === $item || '..' === $item) {
- continue;
- }
-
- if (!self::removeDirectory($directoryPath . DIRECTORY_SEPARATOR . $item)) {
- return false;
- }
- }
-
- /*
- * Directory should be removed too?
- */
- 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);
+ $converter = Transliterator::create('Latin-ASCII;');
- 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
- */
- public static function lowercaseFirst($text, $restLowercase = null)
- {
- if (empty($text)) {
+ /*
+ * Oops, cannot instantiate converter
+ * Nothing to do
+ */
+ if (null === $converter) {
return '';
}
- $effect = $text;
+ $converted = $converter->transliterate($string);
- if ($restLowercase) {
- $effect = mb_strtolower($effect);
- } elseif (false === $restLowercase) {
- $effect = mb_strtoupper($effect);
+ // 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));
+ }
}
- return lcfirst($effect);
+ /*
+ * 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 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;
}
/**
* 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
+ * @param null|bool $restLowercase (optional) Information that to do with rest of given string
* @return string
*
* Values of the $restLowercase argument:
@@ -844,507 +1311,20 @@ class Miscellaneous
}
/**
- * Quotes given value with apostrophes or quotation marks
+ * Converts value to non-negative integer (element of the set {0, 1, 2, 3, ...})
*
- * @param mixed $value The value to quote
- * @param bool $useApostrophe (optional) If is set to true, apostrophes are used. Otherwise - quotation marks.
- * @return string
+ * @param mixed $value Value to convert
+ * @param int $negativeReplacement (optional) Replacement for negative value
+ * @return int
*/
- public static function quoteValue($value, $useApostrophe = true)
+ public static function value2NonNegativeInteger($value, $negativeReplacement = 0)
{
- if (is_string($value)) {
- $quotes = '"';
+ $effect = (int) $value;
- 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 / (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));
+ if ($effect < 0) {
+ return $negativeReplacement;
}
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];
- }
- }
-
- return $value;
- }
-
- /**
- * 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 .= '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);
- }
-
- 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.
- */
- $validColor = Regex::getValidColorHexValue($color);
-
- /*
- * Grab color's components
- */
- $red = hexdec(substr($validColor, 0, 2));
- $green = hexdec(substr($validColor, 2, 2));
- $blue = hexdec(substr($validColor, 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/Utilities/QueryBuilderUtility.php b/src/Utilities/QueryBuilderUtility.php
index 0e87ed1..392525b 100644
--- a/src/Utilities/QueryBuilderUtility.php
+++ b/src/Utilities/QueryBuilderUtility.php
@@ -23,25 +23,68 @@ use Doctrine\ORM\QueryBuilder;
class QueryBuilderUtility
{
/**
- * Returns root alias of given query builder.
- * If null is returned, alias was not found.
+ * Adds given parameters to given query builder.
+ * Attention. Existing parameters will be overridden.
*
- * @param QueryBuilder $queryBuilder The query builder to retrieve root alias
- * @return null|string
+ * @param QueryBuilder $queryBuilder The query builder
+ * @param array|ArrayCollection $parameters Parameters to add. Collection of Doctrine\ORM\Query\Parameter
+ * instances or an array with key-value pairs.
+ * @return QueryBuilder
*/
- public static function getRootAlias(QueryBuilder $queryBuilder)
+ public static function addParameters(QueryBuilder $queryBuilder, $parameters)
{
- $aliases = $queryBuilder->getRootAliases();
-
/*
- * No aliases?
+ * No parameters?
* Nothing to do
*/
- if (empty($aliases)) {
- return null;
+ if (empty($parameters)) {
+ return $queryBuilder;
}
- return Arrays::getFirstElement($aliases);
+ foreach ($parameters as $key => $parameter) {
+ $name = $key;
+ $value = $parameter;
+
+ if ($parameter instanceof Parameter) {
+ $name = $parameter->getName();
+ $value = $parameter->getValue();
+ }
+
+ $queryBuilder->setParameter($name, $value);
+ }
+
+ return $queryBuilder;
+ }
+
+ /**
+ * Deletes given entities
+ *
+ * @param EntityManager $entityManager The entity manager
+ * @param array|ArrayCollection $entities The entities to delete
+ * @param bool $flushDeleted (optional) If is set to true, flushes the deleted objects (default
+ * behaviour). Otherwise - not.
+ * @return bool
+ */
+ public static function deleteEntities(EntityManager $entityManager, $entities, $flushDeleted = true)
+ {
+ /*
+ * No entities provided?
+ * Nothing to do
+ */
+ if (empty($entities)) {
+ return false;
+ }
+
+ foreach ($entities as $entity) {
+ $entityManager->remove($entity);
+ }
+
+ // The deleted objects should be flushed?
+ if ($flushDeleted) {
+ $entityManager->flush();
+ }
+
+ return true;
}
/**
@@ -70,7 +113,7 @@ class QueryBuilderUtility
$pattern = sprintf($patternTemplate, $property);
foreach ($joins as $joinExpressions) {
- /* @var $expression Join */
+ /** @var Join $expression */
foreach ($joinExpressions as $expression) {
$joinedProperty = $expression->getJoin();
@@ -83,6 +126,28 @@ class QueryBuilderUtility
return null;
}
+ /**
+ * Returns root alias of given query builder.
+ * If null is returned, alias was not found.
+ *
+ * @param QueryBuilder $queryBuilder The query builder to retrieve root alias
+ * @return null|string
+ */
+ public static function getRootAlias(QueryBuilder $queryBuilder)
+ {
+ $aliases = $queryBuilder->getRootAliases();
+
+ /*
+ * No aliases?
+ * Nothing to do
+ */
+ if (empty($aliases)) {
+ return null;
+ }
+
+ return Arrays::getFirstElement($aliases);
+ }
+
/**
* Sets the WHERE criteria in given query builder
*
@@ -90,7 +155,7 @@ class QueryBuilderUtility
* @param array $criteria (optional) The criteria used in WHERE clause. It may simple array with pairs
* key-value or an array of arrays where second element of sub-array is the
* comparison operator. Example below.
- * @param string|null $alias (optional) Alias used in the query
+ * @param null|string $alias (optional) Alias used in the query
* @return QueryBuilder
*
* Example of the $criteria argument:
@@ -149,71 +214,4 @@ class QueryBuilderUtility
return $queryBuilder;
}
-
- /**
- * Deletes given entities
- *
- * @param EntityManager $entityManager The entity manager
- * @param array|ArrayCollection $entities The entities to delete
- * @param bool $flushDeleted (optional) If is set to true, flushes the deleted objects (default
- * behaviour). Otherwise - not.
- * @return bool
- */
- public static function deleteEntities(EntityManager $entityManager, $entities, $flushDeleted = true)
- {
- /*
- * No entities provided?
- * Nothing to do
- */
- if (empty($entities)) {
- return false;
- }
-
- foreach ($entities as $entity) {
- $entityManager->remove($entity);
- }
-
- /*
- * The deleted objects should be flushed?
- */
- if ($flushDeleted) {
- $entityManager->flush();
- }
-
- return true;
- }
-
- /**
- * Adds given parameters to given query builder.
- * Attention. Existing parameters will be overridden.
- *
- * @param QueryBuilder $queryBuilder The query builder
- * @param array|ArrayCollection $parameters Parameters to add. Collection of Doctrine\ORM\Query\Parameter
- * instances or an array with key-value pairs.
- * @return QueryBuilder
- */
- public static function addParameters(QueryBuilder $queryBuilder, $parameters)
- {
- /*
- * No parameters?
- * Nothing to do
- */
- if (empty($parameters)) {
- return $queryBuilder;
- }
-
- foreach ($parameters as $key => $parameter) {
- $name = $key;
- $value = $parameter;
-
- if ($parameter instanceof Parameter) {
- $name = $parameter->getName();
- $value = $parameter->getValue();
- }
-
- $queryBuilder->setParameter($name, $value);
- }
-
- return $queryBuilder;
- }
}
diff --git a/src/Utilities/Reflection.php b/src/Utilities/Reflection.php
index c3fbafe..be86a2a 100644
--- a/src/Utilities/Reflection.php
+++ b/src/Utilities/Reflection.php
@@ -8,13 +8,18 @@
namespace Meritoo\Common\Utilities;
-use Doctrine\Common\Util\ClassUtils;
-use Doctrine\Common\Util\Inflector;
-use Meritoo\Common\Collection\Collection;
+use Doctrine\Inflector\InflectorFactory;
+use Doctrine\Persistence\Proxy;
+use Meritoo\Common\Contract\Collection\CollectionInterface;
use Meritoo\Common\Exception\Reflection\CannotResolveClassNameException;
use Meritoo\Common\Exception\Reflection\MissingChildClassesException;
use Meritoo\Common\Exception\Reflection\NotExistingPropertyException;
use Meritoo\Common\Exception\Reflection\TooManyChildClassesException;
+use ReflectionClass;
+use ReflectionException;
+use ReflectionMethod;
+use ReflectionObject;
+use ReflectionProperty;
/**
* Useful reflection methods
@@ -25,289 +30,56 @@ use Meritoo\Common\Exception\Reflection\TooManyChildClassesException;
class Reflection
{
/**
- * Returns names of methods for given class / object
+ * 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 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
+ * @param array|object|string $class Class who child classes should be returned. An array of objects, strings,
+ * object or string.
+ * @return null|array
+ * @throws CannotResolveClassNameException
*/
- public static function getMethods($class, $withoutInheritance = false)
+ public static function getChildClasses($class): ?array
{
- $effect = [];
+ $allClasses = get_declared_classes();
- $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 integer value of constant of given class / object.
- * Constants whose values are integers are considered only.
- *
- * @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)) {
+ /*
+ * No classes?
+ * Nothing to do
+ */
+ if (empty($allClasses)) {
return null;
}
- $maxNumber = 0;
+ $className = self::getClassName($class);
- foreach ($constants as $constant) {
- if (is_numeric($constant) && $constant > $maxNumber) {
- $maxNumber = $constant;
- }
+ // Oops, cannot resolve class
+ if (null === $className) {
+ throw CannotResolveClassNameException::create('');
}
- return $maxNumber;
- }
+ $childClasses = [];
- /**
- * 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
- *
- * Meritoo
- * 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) {
+ foreach ($allClasses as $oneClass) {
+ if (self::isChildOfClass($oneClass, $className)) {
/*
- * 2nd try:
- * Look for the get / has / is methods
+ * Attention. I have to use static::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.
*/
- $class = new \ReflectionObject($object);
- $valueFound = false;
+ $realClass = static::getRealClass($oneClass);
- if ($force || $class->hasProperty($property)) {
- $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 (in_array($realClass, $childClasses, true)) {
+ continue;
}
- 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);
- }
+ $childClasses[] = $realClass;
}
}
- 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;
+ return $childClasses;
}
/**
@@ -316,9 +88,9 @@ class Reflection
* @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
+ * @return null|string
*/
- public static function getClassName($source, $withoutNamespace = false)
+ public static function getClassName($source, bool $withoutNamespace = false): ?string
{
/*
* First argument is not proper source of class?
@@ -338,9 +110,7 @@ class Reflection
$source = Arrays::getFirstElement($source);
}
- /*
- * Let's prepare name of class
- */
+ // Let's prepare name of class
if (is_object($source)) {
$name = get_class($source);
} elseif (is_string($source) && (class_exists($source) || trait_exists($source))) {
@@ -369,7 +139,7 @@ class Reflection
return $name;
}
- return ClassUtils::getRealClass($name);
+ return static::getRealClass($name);
}
/**
@@ -378,7 +148,7 @@ class Reflection
* @param array|object|string $source An array of objects, namespaces, object or namespace
* @return string
*/
- public static function getClassNamespace($source)
+ public static function getClassNamespace($source): string
{
$fullClassName = self::getClassName($source);
@@ -396,145 +166,92 @@ class Reflection
}
/**
- * Returns information if given interface is implemented by given class / object
+ * Returns value of given constant
*
- * @param array|object|string $source An array of objects, namespaces, object or namespace
- * @param string $interface The interface that should be implemented
- * @return bool
+ * @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 isInterfaceImplemented($source, $interface)
+ public static function getConstantValue($class, string $constant)
{
- $className = self::getClassName($source);
- $interfaces = class_implements($className);
+ $reflection = new ReflectionClass($class);
- return in_array($interface, $interfaces, true);
- }
-
- /**
- * 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) && 0 < count($parents)) {
- return in_array($parentClassName, $parents, true);
+ if (self::hasConstant($class, $constant)) {
+ return $reflection->getConstant($constant);
}
- return false;
+ return null;
}
/**
- * Returns given object properties
+ * Returns constants of given class / object
*
- * @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
+ * @param object|string $class The object or name of object's class
+ * @return array
*/
- public static function getProperties($source, $filter = null, $includeParents = false)
+ public static function getConstants($class): array
{
- $className = self::getClassName($source);
- $reflection = new \ReflectionClass($className);
+ $reflection = new ReflectionClass($class);
- 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);
+ return $reflection->getConstants();
}
/**
- * Returns a parent class or false if there is no parent class
+ * Returns maximum integer value of constant of given class / object.
+ * Constants whose values are integers are considered only.
*
- * @param array|object|string $source An array of objects, namespaces, object or namespace
- * @return \ReflectionClass|bool
+ * @param object|string $class The object or name of object's class
+ * @return null|int
*/
- public static function getParentClass($source)
+ public static function getMaxNumberConstant($class): ?int
{
- $className = self::getClassName($source);
- $reflection = new \ReflectionClass($className);
+ $constants = self::getConstants($class);
- 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.
- * @throws CannotResolveClassNameException
- * @return array|null
- */
- public static function getChildClasses($class)
- {
- $allClasses = get_declared_classes();
-
- /*
- * No classes?
- * Nothing to do
- */
- if (empty($allClasses)) {
+ if (empty($constants)) {
return null;
}
- $className = self::getClassName($class);
+ $maxNumber = 0;
- /*
- * Oops, cannot resolve class
- */
- if (null === $className) {
- throw CannotResolveClassNameException::create($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, true)) {
- continue;
- }
-
- $childClasses[] = $realClass;
+ foreach ($constants as $constant) {
+ if (is_numeric($constant) && $constant > $maxNumber) {
+ $maxNumber = $constant;
}
}
- return $childClasses;
+ return $maxNumber;
+ }
+
+ /**
+ * 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, bool $withoutInheritance = false): array
+ {
+ $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;
}
/**
@@ -543,9 +260,8 @@ class Reflection
*
* @param array|object|string $parentClass Class who child class should be returned. An array of objects,
* namespaces, object or namespace.
- * @throws MissingChildClassesException
- * @throws TooManyChildClassesException
* @return mixed
+ * @throws TooManyChildClassesException|MissingChildClassesException|CannotResolveClassNameException
*/
public static function getOneChildClass($parentClass)
{
@@ -570,22 +286,92 @@ class Reflection
return trim($childClasses[0]);
}
+ /**
+ * 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 false|ReflectionClass
+ */
+ public static function getParentClass($source)
+ {
+ $className = self::getClassName($source);
+ $reflection = new ReflectionClass($className);
+
+ return $reflection->getParentClass();
+ }
+
+ /**
+ * 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 null|string
+ */
+ public static function getParentClassName($class): ?string
+ {
+ $className = self::getClassName($class);
+ $reflection = new ReflectionClass($className);
+ $parentClass = $reflection->getParentClass();
+
+ if (null === $parentClass || false === $parentClass) {
+ return null;
+ }
+
+ return $parentClass->getName();
+ }
+
+ /**
+ * 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 ReflectionProperty[]
+ */
+ public static function getProperties($source, int $filter = null, bool $includeParents = false): array
+ {
+ $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 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.
+ * @param int|null $filter (optional) Filter of properties. Uses \ReflectionProperty class constants.
* By default all properties are allowed / processed.
- * @return null|\ReflectionProperty
+ * @return null|ReflectionProperty
*/
- public static function getProperty($class, $property, $filter = null)
+ public static function getProperty($class, string $property, int $filter = null): ?ReflectionProperty
{
$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;
@@ -596,6 +382,217 @@ class Reflection
return null;
}
+ /**
+ * Returns value of given property
+ *
+ * @param mixed $source 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($source, string $property, bool $force = false)
+ {
+ if (Regex::contains($property, '.')) {
+ return self::getPropertyValueByPropertiesChain($source, $property, $force);
+ }
+
+ [
+ $value,
+ $valueFound,
+ ] = self::getPropertyValueByReflectionProperty($source, $property);
+
+ if (!$valueFound) {
+ [
+ $value,
+ $valueFound,
+ ] = self::getPropertyValueByParentClasses($source, $property);
+ }
+
+ if (!$valueFound && ($force || self::hasProperty($source, $property))) {
+ [
+ $value,
+ $valueFound,
+ ] = self::getPropertyValueByGetter($source, $property);
+ }
+
+ if (!$valueFound) {
+ $byReflectionProperty = self::getPropertyValueByReflectionProperty($source, $property);
+ $value = $byReflectionProperty[0];
+ }
+
+ return $value;
+ }
+
+ /**
+ * Returns values of given property for given objects.
+ * Looks for proper getter for the property.
+ *
+ * @param array|CollectionInterface|object $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, string $property, bool $force = false): array
+ {
+ /*
+ * No objects?
+ * Nothing to do
+ */
+ if (empty($objects)) {
+ return [];
+ }
+
+ if ($objects instanceof CollectionInterface) {
+ $objects = $objects->toArray();
+ }
+
+ $values = [];
+ $objects = Arrays::makeArray($objects);
+
+ foreach ($objects as $object) {
+ $value = self::getPropertyValue($object, $property, $force);
+
+ if (null !== $value) {
+ $values[] = $value;
+ }
+ }
+
+ return $values;
+ }
+
+ /**
+ * 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, string $constant): bool
+ {
+ $reflection = new ReflectionClass($class);
+
+ return $reflection->hasConstant($constant);
+ }
+
+ /**
+ * 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, string $method): bool
+ {
+ $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, string $property): bool
+ {
+ $reflection = new ReflectionClass($class);
+
+ return $reflection->hasProperty($property);
+ }
+
+ /**
+ * 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): bool
+ {
+ $childClassName = self::getClassName($childClass);
+ $parentClassName = self::getClassName($parentClass);
+
+ $parents = class_parents($childClassName);
+
+ if (is_array($parents) && 0 < count($parents)) {
+ return in_array($parentClassName, $parents, true);
+ }
+
+ return false;
+ }
+
+ /**
+ * 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, string $interface): bool
+ {
+ $className = self::getClassName($source);
+ $interfaces = class_implements($className);
+
+ return in_array($interface, $interfaces, true);
+ }
+
+ /**
+ * Sets values of properties in given object
+ *
+ * @param mixed $object Object that should contains given property
+ * @param array $propertiesValues Key-value pairs, where key - name of the property, value - value of the property
+ */
+ public static function setPropertiesValues($object, array $propertiesValues): void
+ {
+ /*
+ * No properties?
+ * Nothing to do
+ */
+ if (empty($propertiesValues)) {
+ return;
+ }
+
+ foreach ($propertiesValues as $property => $value) {
+ static::setPropertyValue($object, $property, $value);
+ }
+ }
+
+ /**
+ * Sets value of given property in given object
+ *
+ * @param mixed $object Object that should contains given property
+ * @param string $property Name of the property
+ * @param mixed $value Value of the property
+ * @throws NotExistingPropertyException
+ */
+ public static function setPropertyValue($object, string $property, $value): void
+ {
+ $reflectionProperty = self::getProperty($object, $property);
+
+ // Oops, property does not exist
+ if (null === $reflectionProperty) {
+ throw NotExistingPropertyException::create($object, $property);
+ }
+
+ $isPublic = $reflectionProperty->isPublic();
+
+ if (!$isPublic) {
+ $reflectionProperty->setAccessible(true);
+ }
+
+ $reflectionProperty->setValue($object, $value);
+
+ if (!$isPublic) {
+ $reflectionProperty->setAccessible(false);
+ }
+ }
+
/**
* Returns information if given class / object uses / implements given trait
*
@@ -603,29 +600,25 @@ class Reflection
* @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.
- * @throws CannotResolveClassNameException
- * @return bool|null
+ * @return null|bool
+ * @throws CannotResolveClassNameException|ReflectionException
*/
- public static function usesTrait($class, $trait, $verifyParents = false)
+ public static function usesTrait($class, $trait, bool $verifyParents = false): ?bool
{
$className = self::getClassName($class);
$traitName = self::getClassName($trait);
- /*
- * Oops, cannot resolve class
- */
+ // Oops, cannot resolve class
if (null === $className || '' === $className) {
- throw CannotResolveClassNameException::create($class);
+ throw CannotResolveClassNameException::create('');
}
- /*
- * Oops, cannot resolve trait
- */
+ // Oops, cannot resolve trait
if (null === $traitName || '' === $traitName) {
- throw new CannotResolveClassNameException($class, false);
+ throw CannotResolveClassNameException::create('', false);
}
- $reflection = new \ReflectionClass($className);
+ $reflection = new ReflectionClass($className);
$traitsNames = $reflection->getTraitNames();
$uses = in_array($traitName, $traitsNames, true);
@@ -642,75 +635,197 @@ class Reflection
}
/**
- * Returns name of the parent class.
- * If given class does not extend another, returns null.
+ * Returns value of given property using getter of the property
*
- * @param array|object|string $class An array of objects, namespaces, object or namespace
- * @return string|null
+ * An array with 2 elements is returned:
+ * - value of given property
+ * - information if the value was found (because null may be returned)
+ *
+ * @param mixed $source Object that should contains given property
+ * @param string $property Name of the property that contains a value
+ * @return array
*/
- public static function getParentClassName($class)
+ private static function getPropertyValueByGetter($source, string $property): array
{
- $className = self::getClassName($class);
- $reflection = new \ReflectionClass($className);
- $parentClass = $reflection->getParentClass();
+ $value = null;
+ $valueFound = false;
- if (null === $parentClass || false === $parentClass) {
- return null;
+ $reflectionObject = new ReflectionObject($source);
+ $inflector = InflectorFactory::create()->build();
+ $property = $inflector->classify($property);
+
+ $gettersPrefixes = [
+ 'get',
+ 'has',
+ 'is',
+ ];
+
+ foreach ($gettersPrefixes as $prefix) {
+ $getter = sprintf('%s%s', $prefix, $property);
+
+ if ($reflectionObject->hasMethod($getter)) {
+ $method = new ReflectionMethod($source, $getter);
+
+ /*
+ * 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 = $source->{$getter}();
+ $valueFound = true;
+
+ break;
+ }
}
- return $parentClass->getName();
+ return [
+ $value,
+ $valueFound,
+ ];
}
/**
- * Sets value of given property in given object
+ * Returns value of given property using parent classes
*
- * @param mixed $object Object that should contains given property
- * @param string $property Name of the property
- * @param mixed $value Value of the property
- * @throws NotExistingPropertyException
+ * @param mixed $source Object that should contains given property
+ * @param string $property Name of the property that contains a value
+ * @return array
*/
- public static function setPropertyValue($object, $property, $value)
+ private static function getPropertyValueByParentClasses($source, string $property): array
{
- $reflectionProperty = self::getProperty($object, $property);
+ $properties = self::getProperties($source, null, true);
+
+ if (empty($properties)) {
+ return [
+ null,
+ false,
+ ];
+ }
+
+ foreach ($properties as $reflectionProperty) {
+ if ($reflectionProperty->getName() === $property) {
+ $byReflectionProperty = self::getPropertyValueByReflectionProperty(
+ $source,
+ $property,
+ $reflectionProperty
+ );
+
+ return [
+ $byReflectionProperty[0],
+ true,
+ ];
+ }
+ }
+
+ return [
+ null,
+ false,
+ ];
+ }
+
+ /**
+ * Returns value of given property represented as chain of properties
+ *
+ * @param mixed $source Object that should contains given property
+ * @param string $property Dot-separated properties, 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
+ */
+ private static function getPropertyValueByPropertiesChain($source, string $property, bool $force)
+ {
+ $exploded = explode('.', $property);
+
+ $property = $exploded[0];
+ $source = self::getPropertyValue($source, $property, $force);
/*
- * Oops, property does not exist
+ * 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
+ *
+ * Meritoo
+ * 2016-11-07
*/
- if (null === $reflectionProperty) {
- throw NotExistingPropertyException::create($object, $property);
+ if (null !== $source) {
+ unset($exploded[0]);
+ $property = implode('.', $exploded);
+
+ return self::getPropertyValue($source, $property, $force);
}
- $notAccessible = $reflectionProperty->isPrivate() || $reflectionProperty->isProtected();
+ return null;
+ }
- if ($notAccessible) {
+ /**
+ * Returns value of given property using the property represented by reflection.
+ * If value cannot be fetched, makes the property accessible temporarily.
+ *
+ * @param mixed $object Object that should contains given property
+ * @param string $property Name of the property that contains a value
+ * @param null|ReflectionProperty $reflectionProperty (optional) Property represented by reflection
+ * @return mixed
+ */
+ private static function getPropertyValueByReflectionProperty(
+ $object,
+ string $property,
+ ?ReflectionProperty $reflectionProperty = null
+ ) {
+ $value = null;
+ $valueFound = false;
+ $className = self::getClassName($object);
+
+ try {
+ if (null === $reflectionProperty) {
+ $reflectionProperty = new ReflectionProperty($className, $property);
+ }
+
+ $value = $reflectionProperty->getValue($object);
+ $valueFound = true;
+ } catch (ReflectionException $exception) {
+ }
+
+ if (null !== $reflectionProperty) {
$reflectionProperty->setAccessible(true);
- }
- $reflectionProperty->setValue($object, $value);
+ $value = $reflectionProperty->getValue($object);
+ $valueFound = true;
- if ($notAccessible) {
$reflectionProperty->setAccessible(false);
}
+
+ return [
+ $value,
+ $valueFound,
+ ];
}
/**
- * Sets values of properties in given object
+ * Returns the real class name of a class name that could be a proxy
*
- * @param mixed $object Object that should contains given property
- * @param array $propertiesValues Key-value pairs, where key - name of the property, value - value of the property
+ * @param string $class Class to verify
+ * @return string
*/
- public static function setPropertiesValues($object, array $propertiesValues)
+ private static function getRealClass(string $class): string
{
- /*
- * No properties?
- * Nothing to do
- */
- if (empty($propertiesValues)) {
- return;
+ if (false === $pos = strrpos($class, '\\'.Proxy::MARKER.'\\')) {
+ return $class;
}
- foreach ($propertiesValues as $property => $value) {
- static::setPropertyValue($object, $property, $value);
- }
+ return substr($class, $pos + Proxy::MARKER_LENGTH + 2);
}
}
diff --git a/src/Utilities/Regex.php b/src/Utilities/Regex.php
index 3f8f78b..78fab4d 100644
--- a/src/Utilities/Regex.php
+++ b/src/Utilities/Regex.php
@@ -10,6 +10,7 @@ namespace Meritoo\Common\Utilities;
use Meritoo\Common\Exception\Regex\IncorrectColorHexLengthException;
use Meritoo\Common\Exception\Regex\InvalidColorHexValueException;
+use Transliterator;
/**
* Useful methods related to regular expressions
@@ -25,21 +26,23 @@ class Regex
* @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]+;/',
- 'htmlAttribute' => '/([\w-]+)="([\w -]+)"/',
- 'fileName' => '/.+\.\w+$/',
- 'isQuoted' => '/^[\'"]{1}.+[\'"]{1}$/',
+ '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]+;/',
+ 'htmlAttribute' => '/([\w-]+)="([\w -]+)"/',
+ 'fileName' => '/[\w.\- +=!@$&()?]+\.\w+$/', // e.g. "this-1_2 3 & my! 4+file.jpg"
+ 'isQuoted' => '/^[\'"]{1}.+[\'"]{1}$/',
'windowsBasedPath' => '/^[A-Z]{1}:\\\.*$/',
- 'money' => '/^[-+]?\d+([\.,]{1}\d*)?$/',
- 'color' => '/^[a-f0-9]{6}$/i',
- 'bundleName' => '/^(([A-Z]{1}[a-z0-9]+)((?2))*)(Bundle)$/',
- 'binaryValue' => '/[^\x20-\x7E\t\r\n]/',
+ 'money' => '/^[-+]?\d+([\.,]{1}\d*)?$/',
+ 'color' => '/^[a-f0-9]{6}$/i',
+ 'bundleName' => '/^(([A-Z]{1}[a-z0-9]+)((?2))*)(Bundle)$/',
+ 'binaryValue' => '/[^\x20-\x7E\t\r\n]/',
+ 'beginningSlash' => '|^\/|',
+ 'endingSlash' => '|\/$|',
/*
* Matches:
@@ -51,9 +54,655 @@ class Regex
*
* Contains "%s" that should be replaced with separator used to split width and height.
*/
- 'size' => '/^[\ ]*(\d+)[\ ]*%s[\ ]*(\d+)[\ ]*$/',
+ 'size' => '/^[\ ]*(\d+)[\ ]*%s[\ ]*(\d+)[\ ]*$/',
];
+ /**
+ * Returns information if given html attributes are valid
+ *
+ * @param string $htmlAttributes The html attributes to verify
+ * @return bool
+ */
+ public static function areValidHtmlAttributes($htmlAttributes)
+ {
+ /*
+ * Not a string?
+ * Nothing to do
+ */
+ if (!is_string($htmlAttributes)) {
+ return false;
+ }
+
+ $pattern = self::getHtmlAttributePattern();
+
+ return (bool) preg_match_all($pattern, $htmlAttributes);
+ }
+
+ /**
+ * 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 2-dimensional array that should be filtered
+ * @param string $arrayColumnKey Column name
+ * @param string $filterExpression Simple filter expression (e.g. "== 2" or "!= \'home\'") or regular
+ * expression (e.g. "/\d+/" or "/[a-z]+[,;]{2,}/")
+ * @param bool $itsRegularExpression (optional) If is set to true, means that filter expression is a regular
+ * expression. Otherwise - not (default behaviour).
+ * @return array
+ */
+ public static function arrayFilter($array, $arrayColumnKey, $filterExpression, $itsRegularExpression = false)
+ {
+ /*
+ * No elements?
+ * Nothing to do
+ */
+ if (empty($array)) {
+ return [];
+ }
+
+ $effect = $array;
+
+ foreach ($effect as $key => &$item) {
+ if (!isset($item[$arrayColumnKey])) {
+ continue;
+ }
+
+ $value = $item[$arrayColumnKey];
+
+ if ($itsRegularExpression) {
+ $matchesCount = preg_match($filterExpression, $value);
+ $remove = 0 === $matchesCount;
+ } else {
+ if (is_string($value)) {
+ $value = sprintf('\'%s\'', $value);
+ } elseif (is_bool($value)) {
+ if (true === $value) {
+ $value = 'true';
+ } else {
+ $value = 'false';
+ }
+ }
+
+ eval(sprintf('$isEqual = %s%s;', $value, $filterExpression));
+
+ /** @var bool $isEqual */
+ $remove = !$isEqual;
+ }
+
+ if ($remove) {
+ unset($effect[$key]);
+ }
+ }
+
+ 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 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;
+ }
+
+ public static function clearBeginningSlash(string $string): string
+ {
+ $pattern = static::$patterns['beginningSlash'];
+
+ return preg_replace($pattern, '', $string);
+ }
+
+ public static function clearEndingSlash(string $string): string
+ {
+ $pattern = static::$patterns['endingSlash'];
+
+ return preg_replace($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 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 slug for given value
+ *
+ * @param string $value Value that should be transformed to slug
+ * @return bool|string
+ */
+ public static function createSlug($value)
+ {
+ /*
+ * Not a scalar value?
+ * Nothing to do
+ */
+ if (!is_scalar($value)) {
+ return false;
+ }
+
+ /*
+ * It's an empty string?
+ * Nothing to do
+ */
+ if ('' === $value) {
+ return '';
+ }
+
+ $id = 'Latin-ASCII; NFD; [:Nonspacing Mark:] Remove; NFC; [:Punctuation:] Remove; Lower();';
+ $transliterator = Transliterator::create($id);
+
+ $cleanValue = trim($value);
+ $result = $transliterator->transliterate($cleanValue);
+
+ return preg_replace('/[-\s]+/', '-', $result);
+ }
+
+ /**
+ * 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 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 array values that match given pattern (or values that keys match the pattern)
+ *
+ * @param string $pattern Pattern to match
+ * @param array $array The array (scalar values only)
+ * @param bool $itsKeyPattern (optional) If is set to true, keys will be checked if they match pattern.
+ * Otherwise - values will be checked (default behaviour).
+ * @return array
+ */
+ public static function getArrayValuesByPattern($pattern, array $array, $itsKeyPattern = false)
+ {
+ /*
+ * No elements?
+ * Nothing to do
+ */
+ if (empty($array)) {
+ return [];
+ }
+
+ if ($itsKeyPattern) {
+ $effect = [];
+
+ foreach ($array as $key => $value) {
+ if ((bool) preg_match($pattern, $key)) {
+ $effect[$key] = $value;
+ }
+ }
+
+ return $effect;
+ }
+
+ return preg_grep($pattern, $array);
+ }
+
+ /**
+ * Returns pattern used to validate / verify name of bundle
+ *
+ * @return string
+ */
+ public static function getBundleNamePattern()
+ {
+ return self::$patterns['bundleName'];
+ }
+
+ /**
+ * Returns pattern used to validate / verify or get camel case parts of string
+ *
+ * @return string
+ */
+ public static function getCamelCasePartPattern()
+ {
+ return self::$patterns['camelCasePart'];
+ }
+
+ /**
+ * 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 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 name of file
+ *
+ * @return string
+ */
+ public static function getFileNamePattern(): string
+ {
+ return self::$patterns['fileName'];
+ }
+
+ /**
+ * Returns pattern used to validate / verify html attribute
+ *
+ * @return string
+ */
+ public static function getHtmlAttributePattern()
+ {
+ return self::$patterns['htmlAttribute'];
+ }
+
+ /**
+ * Returns pattern used to validate / verify html entity
+ *
+ * @return string
+ */
+ public static function getHtmlEntityPattern()
+ {
+ return self::$patterns['htmlEntity'];
+ }
+
+ /**
+ * 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 pattern used to validate / verify letter or digit
+ *
+ * @return string
+ */
+ public static function getLetterOrDigitPattern()
+ {
+ return self::$patterns['letterOrDigit'];
+ }
+
+ /**
+ * Returns pattern used to validate / verify if given value is money-related value
+ *
+ * @return string
+ */
+ public static function getMoneyPattern()
+ {
+ return self::$patterns['money'];
+ }
+
+ /**
+ * 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 size
+ *
+ * @param string $separator (optional) Separator used to split width and height. Default: " x ".
+ * @return string
+ */
+ public static function getSizePattern($separator = ' x ')
+ {
+ $escapeMe = [
+ '/',
+ '|',
+ '.',
+ '(',
+ ')',
+ '[',
+ ']',
+ ];
+
+ $cleanSeparator = trim($separator);
+
+ if (in_array($cleanSeparator, $escapeMe, true)) {
+ // I have to escape special character of regular expression that may be used as separator
+ $separator = str_replace($cleanSeparator, '\\'.$cleanSeparator, $separator);
+ }
+
+ return sprintf(self::$patterns['size'], $separator);
+ }
+
+ /**
+ * 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 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 bool|string
+ * @throws InvalidColorHexValueException
+ * @throws IncorrectColorHexLengthException
+ */
+ public static function getValidColorHexValue($color, $throwException = true)
+ {
+ // Not a scalar value?
+ if (!is_scalar($color)) {
+ return false;
+ }
+
+ $color = Miscellaneous::replace($color, '/#/', '');
+ $length = strlen($color);
+
+ // Color hasn't 3 or 6 characters length?
+ if (3 !== $length && 6 !== $length) {
+ if ($throwException) {
+ throw new IncorrectColorHexLengthException($color);
+ }
+
+ return false;
+ }
+
+ // Make the color 6 characters length, if has 3
+ if (3 === $length) {
+ $color = Miscellaneous::replace($color, '/(.)(.)(.)/', '$1$1$2$2$3$3');
+ }
+
+ $pattern = self::$patterns['color'];
+ $match = (bool) preg_match($pattern, $color);
+
+ // It's not a valid color
+ if (!$match) {
+ if ($throwException) {
+ throw new InvalidColorHexValueException($color);
+ }
+
+ return false;
+ }
+
+ return strtolower($color);
+ }
+
+ /**
+ * 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 value is a binary value
+ *
+ * @param string $value Value to verify
+ * @return bool
+ */
+ public static function isBinaryValue($value)
+ {
+ /*
+ * Not a string?
+ * Nothing to do
+ */
+ if (!is_string($value)) {
+ return false;
+ }
+
+ $pattern = self::$patterns['binaryValue'];
+
+ return (bool) preg_match($pattern, $value);
+ }
+
+ /**
+ * 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(string $fileName): bool
+ {
+ $pattern = self::getFileNamePattern();
+
+ return (bool) preg_match($pattern, $fileName);
+ }
+
+ /**
+ * 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 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 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 information if given value is a size value
+ *
+ * @param string $value Value to verify
+ * @param string $separator (optional) Separator used to split width and height. Default: " x ".
+ * @return bool
+ */
+ public static function isSizeValue($value, $separator = ' x ')
+ {
+ /*
+ * Not a string?
+ * Nothing to do
+ */
+ if (!is_string($value)) {
+ return false;
+ }
+
+ $pattern = self::getSizePattern($separator);
+
+ return (bool) preg_match($pattern, $value);
+ }
+
+ /**
+ * 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 information if given name of bundle is valid
+ *
+ * @param string $bundleName Full name of bundle to verify, e.g. "MyExtraBundle"
+ * @return bool
+ */
+ public static function isValidBundleName($bundleName)
+ {
+ /*
+ * Not a string?
+ * Nothing to do
+ */
+ if (!is_string($bundleName)) {
+ return false;
+ }
+
+ $pattern = self::getBundleNamePattern();
+
+ return (bool) preg_match($pattern, $bundleName);
+ }
+
/**
* Returns information if given e-mail address is valid
*
@@ -81,7 +730,114 @@ class Regex
$pattern = self::getEmailPattern();
- return (bool)preg_match($pattern, $email);
+ return (bool) preg_match($pattern, $email);
+ }
+
+ /**
+ * Returns information if given html attribute is valid
+ *
+ * @param string $htmlAttribute The html attribute to verify
+ * @return bool
+ */
+ public static function isValidHtmlAttribute($htmlAttribute)
+ {
+ /*
+ * Not a string?
+ * Nothing to do
+ */
+ if (!is_string($htmlAttribute)) {
+ return false;
+ }
+
+ $pattern = self::getHtmlAttributePattern();
+
+ return (bool) preg_match($pattern, $htmlAttribute);
+ }
+
+ /**
+ * Returns information if given value is valid money-related value
+ *
+ * @param mixed $value Value to verify
+ * @return bool
+ */
+ public static function isValidMoneyValue($value)
+ {
+ /*
+ * Not a scalar value?
+ * Nothing to do
+ */
+ if (!is_scalar($value)) {
+ return false;
+ }
+
+ $pattern = self::getMoneyPattern();
+
+ return (bool) preg_match($pattern, $value);
+ }
+
+ /**
+ * 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('/[\D]/', '', $nip);
+
+ $invalidNips = [
+ '1234567890',
+ '0000000000',
+ ];
+
+ if (!preg_match('/^[\d]{10}$/', $nip) || in_array($nip, $invalidNips, true)) {
+ 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 === (int) $nip[9];
+ }
+
+ /**
+ * Returns information if given phone number is valid
+ *
+ * @param string $phoneNumber The phone number to validate / verify
+ * @return bool
+ */
+ public static function isValidPhoneNumber($phoneNumber)
+ {
+ /*
+ * Not a string?
+ * Nothing to do
+ */
+ if (!is_string($phoneNumber)) {
+ return false;
+ }
+
+ $pattern = self::getPhoneNumberPattern();
+
+ return (bool) preg_match($pattern, trim($phoneNumber));
}
/**
@@ -141,7 +897,7 @@ class Regex
* Tax ID is valid
*/
- return $sum % 11 === (int)$taxId[9];
+ return $sum % 11 === (int) $taxId[9];
}
/**
@@ -164,123 +920,20 @@ class Regex
$pattern = self::getUrlPattern($requireProtocol);
- return (bool)preg_match($pattern, $url);
+ return (bool) preg_match($pattern, $url);
}
/**
- * Returns information if given phone number is valid
+ * Returns information if given path is a Windows-based path, e.g. "C:\path\to\file.jpg"
*
- * @param string $phoneNumber The phone number to validate / verify
+ * @param string $path The path to verify
* @return bool
*/
- public static function isValidPhoneNumber($phoneNumber)
+ public static function isWindowsBasedPath($path)
{
- /*
- * Not a string?
- * Nothing to do
- */
- if (!is_string($phoneNumber)) {
- return false;
- }
+ $pattern = self::getWindowsBasedPathPattern();
- $pattern = self::getPhoneNumberPattern();
-
- return (bool)preg_match($pattern, trim($phoneNumber));
- }
-
- /**
- * Returns array values that match given pattern (or values that keys match the pattern)
- *
- * @param string $pattern Pattern to match
- * @param array $array The array (scalar values only)
- * @param bool $itsKeyPattern (optional) If is set to true, keys will be checked if they match pattern.
- * Otherwise - values will be checked (default behaviour).
- * @return array
- */
- public static function getArrayValuesByPattern($pattern, array $array, $itsKeyPattern = false)
- {
- /*
- * No elements?
- * Nothing to do
- */
- if (empty($array)) {
- return [];
- }
-
- if ($itsKeyPattern) {
- $effect = [];
-
- foreach ($array as $key => $value) {
- if ((bool)preg_match($pattern, $key)) {
- $effect[$key] = $value;
- }
- }
-
- return $effect;
- }
-
- return preg_grep($pattern, $array);
- }
-
- /**
- * 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 2-dimensional array that should be filtered
- * @param string $arrayColumnKey Column name
- * @param string $filterExpression Simple filter expression (e.g. "== 2" or "!= \'home\'") or regular
- * expression (e.g. "/\d+/" or "/[a-z]+[,;]{2,}/")
- * @param bool $itsRegularExpression (optional) If is set to true, means that filter expression is a regular
- * expression. Otherwise - not (default behaviour).
- * @return array
- */
- public static function arrayFilter($array, $arrayColumnKey, $filterExpression, $itsRegularExpression = false)
- {
- /*
- * No elements?
- * Nothing to do
- */
- if (empty($array)) {
- return [];
- }
-
- $effect = $array;
-
- foreach ($effect as $key => &$item) {
- if (!isset($item[$arrayColumnKey])) {
- continue;
- }
-
- $value = $item[$arrayColumnKey];
-
- if ($itsRegularExpression) {
- $matchesCount = preg_match($filterExpression, $value);
- $remove = 0 === $matchesCount;
- } else {
- if (is_string($value)) {
- $value = sprintf('\'%s\'', $value);
- } elseif (is_bool($value)) {
- if (true === $value) {
- $value = 'true';
- } else {
- $value = 'false';
- }
- }
-
- eval(sprintf('$isEqual = %s%s;', $value, $filterExpression));
-
- /* @var bool $isEqual */
- $remove = !$isEqual;
- }
-
- if ($remove) {
- unset($effect[$key]);
- }
- }
-
- return $effect;
+ return (bool) preg_match($pattern, $path);
}
/**
@@ -311,12 +964,13 @@ class Regex
}
foreach ($patterns as $pattern) {
- $matched = (bool)preg_match_all($pattern, $subject);
+ $matched = (bool) preg_match_all($pattern, $subject);
if ($mustAllMatch) {
$effect = $effect && $matched;
} elseif ($matched) {
$effect = $matched;
+
break;
}
}
@@ -324,180 +978,6 @@ class Regex
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
*
@@ -509,33 +989,17 @@ class Regex
{
if (!empty($string) && !empty($beginning)) {
if (1 === strlen($beginning) && !self::isLetterOrDigit($beginning)) {
- $beginning = '\\' . $beginning;
+ $beginning = '\\'.$beginning;
}
$pattern = sprintf('|^%s|', $beginning);
- return (bool)preg_match($pattern, $string);
+ 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
*
@@ -552,466 +1016,4 @@ class Regex
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('/[\D]/', '', $nip);
-
- $invalidNips = [
- '1234567890',
- '0000000000',
- ];
-
- if (!preg_match('/^[\d]{10}$/', $nip) || in_array($nip, $invalidNips, true)) {
- 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 === (int)$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)
- {
- /*
- * Not a scalar value?
- * Nothing to do
- */
- if (!is_scalar($value)) {
- return false;
- }
-
- $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.
- * @throws IncorrectColorHexLengthException
- * @throws InvalidColorHexValueException
- * @return string|bool
- */
- public static function getValidColorHexValue($color, $throwException = true)
- {
- /*
- * Not a scalar value?
- * Nothing to do
- */
- if (!is_scalar($color)) {
- return false;
- }
-
- $color = Miscellaneous::replace($color, '/#/', '');
- $length = strlen($color);
-
- /*
- * Color is not 3 or 6 characters long?
- * Nothing to do
- */
- if (3 !== $length && 6 !== $length) {
- if ($throwException) {
- throw new IncorrectColorHexLengthException($color);
- }
-
- return false;
- }
-
- /*
- * Color is 3 characters long?
- * Let's make it 6 characters long
- */
- if (3 === $length) {
- $color = Miscellaneous::replace($color, '/(.)(.)(.)/', '$1$1$2$2$3$3');
- }
-
- $pattern = self::$patterns['color'];
- $match = (bool)preg_match($pattern, $color);
-
- /*
- * It's valid color
- * Nothing to do more
- */
- if ($match) {
- return strtolower($color);
- }
-
- if ($throwException) {
- throw new InvalidColorHexValueException($color);
- }
-
- return false;
- }
-
- /**
- * Returns information if given name of bundle is valid
- *
- * @param string $bundleName Full name of bundle to verify, e.g. "MyExtraBundle"
- * @return bool
- */
- public static function isValidBundleName($bundleName)
- {
- /*
- * Not a string?
- * Nothing to do
- */
- if (!is_string($bundleName)) {
- return false;
- }
-
- $pattern = self::getBundleNamePattern();
-
- return (bool)preg_match($pattern, $bundleName);
- }
-
- /**
- * Returns pattern used to validate / verify name of bundle
- *
- * @return string
- */
- public static function getBundleNamePattern()
- {
- return self::$patterns['bundleName'];
- }
-
- /**
- * Returns pattern used to validate / verify html attribute
- *
- * @return string
- */
- public static function getHtmlAttributePattern()
- {
- return self::$patterns['htmlAttribute'];
- }
-
- /**
- * Returns information if given html attribute is valid
- *
- * @param string $htmlAttribute The html attribute to verify
- * @return bool
- */
- public static function isValidHtmlAttribute($htmlAttribute)
- {
- /*
- * Not a string?
- * Nothing to do
- */
- if (!is_string($htmlAttribute)) {
- return false;
- }
-
- $pattern = self::getHtmlAttributePattern();
-
- return (bool)preg_match($pattern, $htmlAttribute);
- }
-
- /**
- * Returns information if given html attributes are valid
- *
- * @param string $htmlAttributes The html attributes to verify
- * @return bool
- */
- public static function areValidHtmlAttributes($htmlAttributes)
- {
- /*
- * Not a string?
- * Nothing to do
- */
- if (!is_string($htmlAttributes)) {
- return false;
- }
-
- $pattern = self::getHtmlAttributePattern();
-
- return (bool)preg_match_all($pattern, $htmlAttributes);
- }
-
- /**
- * Returns information if given value is a binary value
- *
- * @param string $value Value to verify
- * @return bool
- */
- public static function isBinaryValue($value)
- {
- /*
- * Not a string?
- * Nothing to do
- */
- if (!is_string($value)) {
- return false;
- }
-
- $pattern = self::$patterns['binaryValue'];
-
- return (bool)preg_match($pattern, $value);
- }
-
- /**
- * Returns pattern used to validate / verify size
- *
- * @param string $separator (optional) Separator used to split width and height. Default: " x ".
- * @return string
- */
- public static function getSizePattern($separator = ' x ')
- {
- $escapeMe = [
- '/',
- '|',
- '.',
- '(',
- ')',
- '[',
- ']',
- ];
-
- $cleanSeparator = trim($separator);
-
- if (in_array($cleanSeparator, $escapeMe, true)) {
- // I have to escape special character of regular expression that may be used as separator
- $separator = str_replace($cleanSeparator, '\\' . $cleanSeparator, $separator);
- }
-
- return sprintf(self::$patterns['size'], $separator);
- }
-
- /**
- * Returns information if given value is a size value
- *
- * @param string $value Value to verify
- * @param string $separator (optional) Separator used to split width and height. Default: " x ".
- * @return bool
- */
- public static function isSizeValue($value, $separator = ' x ')
- {
- /*
- * Not a string?
- * Nothing to do
- */
- if (!is_string($value)) {
- return false;
- }
-
- $pattern = self::getSizePattern($separator);
-
- return (bool)preg_match($pattern, $value);
- }
-
- /**
- * Returns slug for given value
- *
- * @param string $value Value that should be transformed to slug
- * @return string|bool
- */
- public static function createSlug($value)
- {
- /*
- * Not a scalar value?
- * Nothing to do
- */
- if (!is_scalar($value)) {
- return false;
- }
-
- /*
- * It's an empty string?
- * Nothing to do
- */
- if ('' === $value) {
- return '';
- }
-
- $id = 'Latin-ASCII; NFD; [:Nonspacing Mark:] Remove; NFC; [:Punctuation:] Remove; Lower();';
- $transliterator = \Transliterator::create($id);
-
- $cleanValue = trim($value);
- $result = $transliterator->transliterate($cleanValue);
-
- return preg_replace('/[-\s]+/', '-', $result);
- }
}
diff --git a/src/Utilities/Repository.php b/src/Utilities/Repository.php
index 32dc95c..323d557 100644
--- a/src/Utilities/Repository.php
+++ b/src/Utilities/Repository.php
@@ -24,7 +24,87 @@ class Repository
*
* @var string
*/
- const POSITION_KEY = 'position';
+ public const POSITION_KEY = 'position';
+
+ /**
+ * Returns query builder for given entity's repository.
+ * The entity should contain given property, e.g. "name".
+ *
+ * @param EntityRepository $repository Repository of the entity
+ * @param string $property (optional) Name of property used by the ORDER BY clause
+ * @param string $direction (optional) Direction used by the ORDER BY clause ("ASC" or "DESC")
+ * @return QueryBuilder
+ */
+ public static function getEntityOrderedQueryBuilder(
+ EntityRepository $repository,
+ $property = 'name',
+ $direction = 'ASC'
+ ) {
+ $alias = 'qb';
+ $queryBuilder = $repository->createQueryBuilder($alias);
+
+ if (empty($property)) {
+ return $queryBuilder;
+ }
+
+ return $queryBuilder->orderBy(sprintf('%s.%s', $alias, $property), $direction);
+ }
+
+ /**
+ * Returns extreme position (max or min) of given items
+ *
+ * @param array $items Objects who have "getPosition()" and "setPosition()" methods or arrays
+ * @param bool $max (optional) If is set to true, maximum value is returned. Otherwise - minimum.
+ * @return int
+ */
+ public static function getExtremePosition(array $items, $max = true)
+ {
+ /*
+ * No items?
+ * Nothing to do
+ */
+ if (empty($items)) {
+ return null;
+ }
+
+ $extreme = null;
+
+ foreach ($items as $item) {
+ // Not sortable?
+ if (!self::isSortable($item)) {
+ continue;
+ }
+
+ $position = null;
+
+ // Let's grab the position
+ if (is_object($item)) {
+ $position = $item->getPosition();
+ } elseif (array_key_exists(static::POSITION_KEY, $item)) {
+ $position = $item[static::POSITION_KEY];
+ }
+
+ // Maximum value is expected?
+ if ($max) {
+ // Position was found and it's larger than previously found position (the extreme position)?
+ if (null === $extreme || (null !== $position && $position > $extreme)) {
+ $extreme = $position;
+ }
+
+ continue;
+ }
+
+ /*
+ * Minimum value is expected here.
+ * Position was found and it's smaller than previously found position (the extreme position)?
+ */
+ if (null === $extreme || (null !== $position && $position < $extreme)) {
+ $extreme = $position;
+ }
+ }
+
+ return $extreme;
+ }
/**
* Replenishes positions of given items
@@ -57,24 +137,17 @@ class Repository
}
foreach ($items as &$item) {
- /*
- * The item is not sortable?
- */
+ // Not sortable?
if (!self::isSortable($item)) {
continue;
}
- /*
- * Position has been set?
- * Nothing to do
- */
+ // Sorted already (position has been set)?
if (self::isSorted($item)) {
continue;
}
- /*
- * Calculate position
- */
+ // Calculate position
if ($asLast) {
++$position;
} else {
@@ -87,6 +160,7 @@ class Repository
*/
if (is_object($item)) {
$item->setPosition($position);
+
continue;
}
@@ -98,94 +172,6 @@ class Repository
}
}
- /**
- * Returns extreme position (max or min) of given items
- *
- * @param array $items Objects who have "getPosition()" and "setPosition()" methods or arrays
- * @param bool $max (optional) If is set to true, maximum value is returned. Otherwise - minimum.
- * @return int
- */
- public static function getExtremePosition(array $items, $max = true)
- {
- /*
- * No items?
- * Nothing to do
- */
- if (empty($items)) {
- return null;
- }
-
- $extreme = null;
-
- foreach ($items as $item) {
- /*
- * The item is not sortable?
- */
- if (!self::isSortable($item)) {
- continue;
- }
-
- $position = null;
-
- /*
- * Let's grab the position
- */
- if (is_object($item)) {
- $position = $item->getPosition();
- } elseif (array_key_exists(static::POSITION_KEY, $item)) {
- $position = $item[static::POSITION_KEY];
- }
-
- /*
- * Maximum value is expected?
- */
- if ($max) {
- /*
- * Position was found and it's larger than previously found position (the extreme position)?
- */
- if (null === $extreme || (null !== $position && $position > $extreme)) {
- $extreme = $position;
- }
-
- continue;
- }
-
- /*
- * Minimum value is expected here.
- * Position was found and it's smaller than previously found position (the extreme position)?
- */
- if (null === $extreme || (null !== $position && $position < $extreme)) {
- $extreme = $position;
- }
- }
-
- return $extreme;
- }
-
- /**
- * Returns query builder for given entity's repository.
- * The entity should contain given property, e.g. "name".
- *
- * @param EntityRepository $repository Repository of the entity
- * @param string $property (optional) Name of property used by the ORDER BY clause
- * @param string $direction (optional) Direction used by the ORDER BY clause ("ASC" or "DESC")
- * @return QueryBuilder
- */
- public static function getEntityOrderedQueryBuilder(
- EntityRepository $repository,
- $property = 'name',
- $direction = 'ASC'
- ) {
- $alias = 'qb';
- $queryBuilder = $repository->createQueryBuilder($alias);
-
- if (empty($property)) {
- return $queryBuilder;
- }
-
- return $queryBuilder->orderBy(sprintf('%s.%s', $alias, $property), $direction);
- }
-
/**
* Returns information if given item is sortable
*
@@ -218,18 +204,6 @@ class Repository
*/
private static function isSorted($item)
{
- /*
- * Given item is not sortable?
- */
- if (!self::isSortable($item)) {
- return false;
- }
-
- /*
- * It's an object or it's an array
- * and position has been set?
- */
-
return
(is_object($item) && null !== $item->getPosition())
||
diff --git a/src/Utilities/Uri.php b/src/Utilities/Uri.php
index ebc1142..d740f0b 100644
--- a/src/Utilities/Uri.php
+++ b/src/Utilities/Uri.php
@@ -9,13 +9,52 @@
namespace Meritoo\Common\Utilities;
/**
- * Useful uri methods (only static functions)
+ * Useful methods related to uri
*
* @author Meritoo
* @copyright Meritoo
*/
class Uri
{
+ /**
+ * Adds protocol to given url, if the url does not contain given protocol.
+ * Returns the new url.
+ *
+ * @param string $url Url string
+ * @param string $protocol (optional) Protocol string
+ * @return string
+ */
+ public static function addProtocolToUrl($url, $protocol = 'http')
+ {
+ $pattern = sprintf('/^%s.*/', $protocol);
+
+ if ((bool) preg_match($pattern, $url)) {
+ return $url;
+ }
+
+ return sprintf('%s://%s', $protocol, $url);
+ }
+
+ public static function buildUrl(string $rootUrl, string ...$urlParts): string
+ {
+ $rootUrl = Regex::clearEndingSlash($rootUrl);
+
+ if (empty($urlParts) || Arrays::containsEmptyStringsOnly($urlParts)) {
+ return $rootUrl;
+ }
+
+ array_walk($urlParts, static function (&$part) {
+ $part = Regex::clearBeginningSlash($part);
+ $part = Regex::clearEndingSlash($part);
+ });
+
+ return sprintf(
+ '%s/%s',
+ $rootUrl,
+ implode('/', $urlParts)
+ );
+ }
+
/**
* Returns full uri string
*
@@ -42,7 +81,75 @@ class Uri
return $requestedUrl;
}
- return self::getServerNameOrIp(true) . $requestedUrl;
+ return self::getServerNameOrIp(true).$requestedUrl;
+ }
+
+ /**
+ * Returns protocol name
+ *
+ * @return string
+ */
+ public static function getProtocolName()
+ {
+ $matches = [];
+ $protocolData = Miscellaneous::getSafelyGlobalVariable(INPUT_SERVER, 'SERVER_PROTOCOL'); // e.g. HTTP/1.1
+ $matchCount = preg_match('|(.+)\/(.+)|', $protocolData, $matches);
+
+ /*
+ * $matches[1] - protocol name, e.g. HTTP
+ * $matches[2] - protocol version, e.g. 1.1
+ */
+
+ // Oops, cannot match protocol
+ if (0 === $matchCount) {
+ return '';
+ }
+
+ return strtolower($matches[1]);
+ }
+
+ /**
+ * Returns http referer uri
+ *
+ * @return string
+ */
+ public static function getRefererUri()
+ {
+ return Miscellaneous::getSafelyGlobalVariable(INPUT_SERVER, 'HTTP_REFERER');
+ }
+
+ /**
+ * Returns url to resource secured by given htpasswd login and password
+ *
+ * @param string $url A path / url to some resource, e.g. page, image, css file
+ * @param string $user (optional) User name used to log in
+ * @param string $password (optional) User password used to log in
+ * @return string
+ */
+ public static function getSecuredUrl($url, $user = '', $password = '')
+ {
+ /*
+ * Url is not provided?
+ * Nothing to do
+ */
+ if (empty($url)) {
+ return '';
+ }
+
+ $protocol = self::getProtocolName();
+ $host = self::getServerNameOrIp();
+
+ if (!Regex::startsWith($url, '/')) {
+ $url = sprintf('/%s', $url);
+ }
+
+ $url = $host.$url;
+
+ if (!empty($user) && !empty($password)) {
+ $url = sprintf('%s:%s@%s', $user, $password, $url);
+ }
+
+ return sprintf('%s://%s', $protocol, $url);
}
/**
@@ -74,42 +181,6 @@ class Uri
return $host;
}
- /**
- * Returns protocol name
- *
- * @return string
- */
- public static function getProtocolName()
- {
- $matches = [];
- $protocolData = Miscellaneous::getSafelyGlobalVariable(INPUT_SERVER, 'SERVER_PROTOCOL'); // e.g. HTTP/1.1
- $matchCount = preg_match('|(.+)\/(.+)|', $protocolData, $matches);
-
- /*
- * $matches[1] - protocol name, e.g. HTTP
- * $matches[2] - protocol version, e.g. 1.1
- */
-
- /*
- * Oops, cannot match protocol
- */
- if (0 === $matchCount) {
- return '';
- }
-
- return strtolower($matches[1]);
- }
-
- /**
- * Returns http referer uri
- *
- * @return string
- */
- public static function getRefererUri()
- {
- return Miscellaneous::getSafelyGlobalVariable(INPUT_SERVER, 'HTTP_REFERER');
- }
-
/**
* Returns user's IP address
*
@@ -121,35 +192,26 @@ class Uri
}
/**
- * Returns name and version of user's web browser
+ * Returns name of user's operating system
*
- * @param bool $withVersion (optional) If is set to true, version of the browser is returned too. Otherwise -
- * name only.
* @return string
*/
- public static function getUserWebBrowserName($withVersion = false)
+ public static function getUserOperatingSystemName()
{
$info = self::getUserWebBrowserInfo();
- $knownBrowsers = [
- 'Firefox/([\d\.]+)$' => 'Mozilla Firefox',
- 'OPR/([\d\.]+)$' => 'Opera',
- 'Chrome/([\d\.]+)$' => 'Google Chrome',
- 'Safari/([\d\.]+)$' => 'Apple Safari',
+ $knownSystems = [
+ 'Linux' => 'Linux',
+ 'Win' => 'Windows',
+ 'Mac' => 'Mac OS',
];
- foreach ($knownBrowsers as $pattern => $browserName) {
+ foreach ($knownSystems as $pattern => $systemName) {
$matches = [];
$matchCount = preg_match(sprintf('|%s|', $pattern), $info, $matches);
if ($matchCount > 0) {
- if ($withVersion) {
- $version = $matches[1];
-
- return sprintf('%s %s', $browserName, $version);
- }
-
- return $browserName;
+ return $systemName;
}
}
@@ -183,48 +245,41 @@ class Uri
}
/**
- * Returns name of user's operating system
+ * Returns name and version of user's web browser
*
+ * @param bool $withVersion (optional) If is set to true, version of the browser is returned too. Otherwise -
+ * name only.
* @return string
*/
- public static function getUserOperatingSystemName()
+ public static function getUserWebBrowserName($withVersion = false)
{
$info = self::getUserWebBrowserInfo();
- $knownSystems = [
- 'Linux' => 'Linux',
- 'Win' => 'Windows',
- 'Mac' => 'Mac OS',
+ $knownBrowsers = [
+ 'Firefox/([\d\.]+)$' => 'Mozilla Firefox',
+ 'OPR/([\d\.]+)$' => 'Opera',
+ 'Chrome/([\d\.]+)$' => 'Google Chrome',
+ 'Safari/([\d\.]+)$' => 'Apple Safari',
];
- foreach ($knownSystems as $pattern => $systemName) {
+ foreach ($knownBrowsers as $pattern => $browserName) {
$matches = [];
$matchCount = preg_match(sprintf('|%s|', $pattern), $info, $matches);
if ($matchCount > 0) {
- return $systemName;
+ if ($withVersion) {
+ $version = $matches[1];
+
+ return sprintf('%s %s', $browserName, $version);
+ }
+
+ return $browserName;
}
}
return '';
}
- /**
- * Returns information if running server is localhost
- *
- * @return bool
- */
- public static function isServerLocalhost()
- {
- $serverNameOrIp = strtolower(self::getServerNameOrIp());
-
- return in_array($serverNameOrIp, [
- 'localhost',
- '127.0.0.1',
- '127.0.1.1',
- ]);
- }
-
/**
* Returns information if given url is external, from another server / domain
*
@@ -244,9 +299,7 @@ class Uri
$currentUrl = self::getServerNameOrIp(true);
$url = self::replenishProtocol($url);
- /*
- * Let's prepare pattern of current url
- */
+ // Let's prepare pattern of current url
$search = [
':',
'/',
@@ -264,6 +317,22 @@ class Uri
return !Regex::contains($url, $currentUrlPattern);
}
+ /**
+ * Returns information if running server is localhost
+ *
+ * @return bool
+ */
+ public static function isServerLocalhost()
+ {
+ $serverNameOrIp = strtolower(self::getServerNameOrIp());
+
+ return in_array($serverNameOrIp, [
+ 'localhost',
+ '127.0.0.1',
+ '127.0.1.1',
+ ]);
+ }
+
/**
* Replenishes protocol in the given url
*
@@ -274,9 +343,7 @@ class Uri
*/
public static function replenishProtocol($url, $protocol = '')
{
- /*
- * Let's trim the url
- */
+ // Let's trim the url
if (is_string($url)) {
$url = trim($url);
}
@@ -297,66 +364,11 @@ class Uri
return $url;
}
- /*
- * Protocol is not provided?
- */
+ // Protocol is not provided?
if (empty($protocol)) {
$protocol = self::getProtocolName();
}
return sprintf('%s://%s', $protocol, $url);
}
-
- /**
- * Returns url to resource secured by given htpasswd login and password
- *
- * @param string $url A path / url to some resource, e.g. page, image, css file
- * @param string $user (optional) User name used to log in
- * @param string $password (optional) User password used to log in
- * @return string
- */
- public static function getSecuredUrl($url, $user = '', $password = '')
- {
- /*
- * Url is not provided?
- * Nothing to do
- */
- if (empty($url)) {
- return '';
- }
-
- $protocol = self::getProtocolName();
- $host = self::getServerNameOrIp();
-
- if (!Regex::startsWith($url, '/')) {
- $url = sprintf('/%s', $url);
- }
-
- $url = $host . $url;
-
- if (!empty($user) && !empty($password)) {
- $url = sprintf('%s:%s@%s', $user, $password, $url);
- }
-
- return sprintf('%s://%s', $protocol, $url);
- }
-
- /**
- * Adds protocol to given url, if the url does not contain given protocol.
- * Returns the new url.
- *
- * @param string $url Url string
- * @param string $protocol (optional) Protocol string
- * @return string
- */
- public static function addProtocolToUrl($url, $protocol = 'http')
- {
- $pattern = sprintf('/^%s.*/', $protocol);
-
- if ((bool)preg_match($pattern, $url)) {
- return $url;
- }
-
- return sprintf('%s://%s', $protocol, $url);
- }
}
diff --git a/src/ValueObject/Address.php b/src/ValueObject/Address.php
index 337f7ca..708c64b 100644
--- a/src/ValueObject/Address.php
+++ b/src/ValueObject/Address.php
@@ -88,13 +88,33 @@ class Address
}
/**
- * Returns street
+ * Returns number of building
*
* @return string
*/
- public function getStreet()
+ public function getBuildingNumber()
{
- return $this->street;
+ return $this->buildingNumber;
+ }
+
+ /**
+ * Returns city, location
+ *
+ * @return string
+ */
+ public function getCity()
+ {
+ return $this->city;
+ }
+
+ /**
+ * Returns number of flat
+ *
+ * @return string
+ */
+ public function getFlatNumber()
+ {
+ return $this->flatNumber;
}
/**
@@ -118,23 +138,13 @@ class Address
}
/**
- * Returns number of building
+ * Returns street
*
* @return string
*/
- public function getBuildingNumber()
+ public function getStreet()
{
- return $this->buildingNumber;
- }
-
- /**
- * Returns number of flat
- *
- * @return string
- */
- public function getFlatNumber()
- {
- return $this->flatNumber;
+ return $this->street;
}
/**
@@ -146,14 +156,4 @@ class Address
{
return $this->zipCode;
}
-
- /**
- * Returns city, location
- *
- * @return string
- */
- public function getCity()
- {
- return $this->city;
- }
}
diff --git a/src/ValueObject/BankAccount.php b/src/ValueObject/BankAccount.php
index 0b2c83f..db80cce 100644
--- a/src/ValueObject/BankAccount.php
+++ b/src/ValueObject/BankAccount.php
@@ -59,16 +59,6 @@ class BankAccount
return Arrays::getNonEmptyValuesAsString($values);
}
- /**
- * Returns name of bank
- *
- * @return string
- */
- public function getBankName()
- {
- return $this->bankName;
- }
-
/**
* Returns number of bank's account
*
@@ -78,4 +68,14 @@ class BankAccount
{
return $this->accountNumber;
}
+
+ /**
+ * Returns name of bank
+ *
+ * @return string
+ */
+ public function getBankName()
+ {
+ return $this->bankName;
+ }
}
diff --git a/src/ValueObject/Company.php b/src/ValueObject/Company.php
index 05facea..ebe1aac 100644
--- a/src/ValueObject/Company.php
+++ b/src/ValueObject/Company.php
@@ -44,7 +44,7 @@ class Company
*
* @param string $name Name of company
* @param Address $address Address of company
- * @param BankAccount|null $bankAccount (optional) Bank account of company
+ * @param null|BankAccount $bankAccount (optional) Bank account of company
*/
public function __construct($name, Address $address, BankAccount $bankAccount = null)
{
@@ -69,16 +69,6 @@ class Company
return Arrays::getNonEmptyValuesAsString($values);
}
- /**
- * Returns name of company
- *
- * @return string
- */
- public function getName()
- {
- return $this->name;
- }
-
/**
* Returns address of company
*
@@ -92,10 +82,20 @@ class Company
/**
* Returns bank account of company
*
- * @return BankAccount|null
+ * @return null|BankAccount
*/
public function getBankAccount()
{
return $this->bankAccount;
}
+
+ /**
+ * Returns name of company
+ *
+ * @return string
+ */
+ public function getName()
+ {
+ return $this->name;
+ }
}
diff --git a/src/ValueObject/Size.php b/src/ValueObject/Size.php
index 1336ca1..b6f4cd0 100644
--- a/src/ValueObject/Size.php
+++ b/src/ValueObject/Size.php
@@ -62,8 +62,8 @@ class Size
*/
private function __construct($width = null, $height = null, $unit = 'px')
{
- $width = (int)$width;
- $height = (int)$height;
+ $width = (int) $width;
+ $height = (int) $height;
if ($width < 0 || $height < 0) {
throw new InvalidSizeDimensionsException($width, $height);
@@ -88,14 +88,84 @@ class Size
}
/**
- * Sets separator used when converting to string
+ * Creates new instance from given array
*
- * @param string $separator The separator
+ * The array should contain 2 elements: width and height.
+ * Examples: ['800', '600'], [800, 600].
+ *
+ * @param array $array The size represented as array
+ * @param string $unit (optional) Unit used when width or height should be returned with unit. Default: "px".
+ * @return null|Size
+ */
+ public static function fromArray(array $array, $unit = 'px')
+ {
+ // Requirements for given array:
+ // - indexes "0" and "1"
+ // - should contains exactly 2 elements
+ if (
+ array_key_exists(0, $array)
+ && array_key_exists(1, $array)
+ && 2 === count($array)
+ ) {
+ [$width, $height] = $array;
+
+ return new self($width, $height, $unit);
+ }
+
+ return null;
+ }
+
+ /**
+ * Creates new instance from given string
+ *
+ * @param string $size The size represented as string (width and height separated by given separator)
+ * @param string $unit (optional) Unit used when width or height should be returned with unit. Default: "px".
+ * @param string $separator (optional) Separator used to split width and height. Default: " x ".
+ * @return null|Size
+ */
+ public static function fromString($size, $unit = 'px', $separator = ' x ')
+ {
+ if (is_string($size)) {
+ $matches = [];
+ $pattern = Regex::getSizePattern($separator);
+
+ if ((bool) preg_match($pattern, $size, $matches)) {
+ $width = (int) $matches[1];
+ $height = (int) $matches[2];
+ $sizeObject = new self($width, $height, $unit);
+
+ return $sizeObject->setSeparator($separator);
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns the height
+ *
+ * @param bool $withUnit (optional) If is set to true, height is returned with unit ("px"). Otherwise - without
+ * (default behaviour).
+ * @return int|string
+ */
+ public function getHeight($withUnit = false)
+ {
+ if ($withUnit) {
+ return sprintf('%d %s', $this->height, $this->unit);
+ }
+
+ return $this->height;
+ }
+
+ /**
+ * Sets the height
+ *
+ * @param int $height The height
* @return Size
*/
- public function setSeparator($separator)
+ public function setHeight($height)
{
- $this->separator = $separator;
+ $this->height = (int) $height;
return $this;
}
@@ -124,55 +194,24 @@ class Size
*/
public function setWidth($width)
{
- $this->width = (int)$width;
+ $this->width = (int) $width;
return $this;
}
/**
- * Returns the height
+ * Sets separator used when converting to string
*
- * @param bool $withUnit (optional) If is set to true, height is returned with unit ("px"). Otherwise - without
- * (default behaviour).
- * @return int|string
- */
- public function getHeight($withUnit = false)
- {
- if ($withUnit) {
- return sprintf('%d %s', $this->height, $this->unit);
- }
-
- return $this->height;
- }
-
- /**
- * Sets the height
- *
- * @param int $height The height
+ * @param string $separator The separator
* @return Size
*/
- public function setHeight($height)
+ public function setSeparator($separator)
{
- $this->height = (int)$height;
+ $this->separator = $separator;
return $this;
}
- /**
- * Returns string representation of instance of this class, e.g. '200 x 100' or '200x100'
- *
- * @param bool $withUnit (optional) If is set to true, width and height are returned with unit ("px"). Otherwise
- * - without (default behaviour).
- * @return string
- */
- public function toString($withUnit = false)
- {
- $width = $this->getWidth($withUnit);
- $height = $this->getHeight($withUnit);
-
- return sprintf('%s%s%s', $width, $this->separator, $height);
- }
-
/**
* Returns instance of this class as an array.
* Values of the array are width and height, eg. [800, 600] or ['800px', '600px'].
@@ -190,56 +229,17 @@ class Size
}
/**
- * Creates new instance from given string
+ * Returns string representation of instance of this class, e.g. '200 x 100' or '200x100'
*
- * @param string $size The size represented as string (width and height separated by given separator)
- * @param string $unit (optional) Unit used when width or height should be returned with unit. Default: "px".
- * @param string $separator (optional) Separator used to split width and height. Default: " x ".
- * @return Size|null
+ * @param bool $withUnit (optional) If is set to true, width and height are returned with unit ("px"). Otherwise
+ * - without (default behaviour).
+ * @return string
*/
- public static function fromString($size, $unit = 'px', $separator = ' x ')
+ public function toString($withUnit = false)
{
- if (is_string($size)) {
- $matches = [];
- $pattern = Regex::getSizePattern($separator);
+ $width = $this->getWidth($withUnit);
+ $height = $this->getHeight($withUnit);
- if ((bool)preg_match($pattern, $size, $matches)) {
- $width = (int)$matches[1];
- $height = (int)$matches[2];
- $sizeObject = new self($width, $height, $unit);
-
- return $sizeObject->setSeparator($separator);
- }
- }
-
- return null;
- }
-
- /**
- * Creates new instance from given array
- *
- * The array should contain 2 elements: width and height.
- * Examples: ['800', '600'], [800, 600].
- *
- * @param array $array The size represented as array
- * @param string $unit (optional) Unit used when width or height should be returned with unit. Default: "px".
- * @return Size|null
- */
- public static function fromArray(array $array, $unit = 'px')
- {
- // Requirements for given array:
- // - indexes "0" and "1"
- // - should contains exactly 2 elements
- if (
- array_key_exists(0, $array)
- && array_key_exists(1, $array)
- && 2 === count($array)
- ) {
- list($width, $height) = $array;
-
- return new self($width, $height, $unit);
- }
-
- return null;
+ return sprintf('%s%s%s', $width, $this->separator, $height);
}
}
diff --git a/src/ValueObject/Template.php b/src/ValueObject/Template.php
new file mode 100644
index 0000000..98cecf5
--- /dev/null
+++ b/src/ValueObject/Template.php
@@ -0,0 +1,151 @@
+
+ * @copyright Meritoo
+ */
+class Template
+{
+ /**
+ * Tag used at beginning and ending of placeholder
+ *
+ * @var string
+ */
+ private const PLACEHOLDER_TAG = '%';
+
+ /**
+ * Raw string with placeholders (content of the template)
+ *
+ * @var string
+ */
+ private $content;
+
+ /**
+ * Class constructor
+ *
+ * @param string $content Raw string with placeholders (content of the template)
+ * @throws InvalidContentException
+ */
+ public function __construct(string $content)
+ {
+ if (!static::isValid($content)) {
+ throw InvalidContentException::create($content);
+ }
+
+ $this->content = $content;
+ }
+
+ /**
+ * Returns content of the template filled with given values (by replacing placeholders with their proper values)
+ *
+ * @param array $values Pairs of key-value where: key - name of placeholder, value - value of the placeholder
+ * @return string
+ * @throws MissingPlaceholdersInValuesException
+ */
+ public function fill(array $values): string
+ {
+ $placeholders = static::getPlaceholders($this->content);
+ $providedPlaceholders = array_keys($values);
+ $missingPlaceholders = array_diff($placeholders[1], $providedPlaceholders);
+
+ // Oops, there are placeholders without values (iow. provided values are different than placeholders)
+ if (!empty($missingPlaceholders)) {
+ throw MissingPlaceholdersInValuesException::create($this->content, $missingPlaceholders);
+ }
+
+ $result = $this->content;
+
+ foreach ($placeholders[0] as $index => $placeholder) {
+ $placeholderName = $placeholders[1][$index];
+
+ if (isset($values[$placeholderName])) {
+ $value = $values[$placeholderName];
+ $result = str_replace($placeholder, (string) $value, $result);
+ }
+ }
+
+ return $result;
+ }
+
+ /**
+ * Returns regular expression that defines format of placeholder
+ *
+ * Expectations:
+ * - surrounded by the placeholder's tags (at beginning and at the end)
+ * - at least 1 character
+ * - no placeholder's tag inside name of placeholder
+ *
+ * Invalid placeholders:
+ * - test
+ * - test%
+ * - % test%
+ *
+ * Valid placeholders:
+ * - %test%
+ * - %another_test%
+ * - %another-test%
+ * - %anotherTest%
+ * - %another test%
+ *
+ * @return string
+ */
+ private static function getPlaceholderPattern(): string
+ {
+ return sprintf(
+ '/%s([^%s]+)%s/',
+ static::PLACEHOLDER_TAG,
+ static::PLACEHOLDER_TAG,
+ static::PLACEHOLDER_TAG
+ );
+ }
+
+ /**
+ * Returns placeholders of given template
+ *
+ * @param string $content Content of template
+ * @return array
+ */
+ private static function getPlaceholders(string $content): array
+ {
+ $result = [];
+ $matchCount = preg_match_all(static::getPlaceholderPattern(), $content, $result);
+
+ if (false !== $matchCount && 0 < $matchCount) {
+ foreach ($result as $index => $placeholders) {
+ $result[$index] = array_unique($placeholders);
+ }
+ }
+
+ return $result;
+ }
+
+ /**
+ * Returns information if given template is valid
+ *
+ * @param string $content Raw string with placeholders to validate (content of the template)
+ * @return bool
+ */
+ private static function isValid(string $content): bool
+ {
+ if ('' === $content) {
+ return false;
+ }
+
+ return (bool) preg_match_all(static::getPlaceholderPattern(), $content);
+ }
+}
diff --git a/src/ValueObject/Version.php b/src/ValueObject/Version.php
index 55e7cb4..344f95b 100644
--- a/src/ValueObject/Version.php
+++ b/src/ValueObject/Version.php
@@ -54,6 +54,96 @@ class Version
$this->patchPart = $patchPart;
}
+ /**
+ * Returns representation of object as string
+ *
+ * @return string
+ */
+ public function __toString()
+ {
+ return sprintf('%d.%d.%d', $this->getMajorPart(), $this->getMinorPart(), $this->getPatchPart());
+ }
+
+ /**
+ * Returns new instance based on given version as array.
+ * Given version should contain 3 integers, 1 per each part ("major", "minor" and "patch").
+ *
+ * Examples:
+ * [1, 0, 2];
+ * [10, 4, 0];
+ *
+ * @param array $version The version
+ * @return null|Version
+ */
+ public static function fromArray(array $version)
+ {
+ /*
+ * No version provided?
+ * Nothing to do
+ */
+ if (empty($version)) {
+ return null;
+ }
+
+ $count = count($version);
+
+ /*
+ * Incorrect version?
+ * Nothing to do
+ */
+ if (3 !== $count) {
+ return null;
+ }
+
+ $majorPart = (int) $version[0];
+ $minorPart = (int) $version[1];
+ $patchPart = (int) $version[2];
+
+ return new static($majorPart, $minorPart, $patchPart);
+ }
+
+ /**
+ * Returns new instance based on given version as string.
+ * Given version should contain 3 dot-separated integers, 1 per each part ("major", "minor" and "patch").
+ *
+ * Examples:
+ * "1.0.2";
+ * "10.4.0";
+ *
+ * @param string $version The version
+ * @return null|Version
+ */
+ public static function fromString(string $version)
+ {
+ $version = trim($version);
+
+ /*
+ * No version provided?
+ * Nothing to do
+ */
+ if (empty($version)) {
+ return null;
+ }
+
+ $matches = [];
+ $pattern = '/^(\d+)\.(\d+)\.(\d+)$/'; // e.g. "1.0.2"
+ $matched = preg_match($pattern, $version, $matches);
+
+ /*
+ * Incorrect version?
+ * Nothing to do
+ */
+ if (0 === $matched || false === $matched) {
+ return null;
+ }
+
+ $majorPart = (int) $matches[1];
+ $minorPart = (int) $matches[2];
+ $patchPart = (int) $matches[3];
+
+ return new static($majorPart, $minorPart, $patchPart);
+ }
+
/**
* Returns the "major" part.
* Incremented when you make incompatible API changes.
@@ -86,94 +176,4 @@ class Version
{
return $this->patchPart;
}
-
- /**
- * Returns representation of object as string
- *
- * @return string
- */
- public function __toString()
- {
- return sprintf('%d.%d.%d', $this->getMajorPart(), $this->getMinorPart(), $this->getPatchPart());
- }
-
- /**
- * Returns new instance based on given version as string.
- * Given version should contain 3 dot-separated integers, 1 per each part ("major", "minor" and "patch").
- *
- * Examples:
- * "1.0.2";
- * "10.4.0";
- *
- * @param string $version The version
- * @return Version|null
- */
- public static function fromString($version)
- {
- $version = trim($version);
-
- /*
- * No version provided?
- * Nothing to do
- */
- if (empty($version)) {
- return null;
- }
-
- $matches = [];
- $pattern = '/^(\d+)\.(\d+)\.(\d+)$/'; // e.g. "1.0.2"
- $matched = preg_match($pattern, $version, $matches);
-
- /*
- * Incorrect version?
- * Nothing to do
- */
- if (0 === $matched || false === $matched) {
- return null;
- }
-
- $majorPart = (int)$matches[1];
- $minorPart = (int)$matches[2];
- $patchPart = (int)$matches[3];
-
- return new static($majorPart, $minorPart, $patchPart);
- }
-
- /**
- * Returns new instance based on given version as array.
- * Given version should contain 3 integers, 1 per each part ("major", "minor" and "patch").
- *
- * Examples:
- * [1, 0, 2];
- * [10, 4, 0];
- *
- * @param array $version The version
- * @return Version|null
- */
- public static function fromArray(array $version)
- {
- /*
- * No version provided?
- * Nothing to do
- */
- if (empty($version)) {
- return null;
- }
-
- $count = count($version);
-
- /*
- * Incorrect version?
- * Nothing to do
- */
- if (3 !== $count) {
- return null;
- }
-
- $majorPart = (int)$version[0];
- $minorPart = (int)$version[1];
- $patchPart = (int)$version[2];
-
- return new static($majorPart, $minorPart, $patchPart);
- }
}
diff --git a/tests/Collection/BaseCollection/FirstNamesCollection.php b/tests/Collection/BaseCollection/FirstNamesCollection.php
new file mode 100644
index 0000000..1dc7c56
--- /dev/null
+++ b/tests/Collection/BaseCollection/FirstNamesCollection.php
@@ -0,0 +1,42 @@
+
+ * @copyright Meritoo
+ *
+ * @internal
+ * @coversNothing
+ */
+class FirstNamesCollection extends BaseCollection
+{
+ protected function isValidType($element): bool
+ {
+ return $element instanceof User;
+ }
+
+ protected function prepareElements(array $elements): array
+ {
+ $result = [];
+
+ /** @var User $element */
+ foreach ($elements as $element) {
+ $result[] = $element->getFirstName();
+ }
+
+ return $result;
+ }
+}
diff --git a/tests/Collection/BaseCollection/User.php b/tests/Collection/BaseCollection/User.php
new file mode 100644
index 0000000..642ef56
--- /dev/null
+++ b/tests/Collection/BaseCollection/User.php
@@ -0,0 +1,45 @@
+
+ * @copyright Meritoo
+ *
+ * @internal
+ * @coversNothing
+ */
+final class User
+{
+ /** @var string */
+ private $firstName;
+
+ /** @var string */
+ private $lastName;
+
+ public function __construct(string $firstName, string $lastName)
+ {
+ $this->firstName = $firstName;
+ $this->lastName = $lastName;
+ }
+
+ public function getFirstName(): string
+ {
+ return $this->firstName;
+ }
+
+ public function getLastName(): string
+ {
+ return $this->lastName;
+ }
+}
diff --git a/tests/Collection/BaseCollectionTest.php b/tests/Collection/BaseCollectionTest.php
new file mode 100644
index 0000000..77c7170
--- /dev/null
+++ b/tests/Collection/BaseCollectionTest.php
@@ -0,0 +1,806 @@
+
+ * @copyright Meritoo
+ *
+ * @internal
+ * @covers \Meritoo\Common\Collection\BaseCollection
+ */
+class BaseCollectionTest extends BaseTestCase
+{
+ /**
+ * An empty collection
+ *
+ * @var StringCollection
+ */
+ private $emptyCollection;
+
+ /**
+ * Simple collection
+ *
+ * @var StringCollection
+ */
+ private $simpleCollection;
+
+ /**
+ * Elements of simple collection
+ *
+ * @var array
+ */
+ private $simpleElements;
+
+ public function provideElementGetByIndex()
+ {
+ yield [
+ 'An empty collection and empty index',
+ new StringCollection(),
+ '',
+ null,
+ ];
+
+ yield [
+ 'An empty collection and non-empty index',
+ new StringCollection(),
+ 'test',
+ null,
+ ];
+
+ yield [
+ 'Non-empty collection and not existing index',
+ new StringCollection([
+ 'lorem' => 'ipsum',
+ 'dolor' => 'sit',
+ ]),
+ 'test',
+ null,
+ ];
+
+ yield [
+ 'Collection with existing index',
+ new StringCollection([
+ 'lorem' => 'ipsum',
+ 'dolor' => 'sit',
+ ]),
+ 'lorem',
+ 'ipsum',
+ ];
+
+ yield [
+ 'Collection with existing index (collection of arrays)',
+ new FirstNamesCollection([
+ new User('John', 'Scott'),
+ new User('Jane', 'Brown'),
+ ]),
+ 0,
+ 'John',
+ ];
+
+ yield [
+ 'Collection with existing index (collection of objects)',
+ new DateTimeCollection([
+ 'x' => new DateTime(),
+ 'y' => new DateTime('2001-01-01'),
+ 'z' => new DateTime('yesterday'),
+ ]),
+ 'y',
+ new DateTime('2001-01-01'),
+ ];
+
+ yield [
+ 'Collection with first names',
+ new FirstNamesCollection([
+ new User('John', 'Scott'),
+ new User('Jane', 'Brown'),
+ ]),
+ 1,
+ 'Jane',
+ ];
+ }
+
+ /**
+ * Provides element to add to collection
+ *
+ * @return Generator
+ */
+ public function provideElementToAdd()
+ {
+ yield [
+ 'This is test 1',
+ 1,
+ 0,
+ new StringCollection(),
+ ];
+
+ yield [
+ 'This is test 2',
+ 2,
+ 1,
+ new StringCollection([
+ 'I am 1st',
+ ]),
+ ];
+
+ yield [
+ 'This is test 3',
+ 3,
+ 2,
+ new StringCollection([
+ 'I am 1st',
+ 'I am 2nd',
+ ]),
+ ];
+ }
+
+ /**
+ * Provides element with index to add to collection
+ *
+ * @return Generator
+ */
+ public function provideElementToAddWithIndex()
+ {
+ yield [
+ 'This is test 1',
+ 'test1',
+ 1,
+ 'test1',
+ new StringCollection(),
+ ];
+
+ yield [
+ 'This is test 2',
+ 'test2',
+ 2,
+ 'test2',
+ new StringCollection([
+ 'test1' => 'I am 1st',
+ ]),
+ ];
+
+ yield [
+ 'This is test 3',
+ null,
+ 3,
+ 0,
+ new StringCollection([
+ 'test1' => 'I am 1st',
+ 'test2' => 'I am 2nd',
+ ]),
+ ];
+
+ yield [
+ 'This is test 4',
+ '',
+ 4,
+ '',
+ new StringCollection([
+ 'test1' => 'I am 1st',
+ 'test2' => 'I am 2nd',
+ 'I am 3rd',
+ ]),
+ ];
+
+ yield [
+ 'This is test 5',
+ 'test5',
+ 5,
+ 'test5',
+ new StringCollection([
+ 'test1' => 'I am 1st',
+ 'test2' => 'I am 2nd',
+ 2 => 'I am 3rd',
+ 3 => 'I am 4th',
+ ]),
+ ];
+
+ yield [
+ 'This is test 6',
+ 'test2',
+ 4,
+ 'test2',
+ new StringCollection([
+ 'test1' => 'I am 1st',
+ 'test2' => 'I am 2nd',
+ 2 => 'I am 3rd',
+ 3 => 'I am 4th',
+ ]),
+ ];
+ }
+
+ public function provideElementToAddWithInvalidType(): ?Generator
+ {
+ yield [
+ ['test'],
+ 0,
+ new StringCollection(),
+ ];
+
+ yield [
+ 123,
+ 2,
+ new StringCollection([
+ 'I am 1st',
+ 'I am 2nd',
+ ]),
+ ];
+ }
+
+ public function provideElementsToValidateType(): ?Generator
+ {
+ yield [
+ 'An empty array',
+ [],
+ [],
+ ];
+
+ yield [
+ 'Valid elements only',
+ [
+ new User('John', 'Scott'),
+ new User('Jane', 'Brown'),
+ ],
+ [
+ 'John',
+ 'Jane',
+ ],
+ ];
+
+ yield [
+ 'Mixed elements',
+ [
+ 1,
+ 'test',
+ '',
+ new User('John', 'Scott'),
+ [],
+ 234,
+ 'test',
+ new User('Jane', 'Brown'),
+ ],
+ [
+ 'John',
+ 'Jane',
+ ],
+ ];
+ }
+
+ public function provideResultOfLimit(): ?Generator
+ {
+ yield 'Negative value of maximum & negative offset' => [
+ [],
+ -1,
+ -2,
+ ];
+
+ yield 'Negative value of maximum & positive offset' => [
+ [],
+ -1,
+ 2,
+ ];
+
+ yield 'Maximum set to 0 & negative offset' => [
+ [],
+ 0,
+ -2,
+ ];
+
+ yield 'Maximum set to 0 & positive offset' => [
+ [],
+ 0,
+ 2,
+ ];
+
+ yield 'Maximum set to 1 & offset set to 2' => [
+ [
+ 123 => 'dolor',
+ ],
+ 1,
+ 2,
+ ];
+
+ yield 'Maximum set to 2 & offset set to 2' => [
+ [
+ 123 => 'dolor',
+ 345 => 'sit',
+ ],
+ 2,
+ 2,
+ ];
+
+ yield 'Maximum set to 3 & offset set to latest element' => [
+ [
+ 346 => 'adipiscing elit',
+ ],
+ 3,
+ 6,
+ ];
+
+ yield 'Maximum set to 1 & offset greater than size of collection' => [
+ [],
+ 1,
+ 10,
+ ];
+ }
+
+ public function provideResultOfLimitWithDefaultOffset(): ?Generator
+ {
+ yield 'Negative value of maximum' => [
+ [],
+ -1,
+ ];
+
+ yield 'Maximum set to 0' => [
+ [],
+ 0,
+ ];
+
+ yield 'Maximum set to 1' => [
+ [
+ 'lorem',
+ ],
+ 1,
+ ];
+
+ yield 'Maximum set to 3' => [
+ [
+ 'lorem',
+ 'ipsum',
+ 123 => 'dolor',
+ ],
+ 3,
+ ];
+
+ yield 'Maximum greater than size of collection' => [
+ [
+ 'lorem',
+ 'ipsum',
+ 123 => 'dolor',
+ 345 => 'sit',
+ 'a' => 'amet',
+ 'c' => 'consectetur',
+ 346 => 'adipiscing elit',
+ ],
+ 10,
+ ];
+ }
+
+ public function testAddMultiple()
+ {
+ $elements = [
+ 'test1',
+ 'test2',
+ 1234 => 'test3',
+ 5678 => 'test4',
+ ];
+
+ $this->emptyCollection->addMultiple($elements);
+
+ static::assertFalse($this->emptyCollection->isEmpty());
+ static::assertSame(4, $this->emptyCollection->count());
+
+ static::assertSame('test1', $this->emptyCollection[0]);
+ static::assertSame('test2', $this->emptyCollection[1]);
+ static::assertSame('test3', $this->emptyCollection[2]);
+ static::assertSame('test4', $this->emptyCollection[3]);
+ }
+
+ public function testAddMultipleUsingEmptyArray()
+ {
+ $this->emptyCollection->addMultiple([]);
+
+ static::assertSame(0, $this->emptyCollection->count());
+ static::assertTrue($this->emptyCollection->isEmpty());
+ }
+
+ public function testAddMultipleUsingIndexes()
+ {
+ $elements = [
+ 'test1',
+ 'test2',
+ 1234 => 'test3',
+ 5678 => 'test4',
+ ];
+
+ $this->emptyCollection->addMultiple($elements, true);
+
+ static::assertFalse($this->emptyCollection->isEmpty());
+ static::assertSame(4, $this->emptyCollection->count());
+
+ static::assertSame('test1', $this->emptyCollection[0]);
+ static::assertSame('test2', $this->emptyCollection[1]);
+ static::assertSame('test3', $this->emptyCollection[1234]);
+ static::assertSame('test4', $this->emptyCollection[5678]);
+ }
+
+ /**
+ * @param mixed $element The element to add
+ * @param mixed $index Index of element to add
+ * @param int $expectedCount Expected count of elements in collection
+ * @param int $expectedIndex Expected index of added element in collection
+ * @param CollectionInterface $collection The collection
+ *
+ * @dataProvider provideElementToAddWithIndex
+ */
+ public function testAddWithIndex($element, $index, $expectedCount, $expectedIndex, CollectionInterface $collection)
+ {
+ $collection->add($element, $index);
+
+ static::assertTrue($collection->has($element));
+ static::assertSame($expectedCount, $collection->count());
+ static::assertSame($element, $collection[$expectedIndex]);
+ }
+
+ /**
+ * @param mixed $element The element to add
+ * @param int $expectedCount Expected count of elements in collection
+ * @param CollectionInterface $collection The collection
+ *
+ * @dataProvider provideElementToAddWithInvalidType
+ */
+ public function testAddWithInvalidType(
+ $element,
+ int $expectedCount,
+ CollectionInterface $collection
+ ): void {
+ $collection->add($element);
+
+ static::assertFalse($collection->has($element));
+ static::assertSame($expectedCount, $collection->count());
+ }
+
+ /**
+ * @param mixed $element The element to add
+ * @param int $expectedCount Expected count of elements in collection
+ * @param int $expectedIndex Expected index of added element in collection
+ * @param CollectionInterface $collection The collection
+ *
+ * @dataProvider provideElementToAdd
+ */
+ public function testAddWithoutIndex(
+ $element,
+ int $expectedCount,
+ int $expectedIndex,
+ CollectionInterface $collection
+ ) {
+ $collection->add($element);
+
+ static::assertTrue($collection->has($element));
+ static::assertSame($expectedCount, $collection->count());
+ static::assertSame($element, $collection[$expectedIndex]);
+ }
+
+ public function testClear(): void
+ {
+ self::assertCount(7, $this->simpleCollection);
+ $this->simpleCollection->clear();
+ self::assertCount(0, $this->simpleCollection);
+ }
+
+ public function testClearIfIsEmpty(): void
+ {
+ self::assertCount(0, $this->emptyCollection);
+ $this->emptyCollection->clear();
+ self::assertCount(0, $this->emptyCollection);
+ }
+
+ public function testCount()
+ {
+ static::assertSame(0, $this->emptyCollection->count());
+ static::assertSame(7, $this->simpleCollection->count());
+ }
+
+ public function testEmptyCollection()
+ {
+ static::assertSame(0, $this->emptyCollection->count());
+ static::assertCount(0, $this->emptyCollection);
+ static::assertEmpty($this->emptyCollection);
+
+ static::assertTrue($this->emptyCollection->isEmpty());
+ static::assertSame([], $this->emptyCollection->toArray());
+ static::assertEmpty($this->emptyCollection->toArray());
+
+ static::assertNull($this->emptyCollection->getFirst());
+ static::assertNull($this->emptyCollection->getLast());
+ static::assertNull($this->emptyCollection[1]);
+ static::assertNull($this->emptyCollection['abc']);
+ }
+
+ public function testExistsVisibilityAndArguments()
+ {
+ $reflectionClass = new ReflectionClass(BaseCollection::class);
+ $method = $reflectionClass->getMethod('exists');
+
+ static::assertMethodVisibility($method, OopVisibilityType::IS_PRIVATE);
+ static::assertMethodArgumentsCount($method, 1, 1);
+ }
+
+ /**
+ * @param string $description Description of test
+ * @param CollectionInterface $collection Collection to search for element with given index
+ * @param mixed $index Index / key of the element
+ * @param mixed $expected Expected element with given index
+ *
+ * @dataProvider provideElementGetByIndex
+ */
+ public function testGetByIndex($description, CollectionInterface $collection, $index, $expected)
+ {
+ static::assertEquals($expected, $collection->getByIndex($index), $description);
+ }
+
+ /**
+ * @param string $description
+ * @param array $elements
+ * @param array $expected
+ *
+ * @dataProvider provideElementsToValidateType
+ */
+ public function testGetElementsWithValidType(string $description, array $elements, array $expected): void
+ {
+ $collection = new FirstNamesCollection($elements);
+ static::assertSame($expected, $collection->toArray(), $description);
+ }
+
+ public function testGetFirst()
+ {
+ static::assertNull($this->emptyCollection->getFirst());
+ static::assertSame('lorem', $this->simpleCollection->getFirst());
+ }
+
+ public function testGetIterator()
+ {
+ static::assertInstanceOf(ArrayIterator::class, $this->simpleCollection->getIterator());
+ }
+
+ public function testGetLast()
+ {
+ static::assertNull($this->emptyCollection->getLast());
+ static::assertSame('adipiscing elit', $this->simpleCollection->getLast());
+ }
+
+ public function testGetNext()
+ {
+ static::assertNull($this->emptyCollection->getNext('abc'));
+ static::assertNull($this->simpleCollection->getNext('abc'));
+ static::assertNull($this->simpleCollection->getNext('adipiscing elit'));
+
+ static::assertSame('dolor', $this->simpleCollection->getNext('ipsum'));
+ static::assertSame('sit', $this->simpleCollection->getNext('dolor'));
+ }
+
+ public function testGetPrevious()
+ {
+ static::assertNull($this->emptyCollection->getPrevious('abc'));
+ static::assertNull($this->simpleCollection->getPrevious('abc'));
+ static::assertNull($this->simpleCollection->getPrevious('lorem'));
+
+ static::assertSame('lorem', $this->simpleCollection->getPrevious('ipsum'));
+ static::assertSame('dolor', $this->simpleCollection->getPrevious('sit'));
+ }
+
+ public function testHas()
+ {
+ static::assertFalse($this->emptyCollection->has('abc'));
+ static::assertFalse($this->simpleCollection->has('abc'));
+ static::assertTrue($this->simpleCollection->has('lorem'));
+ static::assertTrue($this->simpleCollection->has('dolor'));
+ }
+
+ public function testIsEmpty()
+ {
+ static::assertTrue($this->emptyCollection->isEmpty());
+ static::assertFalse($this->simpleCollection->isEmpty());
+ }
+
+ public function testIsFirst()
+ {
+ static::assertFalse($this->emptyCollection->isFirst('abc'));
+ static::assertFalse($this->simpleCollection->isFirst('abc'));
+ static::assertFalse($this->simpleCollection->isFirst('dolor'));
+ static::assertTrue($this->simpleCollection->isFirst('lorem'));
+ }
+
+ public function testIsLast()
+ {
+ static::assertFalse($this->emptyCollection->isLast('abc'));
+ static::assertFalse($this->simpleCollection->isLast('abc'));
+ static::assertFalse($this->simpleCollection->isLast('dolor'));
+ static::assertTrue($this->simpleCollection->isLast('adipiscing elit'));
+ }
+
+ /**
+ * @param array $expected
+ * @param int $max
+ * @param int $offset
+ *
+ * @dataProvider provideResultOfLimit
+ */
+ public function testLimit(array $expected, int $max, int $offset): void
+ {
+ $result = $this->simpleCollection->limit($max, $offset);
+ self::assertSame($expected, $result->toArray());
+ }
+
+ public function testLimitIfIsEmpty(): void
+ {
+ $result = $this->emptyCollection->limit(10);
+ self::assertEquals(new StringCollection(), $result);
+ }
+
+ /**
+ * @param array $expected
+ * @param int $max
+ *
+ * @dataProvider provideResultOfLimitWithDefaultOffset
+ */
+ public function testLimitWithDefaultOffset(array $expected, int $max): void
+ {
+ $result = $this->simpleCollection->limit($max);
+ self::assertSame($expected, $result->toArray());
+ }
+
+ public function testNotEmptyCollection()
+ {
+ static::assertSame(7, $this->simpleCollection->count());
+ static::assertCount(7, $this->simpleCollection);
+ static::assertNotEmpty($this->simpleCollection);
+
+ static::assertFalse($this->simpleCollection->isEmpty());
+ static::assertSame($this->simpleElements, $this->simpleCollection->toArray());
+ static::assertNotEmpty($this->simpleCollection->toArray());
+
+ static::assertSame('lorem', $this->simpleCollection->getFirst());
+ static::assertSame('adipiscing elit', $this->simpleCollection->getLast());
+ static::assertSame('dolor', $this->simpleCollection[123]);
+ }
+
+ public function testOffsetExists()
+ {
+ static::assertFalse(isset($this->emptyCollection['abc']));
+ static::assertFalse(isset($this->simpleCollection['abc']));
+
+ static::assertTrue(isset($this->simpleCollection[0]));
+ static::assertTrue(isset($this->simpleCollection[345]));
+ }
+
+ public function testOffsetGet()
+ {
+ static::assertNull($this->emptyCollection['abc']);
+ static::assertNull($this->simpleCollection['abc']);
+
+ static::assertSame('lorem', $this->simpleCollection[0]);
+ static::assertSame('sit', $this->simpleCollection[345]);
+ }
+
+ public function testOffsetSet()
+ {
+ $this->emptyCollection['test1'] = 1234;
+ $this->simpleCollection['test2'] = 5678;
+
+ static::assertTrue($this->emptyCollection->has(1234));
+ static::assertSame(1234, $this->emptyCollection['test1']);
+
+ static::assertTrue($this->simpleCollection->has(5678));
+ static::assertSame(5678, $this->simpleCollection['test2']);
+ }
+
+ public function testOffsetUnset()
+ {
+ unset($this->simpleCollection[0]);
+
+ static::assertFalse($this->simpleCollection->has('lorem'));
+ static::assertSame('ipsum', $this->simpleCollection[1]);
+ static::assertSame(6, $this->simpleCollection->count());
+
+ unset($this->simpleCollection[123]);
+
+ static::assertFalse($this->simpleCollection->has('dolor'));
+ static::assertSame('ipsum', $this->simpleCollection[1]);
+ static::assertSame(5, $this->simpleCollection->count());
+ }
+
+ public function testAppend(): void
+ {
+ $this->emptyCollection->append('lorem-ipsum');
+
+ static::assertFalse($this->emptyCollection->isEmpty());
+ static::assertSame(1, $this->emptyCollection->count());
+ static::assertSame('lorem-ipsum', $this->emptyCollection[0]);
+
+ $this->simpleCollection->append('lorem-ipsum');
+
+ static::assertFalse($this->simpleCollection->isEmpty());
+ static::assertSame(8, $this->simpleCollection->count());
+ static::assertSame('lorem-ipsum', $this->simpleCollection[347]);
+ }
+
+ public function testPrepend()
+ {
+ $this->emptyCollection->prepend('lorem-ipsum');
+
+ static::assertFalse($this->emptyCollection->isEmpty());
+ static::assertSame(1, $this->emptyCollection->count());
+ static::assertSame('lorem-ipsum', $this->emptyCollection[0]);
+
+ $this->simpleCollection->prepend('lorem-ipsum');
+
+ static::assertFalse($this->simpleCollection->isEmpty());
+ static::assertSame(8, $this->simpleCollection->count());
+ static::assertSame('lorem-ipsum', $this->simpleCollection[0]);
+ }
+
+ public function testRemove()
+ {
+ static::assertFalse($this->simpleCollection->isEmpty());
+ static::assertSame(7, $this->simpleCollection->count());
+ static::assertSame('ipsum', $this->simpleCollection[1]);
+
+ $this->simpleCollection->remove('ipsum');
+
+ static::assertFalse($this->simpleCollection->isEmpty());
+ static::assertSame(6, $this->simpleCollection->count());
+ static::assertNull($this->simpleCollection[1]);
+ }
+
+ public function testRemoveNotExistingElement()
+ {
+ $this->emptyCollection->remove('abc');
+
+ static::assertTrue($this->emptyCollection->isEmpty());
+ static::assertSame(0, $this->emptyCollection->count());
+
+ $this->simpleCollection->remove('abc');
+
+ static::assertFalse($this->simpleCollection->isEmpty());
+ static::assertSame(7, $this->simpleCollection->count());
+ }
+
+ public function testToArray()
+ {
+ static::assertSame([], $this->emptyCollection->toArray());
+ static::assertSame($this->simpleElements, $this->simpleCollection->toArray());
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function setUp(): void
+ {
+ parent::setUp();
+
+ $this->simpleElements = [
+ 'lorem',
+ 'ipsum',
+ 123 => 'dolor',
+ 345 => 'sit',
+ 'a' => 'amet',
+ 'c' => 'consectetur',
+ 'adipiscing elit',
+ ];
+
+ $this->emptyCollection = new StringCollection();
+ $this->simpleCollection = new StringCollection($this->simpleElements);
+ }
+}
diff --git a/tests/Collection/CollectionTest.php b/tests/Collection/CollectionTest.php
deleted file mode 100644
index 37e9be2..0000000
--- a/tests/Collection/CollectionTest.php
+++ /dev/null
@@ -1,508 +0,0 @@
-
- * @copyright Meritoo
- */
-class CollectionTest extends BaseTestCase
-{
- /**
- * An empty collection
- *
- * @var Collection
- */
- private $emptyCollection;
-
- /**
- * Simple collection
- *
- * @var Collection
- */
- private $simpleCollection;
-
- /**
- * Elements of simple collection
- *
- * @var array
- */
- private $simpleElements;
-
- public function testEmptyCollection()
- {
- static::assertSame(0, $this->emptyCollection->count());
- static::assertCount(0, $this->emptyCollection);
- static::assertEmpty($this->emptyCollection);
-
- static::assertTrue($this->emptyCollection->isEmpty());
- static::assertSame([], $this->emptyCollection->toArray());
- static::assertEmpty($this->emptyCollection->toArray());
-
- static::assertNull($this->emptyCollection->getFirst());
- static::assertNull($this->emptyCollection->getLast());
- static::assertNull($this->emptyCollection[1]);
- static::assertNull($this->emptyCollection['abc']);
- }
-
- public function testNotEmptyCollection()
- {
- static::assertSame(4, $this->simpleCollection->count());
- static::assertCount(4, $this->simpleCollection);
- static::assertNotEmpty($this->simpleCollection);
-
- static::assertFalse($this->simpleCollection->isEmpty());
- static::assertSame($this->simpleElements, $this->simpleCollection->toArray());
- static::assertNotEmpty($this->simpleCollection->toArray());
-
- static::assertSame('lorem', $this->simpleCollection->getFirst());
- static::assertSame('sit', $this->simpleCollection->getLast());
- static::assertSame('dolor', $this->simpleCollection[123]);
- }
-
- public function testCount()
- {
- static::assertSame(0, $this->emptyCollection->count());
- static::assertSame(4, $this->simpleCollection->count());
- }
-
- public function testOffsetExists()
- {
- static::assertFalse(isset($this->emptyCollection['abc']));
- static::assertFalse(isset($this->simpleCollection['abc']));
-
- static::assertTrue(isset($this->simpleCollection[0]));
- static::assertTrue(isset($this->simpleCollection[345]));
- }
-
- public function testOffsetGet()
- {
- static::assertNull($this->emptyCollection['abc']);
- static::assertNull($this->simpleCollection['abc']);
-
- static::assertSame('lorem', $this->simpleCollection[0]);
- static::assertSame('sit', $this->simpleCollection[345]);
- }
-
- public function testOffsetSet()
- {
- $this->emptyCollection['test1'] = 1234;
- $this->simpleCollection['test2'] = 5678;
-
- static::assertTrue($this->emptyCollection->has(1234));
- static::assertSame(1234, $this->emptyCollection['test1']);
-
- static::assertTrue($this->simpleCollection->has(5678));
- static::assertSame(5678, $this->simpleCollection['test2']);
- }
-
- public function testOffsetUnset()
- {
- unset($this->simpleCollection[0]);
-
- static::assertFalse($this->simpleCollection->has('lorem'));
- static::assertSame('ipsum', $this->simpleCollection[1]);
- static::assertSame(3, $this->simpleCollection->count());
-
- unset($this->simpleCollection[123]);
-
- static::assertFalse($this->simpleCollection->has('dolor'));
- static::assertSame('ipsum', $this->simpleCollection[1]);
- static::assertSame(2, $this->simpleCollection->count());
- }
-
- public function testGetIterator()
- {
- static::assertInstanceOf(ArrayIterator::class, $this->simpleCollection->getIterator());
- }
-
- /**
- * @param mixed $element The element to add
- * @param int $expectedCount Expected count of elements in collection
- * @param int $expectedIndex Expected index of added element in collection
- * @param Collection $collection The collection
- *
- * @dataProvider provideElementToAdd
- */
- public function testAddWithoutIndex($element, $expectedCount, $expectedIndex, Collection $collection)
- {
- $collection->add($element);
-
- static::assertTrue($collection->has($element));
- static::assertSame($expectedCount, $collection->count());
- static::assertSame($element, $collection[$expectedIndex]);
- }
-
- /**
- * @param mixed $element The element to add
- * @param mixed $index Index of element to add
- * @param int $expectedCount Expected count of elements in collection
- * @param int $expectedIndex Expected index of added element in collection
- * @param Collection $collection The collection
- *
- * @dataProvider provideElementToAddWithIndex
- */
- public function testAddWithIndex($element, $index, $expectedCount, $expectedIndex, Collection $collection)
- {
- $collection->add($element, $index);
-
- static::assertTrue($collection->has($element));
- static::assertSame($expectedCount, $collection->count());
- static::assertSame($element, $collection[$expectedIndex]);
- }
-
- public function testAddMultipleUsingEmptyArray()
- {
- $this->emptyCollection->addMultiple([]);
-
- static::assertSame(0, $this->emptyCollection->count());
- static::assertTrue($this->emptyCollection->isEmpty());
- }
-
- public function testAddMultiple()
- {
- $elements = [
- 'test1',
- 'test2',
- 1234 => 'test3',
- 5678 => 'test4',
- ];
-
- $this->emptyCollection->addMultiple($elements);
-
- static::assertFalse($this->emptyCollection->isEmpty());
- static::assertSame(4, $this->emptyCollection->count());
-
- static::assertSame('test1', $this->emptyCollection[0]);
- static::assertSame('test2', $this->emptyCollection[1]);
- static::assertSame('test3', $this->emptyCollection[2]);
- static::assertSame('test4', $this->emptyCollection[3]);
- }
-
- public function testAddMultipleUsingIndexes()
- {
- $elements = [
- 'test1',
- 'test2',
- 1234 => 'test3',
- 5678 => 'test4',
- ];
-
- $this->emptyCollection->addMultiple($elements, true);
-
- static::assertFalse($this->emptyCollection->isEmpty());
- static::assertSame(4, $this->emptyCollection->count());
-
- static::assertSame('test1', $this->emptyCollection[0]);
- static::assertSame('test2', $this->emptyCollection[1]);
- static::assertSame('test3', $this->emptyCollection[1234]);
- static::assertSame('test4', $this->emptyCollection[5678]);
- }
-
- public function testPrepend()
- {
- $this->emptyCollection->prepend('lorem-ipsum');
-
- static::assertFalse($this->emptyCollection->isEmpty());
- static::assertSame(1, $this->emptyCollection->count());
- static::assertSame('lorem-ipsum', $this->emptyCollection[0]);
-
- $this->simpleCollection->prepend('lorem-ipsum');
-
- static::assertFalse($this->simpleCollection->isEmpty());
- static::assertSame(5, $this->simpleCollection->count());
- static::assertSame('lorem-ipsum', $this->simpleCollection[0]);
- }
-
- public function testRemoveNotExistingElement()
- {
- $this->emptyCollection->remove('abc');
-
- static::assertTrue($this->emptyCollection->isEmpty());
- static::assertSame(0, $this->emptyCollection->count());
-
- $this->simpleCollection->remove('abc');
-
- static::assertFalse($this->simpleCollection->isEmpty());
- static::assertSame(4, $this->simpleCollection->count());
- }
-
- public function testRemove()
- {
- static::assertFalse($this->simpleCollection->isEmpty());
- static::assertSame(4, $this->simpleCollection->count());
- static::assertSame('ipsum', $this->simpleCollection[1]);
-
- $this->simpleCollection->remove('ipsum');
-
- static::assertFalse($this->simpleCollection->isEmpty());
- static::assertSame(3, $this->simpleCollection->count());
- static::assertNull($this->simpleCollection[1]);
- }
-
- public function testIsEmpty()
- {
- static::assertTrue($this->emptyCollection->isEmpty());
- static::assertFalse($this->simpleCollection->isEmpty());
- }
-
- public function testIsFirst()
- {
- static::assertFalse($this->emptyCollection->isFirst('abc'));
- static::assertFalse($this->simpleCollection->isFirst('abc'));
- static::assertFalse($this->simpleCollection->isFirst('dolor'));
- static::assertTrue($this->simpleCollection->isFirst('lorem'));
- }
-
- public function testIsLast()
- {
- static::assertFalse($this->emptyCollection->isLast('abc'));
- static::assertFalse($this->simpleCollection->isLast('abc'));
- static::assertFalse($this->simpleCollection->isLast('dolor'));
- static::assertTrue($this->simpleCollection->isLast('sit'));
- }
-
- public function testHas()
- {
- static::assertFalse($this->emptyCollection->has('abc'));
- static::assertFalse($this->simpleCollection->has('abc'));
- static::assertTrue($this->simpleCollection->has('lorem'));
- static::assertTrue($this->simpleCollection->has('dolor'));
- }
-
- public function testGetPrevious()
- {
- static::assertNull($this->emptyCollection->getPrevious('abc'));
- static::assertNull($this->simpleCollection->getPrevious('abc'));
- static::assertNull($this->simpleCollection->getPrevious('lorem'));
-
- static::assertSame('lorem', $this->simpleCollection->getPrevious('ipsum'));
- static::assertSame('dolor', $this->simpleCollection->getPrevious('sit'));
- }
-
- public function testGetNext()
- {
- static::assertNull($this->emptyCollection->getNext('abc'));
- static::assertNull($this->simpleCollection->getNext('abc'));
- static::assertNull($this->simpleCollection->getNext('sit'));
-
- static::assertSame('dolor', $this->simpleCollection->getNext('ipsum'));
- static::assertSame('sit', $this->simpleCollection->getNext('dolor'));
- }
-
- public function testGetFirst()
- {
- static::assertNull($this->emptyCollection->getFirst());
- static::assertSame('lorem', $this->simpleCollection->getFirst());
- }
-
- public function testGetLast()
- {
- static::assertNull($this->emptyCollection->getLast());
- static::assertSame('sit', $this->simpleCollection->getLast());
- }
-
- public function testToArray()
- {
- static::assertSame([], $this->emptyCollection->toArray());
- static::assertSame($this->simpleElements, $this->simpleCollection->toArray());
- }
-
- public function testExistsVisibilityAndArguments()
- {
- static::assertMethodVisibilityAndArguments(Collection::class, 'exists', OopVisibilityType::IS_PRIVATE, 1, 1);
- }
-
- /**
- * @param string $description Description of test
- * @param Collection $collection Collection to search for element with given index
- * @param mixed $index Index / key of the element
- * @param mixed $expected Expected element with given index
- *
- * @dataProvider provideElementGetByIndex
- */
- public function testGetByIndex($description, Collection $collection, $index, $expected)
- {
- static::assertEquals($expected, $collection->getByIndex($index), $description);
- }
-
- /**
- * Provides element to add to collection
- *
- * @return Generator
- */
- public function provideElementToAdd()
- {
- $collection = new Collection();
-
- yield[
- 'test1',
- 1,
- 0,
- $collection,
- ];
-
- yield[
- 'test2',
- 2,
- 1,
- $collection,
- ];
-
- yield[
- 'test3',
- 3,
- 2,
- $collection,
- ];
- }
-
- /**
- * Provides element with index to add to collection
- *
- * @return Generator
- */
- public function provideElementToAddWithIndex()
- {
- $collection = new Collection();
-
- yield[
- 'test1',
- 'aa',
- 1,
- 'aa',
- $collection,
- ];
-
- yield[
- 'test2',
- 'oo',
- 2,
- 'oo',
- $collection,
- ];
-
- yield[
- 'test3',
- null,
- 3,
- 0,
- $collection,
- ];
-
- yield[
- 'test4',
- '',
- 4,
- 1,
- $collection,
- ];
-
- yield[
- 'test5',
- 'vv',
- 5,
- 'vv',
- $collection,
- ];
- }
-
- public function provideElementGetByIndex()
- {
- yield[
- 'An empty collection and empty index',
- new Collection(),
- '',
- null,
- ];
-
- yield[
- 'An empty collection and non-empty index',
- new Collection(),
- 'test',
- null,
- ];
-
- yield[
- 'Non-empty collection and not existing index',
- new Collection([
- 'lorem' => 'ipsum',
- 'dolor' => 'sit',
- ]),
- 'test',
- null,
- ];
-
- yield[
- 'Collection with existing index',
- new Collection([
- 'lorem' => 'ipsum',
- 'dolor' => 'sit',
- ]),
- 'lorem',
- 'ipsum',
- ];
-
- yield[
- 'Collection with existing index (collection of arrays)',
- new Collection([
- [
- 'lorem',
- 'ipsum',
- ],
- [
- 'dolor',
- 'sit',
- ],
- ]),
- 0,
- [
- 'lorem',
- 'ipsum',
- ],
- ];
-
- yield[
- 'Collection with existing index (collection of objects)',
- new Collection([
- 'x' => new \DateTime(),
- 'y' => new \DateTime('2001-01-01'),
- 'z' => new \DateTime('yesterday'),
- ]),
- 'y',
- new \DateTime('2001-01-01'),
- ];
- }
-
- /**
- * {@inheritdoc}
- */
- protected function setUp()
- {
- parent::setUp();
-
- $this->simpleElements = [
- 'lorem',
- 'ipsum',
- 123 => 'dolor',
- 345 => 'sit',
- ];
-
- $this->emptyCollection = new Collection();
- $this->simpleCollection = new Collection($this->simpleElements);
- }
-}
diff --git a/tests/Collection/DateTimeCollectionTest.php b/tests/Collection/DateTimeCollectionTest.php
new file mode 100644
index 0000000..e68415c
--- /dev/null
+++ b/tests/Collection/DateTimeCollectionTest.php
@@ -0,0 +1,92 @@
+
+ * @copyright Meritoo
+ *
+ * @internal
+ * @covers \Meritoo\Common\Collection\DateTimeCollection
+ */
+class DateTimeCollectionTest extends BaseTestCase
+{
+ public function provideDifferentTypesOfElements(): ?Generator
+ {
+ yield [
+ 'An empty array',
+ [],
+ [],
+ ];
+
+ yield [
+ 'Valid elements only',
+ [
+ new DateTime('2001-01-01'),
+ new DateTime('2001-01-02'),
+ ],
+ [
+ new DateTime('2001-01-01'),
+ new DateTime('2001-01-02'),
+ ],
+ ];
+
+ yield [
+ 'Mixed elements',
+ [
+ 1,
+ 'test',
+ new DateTime('2001-01-01'),
+ '',
+ [],
+ 234,
+ new DateTime('2001-01-02'),
+ ],
+ [
+ 2 => new DateTime('2001-01-01'),
+ 6 => new DateTime('2001-01-02'),
+ ],
+ ];
+ }
+
+ public function testConstructor(): void
+ {
+ static::assertConstructorVisibilityAndArguments(
+ DateTimeCollection::class,
+ OopVisibilityType::IS_PUBLIC,
+ 1
+ );
+ }
+
+ /**
+ * @param string $description
+ * @param array $elements
+ * @param array $expectedElements
+ *
+ * @dataProvider provideDifferentTypesOfElements
+ */
+ public function testCreateWithDifferentTypesOfElements(
+ string $description,
+ array $elements,
+ array $expectedElements
+ ): void {
+ $collection = new DateTimeCollection($elements);
+ static::assertEquals($expectedElements, $collection->toArray(), $description);
+ }
+}
diff --git a/tests/Collection/IntegerCollectionTest.php b/tests/Collection/IntegerCollectionTest.php
new file mode 100644
index 0000000..53ffcb6
--- /dev/null
+++ b/tests/Collection/IntegerCollectionTest.php
@@ -0,0 +1,92 @@
+
+ * @copyright Meritoo
+ *
+ * @internal
+ * @covers \Meritoo\Common\Collection\IntegerCollection
+ */
+class IntegerCollectionTest extends BaseTestCase
+{
+ public function provideDifferentTypesOfElements(): ?Generator
+ {
+ yield [
+ 'An empty array',
+ [],
+ [],
+ ];
+
+ yield [
+ 'Valid elements only',
+ [
+ 1,
+ 2,
+ 3,
+ ],
+ [
+ 1,
+ 2,
+ 3,
+ ],
+ ];
+
+ yield [
+ 'Mixed elements',
+ [
+ 1,
+ 'test',
+ '',
+ [],
+ 234,
+ 'test',
+ ],
+ [
+ 0 => 1,
+ 4 => 234,
+ ],
+ ];
+ }
+
+ public function testConstructor(): void
+ {
+ static::assertConstructorVisibilityAndArguments(
+ IntegerCollection::class,
+ OopVisibilityType::IS_PUBLIC,
+ 1
+ );
+ }
+
+ /**
+ * @param string $description
+ * @param array $elements
+ * @param array $expectedElements
+ *
+ * @dataProvider provideDifferentTypesOfElements
+ */
+ public function testCreateWithDifferentTypesOfElements(
+ string $description,
+ array $elements,
+ array $expectedElements
+ ): void {
+ $collection = new IntegerCollection($elements);
+ static::assertSame($expectedElements, $collection->toArray(), $description);
+ }
+}
diff --git a/tests/Collection/StringCollectionTest.php b/tests/Collection/StringCollectionTest.php
new file mode 100644
index 0000000..cbab50a
--- /dev/null
+++ b/tests/Collection/StringCollectionTest.php
@@ -0,0 +1,93 @@
+
+ * @copyright Meritoo
+ *
+ * @internal
+ * @covers \Meritoo\Common\Collection\StringCollection
+ */
+class StringCollectionTest extends BaseTestCase
+{
+ public function provideDifferentTypesOfElements(): ?Generator
+ {
+ yield [
+ 'An empty array',
+ [],
+ [],
+ ];
+
+ yield [
+ 'Valid elements only',
+ [
+ '1',
+ 'test',
+ '',
+ ],
+ [
+ '1',
+ 'test',
+ '',
+ ],
+ ];
+
+ yield [
+ 'Mixed elements',
+ [
+ 1,
+ 'test',
+ '',
+ [],
+ 234,
+ 'test',
+ ],
+ [
+ 1 => 'test',
+ 2 => '',
+ 5 => 'test',
+ ],
+ ];
+ }
+
+ public function testConstructor(): void
+ {
+ static::assertConstructorVisibilityAndArguments(
+ StringCollection::class,
+ OopVisibilityType::IS_PUBLIC,
+ 1
+ );
+ }
+
+ /**
+ * @param string $description
+ * @param array $elements
+ * @param array $expectedElements
+ *
+ * @dataProvider provideDifferentTypesOfElements
+ */
+ public function testCreateWithDifferentTypesOfElements(
+ string $description,
+ array $elements,
+ array $expectedElements
+ ): void {
+ $collection = new StringCollection($elements);
+ static::assertSame($expectedElements, $collection->toArray(), $description);
+ }
+}
diff --git a/tests/Collection/TemplatesTest.php b/tests/Collection/TemplatesTest.php
new file mode 100644
index 0000000..adc84dd
--- /dev/null
+++ b/tests/Collection/TemplatesTest.php
@@ -0,0 +1,188 @@
+
+ * @copyright Meritoo
+ *
+ * @internal
+ * @covers \Meritoo\Common\Collection\Templates
+ */
+class TemplatesTest extends BaseTestCase
+{
+ public function provideArrayWithTemplates(): ?Generator
+ {
+ yield [
+ 'An empty array',
+ [],
+ new Templates(),
+ ];
+
+ yield [
+ 'Number-based indexes',
+ [
+ 'First name: %first_name%',
+ 'Last name: %last_name%',
+ ],
+ new Templates([
+ new Template('First name: %first_name%'),
+ new Template('Last name: %last_name%'),
+ ]),
+ ];
+
+ yield [
+ 'String-based indexes',
+ [
+ 'first' => 'First name: %first_name%',
+ 'last' => 'Last name: %last_name%',
+ ],
+ new Templates([
+ 'first' => new Template('First name: %first_name%'),
+ 'last' => new Template('Last name: %last_name%'),
+ ]),
+ ];
+ }
+
+ public function provideTemplatesToFind(): ?Generator
+ {
+ yield [
+ '2 templates only',
+ new Templates([
+ 'first' => new Template('First name: %first_name%'),
+ 'last' => new Template('Last name: %last_name%'),
+ ]),
+ 'first',
+ new Template('First name: %first_name%'),
+ ];
+
+ yield [
+ 'Different indexes',
+ new Templates([
+ 'first' => new Template('First name: %first_name%'),
+ 'last' => new Template('Last name: %last_name%'),
+ 1 => new Template('Hi %name%, how are you?'),
+ '2' => new Template('Your score is: %score%'),
+ ]),
+ '1',
+ new Template('Hi %name%, how are you?'),
+ ];
+ }
+
+ public function provideTemplatesWithNotExistingIndex(): ?Generator
+ {
+ $template = 'Template with \'%s\' index was not found. Did you provide all required templates?';
+
+ yield [
+ new Templates(),
+ 'test',
+ sprintf($template, 'test'),
+ ];
+
+ yield [
+ new Templates([
+ 'first' => new Template('First name: %first_name%'),
+ 'last' => new Template('Last name: %last_name%'),
+ ]),
+ 'test',
+ sprintf($template, 'test'),
+ ];
+
+ yield [
+ new Templates([
+ 'first' => new Template('First name: %first_name%'),
+ 'last' => new Template('Last name: %last_name%'),
+ ]),
+ '',
+ sprintf($template, ''),
+ ];
+
+ yield [
+ new Templates([
+ 'first' => new Template('First name: %first_name%'),
+ 'last' => new Template('Last name: %last_name%'),
+ ]),
+ '4',
+ sprintf($template, 4),
+ ];
+ }
+
+ public function testConstructor(): void
+ {
+ static::assertConstructorVisibilityAndArguments(
+ Templates::class,
+ OopVisibilityType::IS_PUBLIC,
+ 1
+ );
+ }
+
+ /**
+ * @param string $description Description of test
+ * @param Templates $templates All templates
+ * @param string $index Index that contains required template
+ * @param Template $expected Expected template
+ *
+ * @dataProvider provideTemplatesToFind
+ */
+ public function testFindTemplate(string $description, Templates $templates, string $index, Template $expected): void
+ {
+ static::assertEquals($expected, $templates->findTemplate($index), $description);
+ }
+
+ public function testFindTemplateUsingEmptyCollection(): void
+ {
+ $template = 'Template with \'%s\' index was not found. Did you provide all required templates?';
+ $message = sprintf($template, 'test');
+
+ $this->expectException(TemplateNotFoundException::class);
+ $this->expectExceptionMessage($message);
+
+ $templates = new Templates();
+ $templates->findTemplate('test');
+ }
+
+ /**
+ * @param Templates $templates All templates
+ * @param string $index Index that contains required template
+ * @param string $expectedMessage Expected message of exception
+ *
+ * @dataProvider provideTemplatesWithNotExistingIndex
+ */
+ public function testFindTemplateUsingNotExistingIndex(
+ Templates $templates,
+ string $index,
+ string $expectedMessage
+ ): void {
+ $this->expectException(TemplateNotFoundException::class);
+ $this->expectExceptionMessage($expectedMessage);
+
+ $templates->findTemplate($index);
+ }
+
+ /**
+ * @param string $description Description of test
+ * @param array $templates Pairs of key-value where: key - template's index, value - template's content
+ * @param Templates $expected Expected collection/storage of templates
+ *
+ * @dataProvider provideArrayWithTemplates
+ */
+ public function testFromArray(string $description, array $templates, Templates $expected): void
+ {
+ static::assertEquals($expected, Templates::fromArray($templates), $description);
+ }
+}
diff --git a/tests/Exception/Base/UnknownTypeExceptionTest.php b/tests/Exception/Base/UnknownTypeExceptionTest.php
index ce910d3..c91547a 100644
--- a/tests/Exception/Base/UnknownTypeExceptionTest.php
+++ b/tests/Exception/Base/UnknownTypeExceptionTest.php
@@ -18,24 +18,27 @@ use Meritoo\Common\Type\OopVisibilityType;
*
* @author Meritoo
* @copyright Meritoo
+ *
+ * @internal
+ * @covers \Meritoo\Common\Exception\Base\UnknownTypeException
*/
class UnknownTypeExceptionTest extends BaseTestCase
{
public function testConstructorVisibilityAndArguments()
{
- static::assertConstructorVisibilityAndArguments(UnknownTestTypeException::class, OopVisibilityType::IS_PUBLIC, 3);
+ static::assertConstructorVisibilityAndArguments(UnknownTypeException::class, OopVisibilityType::IS_PUBLIC, 3);
+ }
+
+ public function testTheException()
+ {
+ $this->expectException(UnknownTestTypeException::class);
+ self::assertEmpty((new TestService())->getTranslatedType('test_3'));
}
public function testWithoutException()
{
self::assertEquals('Test 2', (new TestService())->getTranslatedType('test_2'));
}
-
- public function testTheException()
- {
- $this->setExpectedException(UnknownTestTypeException::class);
- self::assertEmpty((new TestService())->getTranslatedType('test_3'));
- }
}
/**
@@ -46,9 +49,9 @@ class UnknownTypeExceptionTest extends BaseTestCase
*/
class TestType extends BaseType
{
- const TEST_1 = 'test_1';
+ public const TEST_1 = 'test_1';
- const TEST_2 = 'test_2';
+ public const TEST_2 = 'test_2';
}
/**
@@ -56,6 +59,9 @@ class TestType extends BaseType
*
* @author Meritoo
* @copyright Meritoo
+ *
+ * @internal
+ * @covers \Meritoo\Common\Exception\Base\UnknownTypeException
*/
class UnknownTestTypeException extends UnknownTypeException
{
@@ -65,12 +71,9 @@ class UnknownTestTypeException extends UnknownTypeException
* @param string $unknownType The unknown type of something (for testing purposes)
* @return UnknownTestTypeException
*/
- public static function createException($unknownType)
+ public static function createException(string $unknownType): UnknownTestTypeException
{
- /* @var UnknownTestTypeException $exception */
- $exception = parent::create($unknownType, new TestType(), 'type of something used for testing');
-
- return $exception;
+ return parent::create($unknownType, new TestType(), 'type of something used for testing');
}
}
@@ -86,12 +89,12 @@ class TestService
* Returns translated type (for testing purposes)
*
* @param string $type Type of something (for testing purposes)
- * @throws UnknownTestTypeException
* @return string
+ * @throws UnknownTestTypeException
*/
- public function getTranslatedType($type)
+ public function getTranslatedType(string $type): string
{
- if ((new TestType())->isCorrectType($type)) {
+ if (TestType::isCorrectType($type)) {
return ucfirst(str_replace('_', ' ', $type));
}
diff --git a/tests/Exception/Bundle/IncorrectBundleNameExceptionTest.php b/tests/Exception/Bundle/IncorrectBundleNameExceptionTest.php
index 5c2d420..d862480 100644
--- a/tests/Exception/Bundle/IncorrectBundleNameExceptionTest.php
+++ b/tests/Exception/Bundle/IncorrectBundleNameExceptionTest.php
@@ -8,6 +8,7 @@
namespace Meritoo\Test\Common\Exception\Bundle;
+use Generator;
use Meritoo\Common\Exception\Bundle\IncorrectBundleNameException;
use Meritoo\Common\Test\Base\BaseTestCase;
use Meritoo\Common\Type\OopVisibilityType;
@@ -17,10 +18,37 @@ use Meritoo\Common\Type\OopVisibilityType;
*
* @author Meritoo
* @copyright Meritoo
+ *
+ * @internal
+ * @covers \Meritoo\Common\Exception\Bundle\IncorrectBundleNameException
*/
class IncorrectBundleNameExceptionTest extends BaseTestCase
{
- public function testConstructor()
+ public function provideBundleNameAndMessage(): Generator
+ {
+ $template = 'Name of bundle \'%s\' is incorrect. It should start with big letter and end with "Bundle". Is'
+ .' there everything ok?';
+
+ yield [
+ 'An empty string as name of bundle',
+ '',
+ sprintf($template, ''),
+ ];
+
+ yield [
+ 'String with spaces as name of bundle',
+ 'This is test',
+ sprintf($template, 'This is test'),
+ ];
+
+ yield [
+ 'String without spaces as name of bundle',
+ 'ThisIsTest',
+ sprintf($template, 'ThisIsTest'),
+ ];
+ }
+
+ public function testConstructor(): void
{
static::assertConstructorVisibilityAndArguments(
IncorrectBundleNameException::class,
@@ -36,39 +64,9 @@ class IncorrectBundleNameExceptionTest extends BaseTestCase
*
* @dataProvider provideBundleNameAndMessage
*/
- public function testCreate($description, $bundleName, $expectedMessage)
+ public function testCreate(string $description, string $bundleName, string $expectedMessage): void
{
$exception = IncorrectBundleNameException::create($bundleName);
static::assertSame($expectedMessage, $exception->getMessage(), $description);
}
-
- public function provideBundleNameAndMessage()
- {
- $template = 'Name of bundle \'%s\' is incorrect. It should start with big letter and end with "Bundle". Is'
- . ' there everything ok?';
-
- yield[
- 'An empty string as name of bundle',
- '',
- sprintf($template, ''),
- ];
-
- yield[
- 'Null as name of bundle',
- null,
- sprintf($template, ''),
- ];
-
- yield[
- 'String with spaces as name of bundle',
- 'This is test',
- sprintf($template, 'This is test'),
- ];
-
- yield[
- 'String without spaces as name of bundle',
- 'ThisIsTest',
- sprintf($template, 'ThisIsTest'),
- ];
- }
}
diff --git a/tests/Exception/Date/UnknownDatePartTypeExceptionTest.php b/tests/Exception/Date/UnknownDatePartTypeExceptionTest.php
index f694ef1..4bc5b7b 100644
--- a/tests/Exception/Date/UnknownDatePartTypeExceptionTest.php
+++ b/tests/Exception/Date/UnknownDatePartTypeExceptionTest.php
@@ -19,9 +19,41 @@ use Meritoo\Common\Type\OopVisibilityType;
*
* @author Meritoo
* @copyright Meritoo
+ *
+ * @internal
+ * @covers \Meritoo\Common\Exception\Type\UnknownDatePartTypeException
*/
class UnknownDatePartTypeExceptionTest extends BaseTestCase
{
+ /**
+ * Provides type of date part, incorrect value and expected exception's message
+ *
+ * @return Generator
+ */
+ public function provideDatePartAndValue()
+ {
+ $template = 'The \'%s\' type of date part (with value %s) is unknown. Probably doesn\'t exist or there is a'
+ .' typo. You should use one of these types: day, hour, minute, month, second, year.';
+
+ yield [
+ DatePartType::DAY,
+ '44',
+ sprintf($template, DatePartType::DAY, '44'),
+ ];
+
+ yield [
+ DatePartType::MONTH,
+ '22',
+ sprintf($template, DatePartType::MONTH, '22'),
+ ];
+
+ yield [
+ DatePartType::MINUTE,
+ '77',
+ sprintf($template, DatePartType::MINUTE, '77'),
+ ];
+ }
+
public function testConstructorVisibilityAndArguments()
{
static::assertConstructorVisibilityAndArguments(UnknownDatePartTypeException::class, OopVisibilityType::IS_PUBLIC, 3);
@@ -39,33 +71,4 @@ class UnknownDatePartTypeExceptionTest extends BaseTestCase
$exception = UnknownDatePartTypeException::createException($unknownDatePart, $value);
static::assertSame($expectedMessage, $exception->getMessage());
}
-
- /**
- * Provides type of date part, incorrect value and expected exception's message
- *
- * @return Generator
- */
- public function provideDatePartAndValue()
- {
- $template = 'The \'%s\' type of date part (with value %s) is unknown. Probably doesn\'t exist or there is a'
- . ' typo. You should use one of these types: day, hour, minute, month, second, year.';
-
- yield[
- DatePartType::DAY,
- '44',
- sprintf($template, DatePartType::DAY, '44'),
- ];
-
- yield[
- DatePartType::MONTH,
- '22',
- sprintf($template, DatePartType::MONTH, '22'),
- ];
-
- yield[
- DatePartType::MINUTE,
- '77',
- sprintf($template, DatePartType::MINUTE, '77'),
- ];
- }
}
diff --git a/tests/Exception/File/EmptyFileExceptionTest.php b/tests/Exception/File/EmptyFileExceptionTest.php
index a2ee08d..0825b32 100644
--- a/tests/Exception/File/EmptyFileExceptionTest.php
+++ b/tests/Exception/File/EmptyFileExceptionTest.php
@@ -18,9 +18,32 @@ use Meritoo\Common\Type\OopVisibilityType;
*
* @author Meritoo
* @copyright Meritoo
+ *
+ * @internal
+ * @covers \Meritoo\Common\Exception\File\EmptyFileException
*/
class EmptyFileExceptionTest extends BaseTestCase
{
+ /**
+ * Provides path of the empty file and expected exception's message
+ *
+ * @return Generator
+ */
+ public function providePathOfFile()
+ {
+ $template = 'File with path \'%s\' is empty (has no content). Did you provide path of proper file?';
+
+ yield [
+ 'aa/bb/cc',
+ sprintf($template, 'aa/bb/cc'),
+ ];
+
+ yield [
+ 'images/show/car.jpg',
+ sprintf($template, 'images/show/car.jpg'),
+ ];
+ }
+
public function testConstructorVisibilityAndArguments()
{
static::assertConstructorVisibilityAndArguments(EmptyFileException::class, OopVisibilityType::IS_PUBLIC, 3);
@@ -37,24 +60,4 @@ class EmptyFileExceptionTest extends BaseTestCase
$exception = EmptyFileException::create($emptyFilePath);
static::assertSame($expectedMessage, $exception->getMessage());
}
-
- /**
- * Provides path of the empty file and expected exception's message
- *
- * @return Generator
- */
- public function providePathOfFile()
- {
- $template = 'File with path \'%s\' is empty (has no content). Did you provide path of proper file?';
-
- yield[
- 'aa/bb/cc',
- sprintf($template, 'aa/bb/cc'),
- ];
-
- yield[
- 'images/show/car.jpg',
- sprintf($template, 'images/show/car.jpg'),
- ];
- }
}
diff --git a/tests/Exception/File/EmptyFilePathExceptionTest.php b/tests/Exception/File/EmptyFilePathExceptionTest.php
index b582579..560351c 100644
--- a/tests/Exception/File/EmptyFilePathExceptionTest.php
+++ b/tests/Exception/File/EmptyFilePathExceptionTest.php
@@ -17,17 +17,20 @@ use Meritoo\Common\Type\OopVisibilityType;
*
* @author Meritoo
* @copyright Meritoo
+ *
+ * @internal
+ * @covers \Meritoo\Common\Exception\File\EmptyFilePathException
*/
class EmptyFilePathExceptionTest extends BaseTestCase
{
- public function testConstructorVisibilityAndArguments()
- {
- static::assertConstructorVisibilityAndArguments(EmptyFilePathException::class, OopVisibilityType::IS_PUBLIC, 3);
- }
-
public function testConstructorMessage()
{
$exception = EmptyFilePathException::create();
static::assertSame('Path of the file is empty. Did you provide path of proper file?', $exception->getMessage());
}
+
+ public function testConstructorVisibilityAndArguments()
+ {
+ static::assertConstructorVisibilityAndArguments(EmptyFilePathException::class, OopVisibilityType::IS_PUBLIC, 3);
+ }
}
diff --git a/tests/Exception/File/NotExistingFileExceptionTest.php b/tests/Exception/File/NotExistingFileExceptionTest.php
index 08f8868..b8c6cb6 100644
--- a/tests/Exception/File/NotExistingFileExceptionTest.php
+++ b/tests/Exception/File/NotExistingFileExceptionTest.php
@@ -18,12 +18,30 @@ use Meritoo\Common\Type\OopVisibilityType;
*
* @author Meritoo
* @copyright Meritoo
+ *
+ * @internal
+ * @covers \Meritoo\Common\Exception\File\NotExistingFileException
*/
class NotExistingFileExceptionTest extends BaseTestCase
{
- public function testConstructorVisibilityAndArguments()
+ /**
+ * Provides path of not existing file and expected exception's message
+ *
+ * @return Generator
+ */
+ public function providePathOfFile()
{
- static::assertConstructorVisibilityAndArguments(NotExistingFileException::class, OopVisibilityType::IS_PUBLIC, 3);
+ $template = 'File with path \'%s\' does not exist (or is not readable). Did you provide path of proper file?';
+
+ yield [
+ 'aa/bb/cc',
+ sprintf($template, 'aa/bb/cc'),
+ ];
+
+ yield [
+ 'images/show/car.jpg',
+ sprintf($template, 'images/show/car.jpg'),
+ ];
}
/**
@@ -38,23 +56,8 @@ class NotExistingFileExceptionTest extends BaseTestCase
static::assertSame($expectedMessage, $exception->getMessage());
}
- /**
- * Provides path of not existing file and expected exception's message
- *
- * @return Generator
- */
- public function providePathOfFile()
+ public function testConstructorVisibilityAndArguments()
{
- $template = 'File with path \'%s\' does not exist (or is not readable). Did you provide path of proper file?';
-
- yield[
- 'aa/bb/cc',
- sprintf($template, 'aa/bb/cc'),
- ];
-
- yield[
- 'images/show/car.jpg',
- sprintf($template, 'images/show/car.jpg'),
- ];
+ static::assertConstructorVisibilityAndArguments(NotExistingFileException::class, OopVisibilityType::IS_PUBLIC, 3);
}
}
diff --git a/tests/Exception/Method/DisabledMethodExceptionTest.php b/tests/Exception/Method/DisabledMethodExceptionTest.php
index a815b4e..18af361 100644
--- a/tests/Exception/Method/DisabledMethodExceptionTest.php
+++ b/tests/Exception/Method/DisabledMethodExceptionTest.php
@@ -18,12 +18,33 @@ use Meritoo\Common\Type\OopVisibilityType;
*
* @author Meritoo
* @copyright Meritoo
+ *
+ * @internal
+ * @covers \Meritoo\Common\Exception\Method\DisabledMethodException
*/
class DisabledMethodExceptionTest extends BaseTestCase
{
- public function testConstructorVisibilityAndArguments()
+ /**
+ * Provides name of the disabled method, name of the alternative method and expected exception's message
+ *
+ * @return Generator
+ */
+ public function provideMethodsNames()
{
- static::assertConstructorVisibilityAndArguments(DisabledMethodException::class, OopVisibilityType::IS_PUBLIC, 3);
+ $templateShort = 'Method %s() cannot be called, because is disabled.';
+ $templateLong = $templateShort.' Use %s() instead.';
+
+ yield [
+ 'FooBar::loremIpsum',
+ '',
+ sprintf($templateShort, 'FooBar::loremIpsum'),
+ ];
+
+ yield [
+ 'FooBar::loremIpsum',
+ 'AnotherClass::alternativeMethod',
+ sprintf($templateLong, 'FooBar::loremIpsum', 'AnotherClass::alternativeMethod'),
+ ];
}
/**
@@ -40,26 +61,8 @@ class DisabledMethodExceptionTest extends BaseTestCase
static::assertSame($expectedMessage, $exception->getMessage());
}
- /**
- * Provides name of the disabled method, name of the alternative method and expected exception's message
- *
- * @return Generator
- */
- public function provideMethodsNames()
+ public function testConstructorVisibilityAndArguments()
{
- $templateShort = 'Method %s() cannot be called, because is disabled.';
- $templateLong = $templateShort . ' Use %s() instead.';
-
- yield[
- 'FooBar::loremIpsum',
- '',
- sprintf($templateShort, 'FooBar::loremIpsum'),
- ];
-
- yield[
- 'FooBar::loremIpsum',
- 'AnotherClass::alternativeMethod',
- sprintf($templateLong, 'FooBar::loremIpsum', 'AnotherClass::alternativeMethod'),
- ];
+ static::assertConstructorVisibilityAndArguments(DisabledMethodException::class, OopVisibilityType::IS_PUBLIC, 3);
}
}
diff --git a/tests/Exception/Reflection/CannotResolveClassNameExceptionTest.php b/tests/Exception/Reflection/CannotResolveClassNameExceptionTest.php
index c6f9082..059b8c3 100644
--- a/tests/Exception/Reflection/CannotResolveClassNameExceptionTest.php
+++ b/tests/Exception/Reflection/CannotResolveClassNameExceptionTest.php
@@ -12,62 +12,74 @@ use Generator;
use Meritoo\Common\Exception\Reflection\CannotResolveClassNameException;
use Meritoo\Common\Test\Base\BaseTestCase;
use Meritoo\Common\Type\OopVisibilityType;
+use stdClass;
/**
* Test case of an exception used while name of class or trait cannot be resolved
*
* @author Meritoo
* @copyright Meritoo
+ *
+ * @internal
+ * @covers \Meritoo\Common\Exception\Reflection\CannotResolveClassNameException
*/
class CannotResolveClassNameExceptionTest extends BaseTestCase
{
- public function testConstructorVisibilityAndArguments()
- {
- static::assertConstructorVisibilityAndArguments(CannotResolveClassNameException::class, OopVisibilityType::IS_PUBLIC, 3);
- }
-
- /**
- * @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 If is set to true, message of this exception for class is prepared.
- * Otherwise - for trait.
- * @param string $expectedMessage Expected exception's message
- *
- * @dataProvider provideClassName
- */
- public function testConstructorMessage($source, $forClass, $expectedMessage)
- {
- $exception = CannotResolveClassNameException::create($source, $forClass);
- static::assertSame($expectedMessage, $exception->getMessage());
- }
-
/**
* Provides source of the class's / trait's name, information if message of this exception should be prepared for
* class and the expected exception's message
*
* @return Generator
*/
- public function provideClassName()
+ public function provideClassName(): Generator
{
- yield[
+ yield [
'Not\Existing\Class',
true,
'Name of class from given \'string\' Not\Existing\Class cannot be resolved. Is there everything ok?',
];
- yield[
+ yield [
'Not\Existing\Trait',
false,
'Name of trait from given \'string\' Not\Existing\Trait cannot be resolved. Is there everything ok?',
];
- yield[
- [
- new \stdClass(),
- new \stdClass(),
- ],
+ yield [
+ stdClass::class,
true,
- 'Name of class from given \'array\' cannot be resolved. Is there everything ok?',
+ 'Name of class from given \'string\' stdClass cannot be resolved. Is there everything ok?',
];
}
+
+ public function testConstructorVisibilityAndArguments(): void
+ {
+ static::assertConstructorVisibilityAndArguments(
+ CannotResolveClassNameException::class,
+ OopVisibilityType::IS_PUBLIC,
+ 3
+ );
+ }
+
+ /**
+ * @param string $source Source of name of the class or trait
+ * @param bool $forClass (optional) If is set to true, message of this exception for class is prepared.
+ * Otherwise - for trait.
+ * @param string $expectedMessage Expected exception's message
+ *
+ * @dataProvider provideClassName
+ */
+ public function testCreate(string $source, bool $forClass, string $expectedMessage): void
+ {
+ $exception = CannotResolveClassNameException::create($source, $forClass);
+ static::assertSame($expectedMessage, $exception->getMessage());
+ }
+
+ public function testCreateUsingDefaults(): void
+ {
+ $exception = CannotResolveClassNameException::create(stdClass::class);
+ $expectedMessage = 'Name of class from given \'string\' stdClass cannot be resolved. Is there everything ok?';
+
+ static::assertSame($expectedMessage, $exception->getMessage());
+ }
}
diff --git a/tests/Exception/Reflection/ClassWithoutConstructorExceptionTest.php b/tests/Exception/Reflection/ClassWithoutConstructorExceptionTest.php
new file mode 100644
index 0000000..13e9eff
--- /dev/null
+++ b/tests/Exception/Reflection/ClassWithoutConstructorExceptionTest.php
@@ -0,0 +1,66 @@
+
+ * @copyright Meritoo
+ *
+ * @internal
+ * @covers \Meritoo\Common\Exception\Reflection\ClassWithoutConstructorException
+ */
+class ClassWithoutConstructorExceptionTest extends BaseTestCase
+{
+ public function provideClassName(): Generator
+ {
+ $template = 'Oops, class \'%s\' hasn\'t constructor. Did you use proper class?';
+
+ yield [
+ 'An empty name of class',
+ '',
+ sprintf($template, ''),
+ ];
+
+ yield [
+ 'The Arrays class',
+ Arrays::class,
+ sprintf($template, Arrays::class),
+ ];
+ }
+
+ public function testConstructor(): void
+ {
+ static::assertConstructorVisibilityAndArguments(
+ ClassWithoutConstructorException::class,
+ OopVisibilityType::IS_PUBLIC,
+ 3
+ );
+ }
+
+ /**
+ * @param string $description Description of test case
+ * @param string $className Fully-qualified name of class that hasn't constructor
+ * @param string $expectedMessage Expected exception's message
+ *
+ * @dataProvider provideClassName
+ */
+ public function testCreate(string $description, string $className, string $expectedMessage): void
+ {
+ $exception = ClassWithoutConstructorException::create($className);
+ static::assertSame($expectedMessage, $exception->getMessage(), $description);
+ }
+}
diff --git a/tests/Exception/Reflection/MissingChildClassesExceptionTest.php b/tests/Exception/Reflection/MissingChildClassesExceptionTest.php
index 900d6e2..fccac2e 100644
--- a/tests/Exception/Reflection/MissingChildClassesExceptionTest.php
+++ b/tests/Exception/Reflection/MissingChildClassesExceptionTest.php
@@ -12,18 +12,50 @@ use Generator;
use Meritoo\Common\Exception\Reflection\MissingChildClassesException;
use Meritoo\Common\Test\Base\BaseTestCase;
use Meritoo\Common\Type\OopVisibilityType;
+use stdClass;
/**
* Test case of an exception used while given class has no child classes
*
* @author Meritoo
* @copyright Meritoo
+ *
+ * @internal
+ * @covers \Meritoo\Common\Exception\Reflection\MissingChildClassesException
*/
class MissingChildClassesExceptionTest extends BaseTestCase
{
- public function testConstructorVisibilityAndArguments()
+ /**
+ * Provides name of class that hasn't child classes, but it should, and expected exception's message
+ *
+ * @return Generator
+ */
+ public function provideParentClass(): ?Generator
{
- static::assertConstructorVisibilityAndArguments(MissingChildClassesException::class, OopVisibilityType::IS_PUBLIC, 3);
+ $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?';
+
+ yield [
+ MissingChildClassesException::class,
+ sprintf($template, MissingChildClassesException::class),
+ ];
+
+ yield [
+ [
+ new stdClass(),
+ new stdClass(),
+ ],
+ sprintf($template, stdClass::class),
+ ];
+ }
+
+ public function testConstructorVisibilityAndArguments(): void
+ {
+ static::assertConstructorVisibilityAndArguments(
+ MissingChildClassesException::class,
+ OopVisibilityType::IS_PUBLIC,
+ 3
+ );
}
/**
@@ -33,33 +65,9 @@ class MissingChildClassesExceptionTest extends BaseTestCase
*
* @dataProvider provideParentClass
*/
- public function testConstructorMessage($parentClass, $expectedMessage)
+ public function testCreate($parentClass, string $expectedMessage): void
{
$exception = MissingChildClassesException::create($parentClass);
static::assertSame($expectedMessage, $exception->getMessage());
}
-
- /**
- * Provides name of class that hasn't child classes, but it should, and expected exception's message
- *
- * @return Generator
- */
- public function provideParentClass()
- {
- $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?';
-
- yield[
- MissingChildClassesException::class,
- sprintf($template, MissingChildClassesException::class),
- ];
-
- yield[
- [
- new \stdClass(),
- new \stdClass(),
- ],
- sprintf($template, \stdClass::class),
- ];
- }
}
diff --git a/tests/Exception/Reflection/NotExistingPropertyExceptionTest.php b/tests/Exception/Reflection/NotExistingPropertyExceptionTest.php
index e172003..256a75c 100644
--- a/tests/Exception/Reflection/NotExistingPropertyExceptionTest.php
+++ b/tests/Exception/Reflection/NotExistingPropertyExceptionTest.php
@@ -8,19 +8,57 @@
namespace Meritoo\Test\Common\Exception\Reflection;
+use Generator;
use Meritoo\Common\Exception\Reflection\NotExistingPropertyException;
use Meritoo\Common\Test\Base\BaseTestCase;
use Meritoo\Common\Type\OopVisibilityType;
+use stdClass;
/**
* Class NotExistingPropertyExceptionTest
*
* @author Meritoo
* @copyright Meritoo
+ *
+ * @internal
+ * @covers \Meritoo\Common\Exception\Reflection\NotExistingPropertyException
*/
class NotExistingPropertyExceptionTest extends BaseTestCase
{
- public function testConstructor()
+ public function provideObjectPropertyAndMessage(): ?Generator
+ {
+ $template = 'Property \'%s\' does not exist in instance of class \'%s\'. Did you use proper name of property?';
+
+ yield [
+ 'An empty string as name of property',
+ new stdClass(),
+ '',
+ sprintf($template, '', get_class(new stdClass())),
+ ];
+
+ yield [
+ 'Null as name of property',
+ new stdClass(),
+ null,
+ sprintf($template, '', get_class(new stdClass())),
+ ];
+
+ yield [
+ 'String with spaces as name of property',
+ new stdClass(),
+ 'This is test',
+ sprintf($template, 'This is test', get_class(new stdClass())),
+ ];
+
+ yield [
+ 'String without spaces as name of property',
+ new stdClass(),
+ 'ThisIsTest',
+ sprintf($template, 'ThisIsTest', get_class(new stdClass())),
+ ];
+ }
+
+ public function testConstructor(): void
{
static::assertConstructorVisibilityAndArguments(
NotExistingPropertyException::class,
@@ -30,49 +68,16 @@ class NotExistingPropertyExceptionTest extends BaseTestCase
}
/**
- * @param string $description Description of test
- * @param mixed $object Object that should contains given property
- * @param string $property Name of the property
- * @param string $expectedMessage Expected exception's message
+ * @param string $description Description of test
+ * @param mixed $object Object that should contains given property
+ * @param null|string $property Name of the property
+ * @param string $expectedMessage Expected exception's message
*
* @dataProvider provideObjectPropertyAndMessage
*/
- public function testCreate($description, $object, $property, $expectedMessage)
+ public function testCreate(string $description, $object, ?string $property, string $expectedMessage): void
{
$exception = NotExistingPropertyException::create($object, $property);
static::assertSame($expectedMessage, $exception->getMessage(), $description);
}
-
- public function provideObjectPropertyAndMessage()
- {
- $template = 'Property \'%s\' does not exist in instance of class \'%s\'. Did you use proper name of property?';
-
- yield[
- 'An empty string as name of property',
- new \stdClass(),
- '',
- sprintf($template, '', get_class(new \stdClass())),
- ];
-
- yield[
- 'Null as name of property',
- new \stdClass(),
- null,
- sprintf($template, '', get_class(new \stdClass())),
- ];
-
- yield[
- 'String with spaces as name of property',
- new \stdClass(),
- 'This is test',
- sprintf($template, 'This is test', get_class(new \stdClass())),
- ];
-
- yield[
- 'String without spaces as name of property',
- new \stdClass(),
- 'ThisIsTest',
- sprintf($template, 'ThisIsTest', get_class(new \stdClass())),
- ];
- }
}
diff --git a/tests/Exception/Reflection/TooManyChildClassesExceptionTest.php b/tests/Exception/Reflection/TooManyChildClassesExceptionTest.php
index 3c19cad..9d0c58d 100644
--- a/tests/Exception/Reflection/TooManyChildClassesExceptionTest.php
+++ b/tests/Exception/Reflection/TooManyChildClassesExceptionTest.php
@@ -12,18 +12,58 @@ use Generator;
use Meritoo\Common\Exception\Reflection\TooManyChildClassesException;
use Meritoo\Common\Test\Base\BaseTestCase;
use Meritoo\Common\Type\OopVisibilityType;
+use stdClass;
/**
* Test case of an exception used while given class has more than one child class
*
* @author Meritoo
* @copyright Meritoo
+ *
+ * @internal
+ * @covers \Meritoo\Common\Exception\Reflection\TooManyChildClassesException
*/
class TooManyChildClassesExceptionTest extends BaseTestCase
{
- public function testConstructorVisibilityAndArguments()
+ /**
+ * Provides name of class that has more than one child class, but it shouldn't, child classes, and expected
+ * exception's message
+ *
+ * @return Generator
+ */
+ public function provideParentAndChildClasses(): ?Generator
{
- static::assertConstructorVisibilityAndArguments(TooManyChildClassesException::class, OopVisibilityType::IS_PUBLIC, 3);
+ $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?";
+
+ yield [
+ BaseTestCase::class,
+ [
+ stdClass::class,
+ OopVisibilityType::class,
+ ],
+ sprintf($template, BaseTestCase::class, implode("\n- ", [
+ stdClass::class,
+ OopVisibilityType::class,
+ ]), BaseTestCase::class),
+ ];
+
+ yield [
+ TooManyChildClassesException::class,
+ [
+ stdClass::class,
+ ],
+ sprintf($template, TooManyChildClassesException::class, implode("\n- ", [stdClass::class]), TooManyChildClassesException::class),
+ ];
+ }
+
+ public function testConstructor(): void
+ {
+ static::assertConstructorVisibilityAndArguments(
+ TooManyChildClassesException::class,
+ OopVisibilityType::IS_PUBLIC,
+ 3
+ );
}
/**
@@ -34,41 +74,9 @@ class TooManyChildClassesExceptionTest extends BaseTestCase
*
* @dataProvider provideParentAndChildClasses
*/
- public function testConstructorMessage($parentClass, array $childClasses, $expectedMessage)
+ public function testCreate($parentClass, array $childClasses, string $expectedMessage): void
{
$exception = TooManyChildClassesException::create($parentClass, $childClasses);
static::assertSame($expectedMessage, $exception->getMessage());
}
-
- /**
- * Provides name of class that has more than one child class, but it shouldn't, child classes, and expected
- * exception's message
- *
- * @return Generator
- */
- public function provideParentAndChildClasses()
- {
- $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?";
-
- yield[
- BaseTestCase::class,
- [
- \stdClass::class,
- OopVisibilityType::class,
- ],
- sprintf($template, BaseTestCase::class, implode("\n- ", [
- \stdClass::class,
- OopVisibilityType::class,
- ]), BaseTestCase::class),
- ];
-
- yield[
- TooManyChildClassesException::class,
- [
- \stdClass::class,
- ],
- sprintf($template, TooManyChildClassesException::class, implode("\n- ", [\stdClass::class]), TooManyChildClassesException::class),
- ];
- }
}
diff --git a/tests/Exception/Regex/IncorrectColorHexLengthExceptionTest.php b/tests/Exception/Regex/IncorrectColorHexLengthExceptionTest.php
index 9482dbd..754f8ab 100644
--- a/tests/Exception/Regex/IncorrectColorHexLengthExceptionTest.php
+++ b/tests/Exception/Regex/IncorrectColorHexLengthExceptionTest.php
@@ -18,12 +18,30 @@ use Meritoo\Common\Type\OopVisibilityType;
*
* @author Meritoo
* @copyright Meritoo
+ *
+ * @internal
+ * @covers \Meritoo\Common\Exception\Regex\IncorrectColorHexLengthException
*/
class IncorrectColorHexLengthExceptionTest extends BaseTestCase
{
- public function testConstructorVisibilityAndArguments()
+ /**
+ * Provides incorrect hexadecimal value of color and expected exception's message
+ *
+ * @return Generator
+ */
+ public function provideColor()
{
- static::assertConstructorVisibilityAndArguments(IncorrectColorHexLengthException::class, OopVisibilityType::IS_PUBLIC, 3);
+ $template = 'Length of hexadecimal value of color \'%s\' is incorrect. It\'s %d, but it should be 3 or 6. Is there everything ok?';
+
+ yield [
+ '',
+ sprintf($template, '', strlen('')),
+ ];
+
+ yield [
+ 'aa-bb-cc',
+ sprintf($template, 'aa-bb-cc', strlen('aa-bb-cc')),
+ ];
}
/**
@@ -38,23 +56,8 @@ class IncorrectColorHexLengthExceptionTest extends BaseTestCase
static::assertSame($expectedMessage, $exception->getMessage());
}
- /**
- * Provides incorrect hexadecimal value of color and expected exception's message
- *
- * @return Generator
- */
- public function provideColor()
+ public function testConstructorVisibilityAndArguments()
{
- $template = 'Length of hexadecimal value of color \'%s\' is incorrect. It\'s %d, but it should be 3 or 6. Is there everything ok?';
-
- yield[
- '',
- sprintf($template, '', strlen('')),
- ];
-
- yield[
- 'aa-bb-cc',
- sprintf($template, 'aa-bb-cc', strlen('aa-bb-cc')),
- ];
+ static::assertConstructorVisibilityAndArguments(IncorrectColorHexLengthException::class, OopVisibilityType::IS_PUBLIC, 3);
}
}
diff --git a/tests/Exception/Regex/InvalidColorHexValueExceptionTest.php b/tests/Exception/Regex/InvalidColorHexValueExceptionTest.php
index ec32268..38b4cf0 100644
--- a/tests/Exception/Regex/InvalidColorHexValueExceptionTest.php
+++ b/tests/Exception/Regex/InvalidColorHexValueExceptionTest.php
@@ -18,12 +18,30 @@ use Meritoo\Common\Type\OopVisibilityType;
*
* @author Meritoo
* @copyright Meritoo
+ *
+ * @internal
+ * @covers \Meritoo\Common\Exception\Regex\InvalidColorHexValueException
*/
class InvalidColorHexValueExceptionTest extends BaseTestCase
{
- public function testConstructorVisibilityAndArguments()
+ /**
+ * Provides invalid hexadecimal value of color and expected exception's message
+ *
+ * @return Generator
+ */
+ public function provideColor()
{
- static::assertConstructorVisibilityAndArguments(InvalidColorHexValueException::class, OopVisibilityType::IS_PUBLIC, 3);
+ $template = 'Hexadecimal value of color \'%s\' is invalid. Is there everything ok?';
+
+ yield [
+ '',
+ sprintf($template, ''),
+ ];
+
+ yield [
+ 'aa-bb-cc',
+ sprintf($template, 'aa-bb-cc'),
+ ];
}
/**
@@ -38,23 +56,8 @@ class InvalidColorHexValueExceptionTest extends BaseTestCase
static::assertSame($expectedMessage, $exception->getMessage());
}
- /**
- * Provides invalid hexadecimal value of color and expected exception's message
- *
- * @return Generator
- */
- public function provideColor()
+ public function testConstructorVisibilityAndArguments()
{
- $template = 'Hexadecimal value of color \'%s\' is invalid. Is there everything ok?';
-
- yield[
- '',
- sprintf($template, ''),
- ];
-
- yield[
- 'aa-bb-cc',
- sprintf($template, 'aa-bb-cc'),
- ];
+ static::assertConstructorVisibilityAndArguments(InvalidColorHexValueException::class, OopVisibilityType::IS_PUBLIC, 3);
}
}
diff --git a/tests/Exception/Regex/InvalidHtmlAttributesExceptionTest.php b/tests/Exception/Regex/InvalidHtmlAttributesExceptionTest.php
index 6772791..799169d 100644
--- a/tests/Exception/Regex/InvalidHtmlAttributesExceptionTest.php
+++ b/tests/Exception/Regex/InvalidHtmlAttributesExceptionTest.php
@@ -18,12 +18,35 @@ use Meritoo\Common\Type\OopVisibilityType;
*
* @author Meritoo
* @copyright Meritoo
+ *
+ * @internal
+ * @covers \Meritoo\Common\Exception\Regex\InvalidHtmlAttributesException
*/
class InvalidHtmlAttributesExceptionTest extends BaseTestCase
{
- public function testConstructorVisibilityAndArguments()
+ /**
+ * Provides html attributes
+ *
+ * @return Generator
+ */
+ public function provideHtmlAttributes()
{
- static::assertConstructorVisibilityAndArguments(InvalidHtmlAttributesException::class, OopVisibilityType::IS_PUBLIC, 3);
+ $template = 'HTML attributes \'%s\' are invalid. Is there everything ok?';
+
+ yield [
+ 'abc = def',
+ sprintf($template, 'abc = def'),
+ ];
+
+ yield [
+ 'abc = def ghi = jkl',
+ sprintf($template, 'abc = def ghi = jkl'),
+ ];
+
+ yield [
+ 'abc=def ghi=jkl',
+ sprintf($template, 'abc=def ghi=jkl'),
+ ];
}
/**
@@ -38,28 +61,8 @@ class InvalidHtmlAttributesExceptionTest extends BaseTestCase
static::assertSame($expectedMessage, $exception->getMessage());
}
- /**
- * Provides html attributes
- *
- * @return Generator
- */
- public function provideHtmlAttributes()
+ public function testConstructorVisibilityAndArguments()
{
- $template = 'HTML attributes \'%s\' are invalid. Is there everything ok?';
-
- yield[
- 'abc = def',
- sprintf($template, 'abc = def'),
- ];
-
- yield[
- 'abc = def ghi = jkl',
- sprintf($template, 'abc = def ghi = jkl'),
- ];
-
- yield[
- 'abc=def ghi=jkl',
- sprintf($template, 'abc=def ghi=jkl'),
- ];
+ static::assertConstructorVisibilityAndArguments(InvalidHtmlAttributesException::class, OopVisibilityType::IS_PUBLIC, 3);
}
}
diff --git a/tests/Exception/Regex/InvalidUrlExceptionTest.php b/tests/Exception/Regex/InvalidUrlExceptionTest.php
index 0e36d77..cee47d9 100644
--- a/tests/Exception/Regex/InvalidUrlExceptionTest.php
+++ b/tests/Exception/Regex/InvalidUrlExceptionTest.php
@@ -18,12 +18,30 @@ use Meritoo\Common\Type\OopVisibilityType;
*
* @author Meritoo
* @copyright Meritoo
+ *
+ * @internal
+ * @covers \Meritoo\Common\Exception\Regex\InvalidUrlException
*/
class InvalidUrlExceptionTest extends BaseTestCase
{
- public function testConstructorVisibilityAndArguments()
+ /**
+ * Provides invalid url and expected exception's message
+ *
+ * @return Generator
+ */
+ public function provideUrl()
{
- static::assertConstructorVisibilityAndArguments(InvalidUrlException::class, OopVisibilityType::IS_PUBLIC, 3);
+ $template = 'Url \'%s\' is invalid. Is there everything ok?';
+
+ yield [
+ 'aa/bb/cc',
+ sprintf($template, 'aa/bb/cc'),
+ ];
+
+ yield [
+ 'http:/images\show\car.jpg',
+ sprintf($template, 'http:/images\show\car.jpg'),
+ ];
}
/**
@@ -38,23 +56,8 @@ class InvalidUrlExceptionTest extends BaseTestCase
static::assertSame($expectedMessage, $exception->getMessage());
}
- /**
- * Provides invalid url and expected exception's message
- *
- * @return Generator
- */
- public function provideUrl()
+ public function testConstructorVisibilityAndArguments()
{
- $template = 'Url \'%s\' is invalid. Is there everything ok?';
-
- yield[
- 'aa/bb/cc',
- sprintf($template, 'aa/bb/cc'),
- ];
-
- yield[
- 'http:/images\show\car.jpg',
- sprintf($template, 'http:/images\show\car.jpg'),
- ];
+ static::assertConstructorVisibilityAndArguments(InvalidUrlException::class, OopVisibilityType::IS_PUBLIC, 3);
}
}
diff --git a/tests/Exception/Type/UnknownOopVisibilityTypeExceptionTest.php b/tests/Exception/Type/UnknownOopVisibilityTypeExceptionTest.php
index 3f8377b..fb71f5b 100644
--- a/tests/Exception/Type/UnknownOopVisibilityTypeExceptionTest.php
+++ b/tests/Exception/Type/UnknownOopVisibilityTypeExceptionTest.php
@@ -19,12 +19,33 @@ use Meritoo\Common\Type\OopVisibilityType;
*
* @author Meritoo
* @copyright Meritoo
+ *
+ * @internal
+ * @covers \Meritoo\Common\Exception\Type\UnknownOopVisibilityTypeException
*/
class UnknownOopVisibilityTypeExceptionTest extends BaseTestCase
{
- public function testConstructorVisibilityAndArguments()
+ /**
+ * Provides path of the empty file and expected exception's message
+ *
+ * @return Generator
+ */
+ public function provideUnknownType(): Generator
{
- static::assertConstructorVisibilityAndArguments(UnknownOopVisibilityTypeException::class, OopVisibilityType::IS_PUBLIC, 3);
+ $allTypes = (new OopVisibilityType())->getAll();
+
+ $template = 'The \'%s\' type of OOP-related visibility is unknown. Probably doesn\'t exist or there is a typo.'
+ .' You should use one of these types: %s.';
+
+ yield [
+ '',
+ sprintf($template, '', implode(', ', $allTypes)),
+ ];
+
+ yield [
+ 123,
+ sprintf($template, 123, implode(', ', $allTypes)),
+ ];
}
/**
@@ -33,32 +54,18 @@ class UnknownOopVisibilityTypeExceptionTest extends BaseTestCase
*
* @dataProvider provideUnknownType
*/
- public function testConstructorMessage($unknownType, $expectedMessage)
+ public function testConstructorMessage($unknownType, $expectedMessage): void
{
$exception = UnknownOopVisibilityTypeException::createException($unknownType);
static::assertSame($expectedMessage, $exception->getMessage());
}
- /**
- * Provides path of the empty file and expected exception's message
- *
- * @return Generator
- */
- public function provideUnknownType()
+ public function testConstructorVisibilityAndArguments(): void
{
- $allTypes = (new OopVisibilityType())->getAll();
-
- $template = 'The \'%s\' type of OOP-related visibility is unknown. Probably doesn\'t exist or there is a typo.'
- . ' You should use one of these types: %s.';
-
- yield[
- '',
- sprintf($template, '', implode(', ', $allTypes)),
- ];
-
- yield[
- 123,
- sprintf($template, 123, implode(', ', $allTypes)),
- ];
+ static::assertConstructorVisibilityAndArguments(
+ UnknownOopVisibilityTypeException::class,
+ OopVisibilityType::IS_PUBLIC,
+ 3
+ );
}
}
diff --git a/tests/Exception/ValueObject/InvalidSizeDimensionsExceptionTest.php b/tests/Exception/ValueObject/InvalidSizeDimensionsExceptionTest.php
index ece3449..6487c98 100644
--- a/tests/Exception/ValueObject/InvalidSizeDimensionsExceptionTest.php
+++ b/tests/Exception/ValueObject/InvalidSizeDimensionsExceptionTest.php
@@ -17,9 +17,35 @@ use Meritoo\Common\Type\OopVisibilityType;
*
* @author Meritoo
* @copyright Meritoo
+ *
+ * @internal
+ * @covers \Meritoo\Common\Exception\ValueObject\InvalidSizeDimensionsException
*/
class InvalidSizeDimensionsExceptionTest extends BaseTestCase
{
+ public function provideWidthAndHeight()
+ {
+ $template = 'Dimensions of size should be positive, but they are not: %d, %d. Is there everything ok?';
+
+ yield [
+ 0,
+ 0,
+ sprintf($template, 0, 0),
+ ];
+
+ yield [
+ -1,
+ -1,
+ sprintf($template, -1, -1),
+ ];
+
+ yield [
+ 200,
+ 100,
+ sprintf($template, 200, 100),
+ ];
+ }
+
public function testConstructorVisibilityAndArguments()
{
static::assertConstructorVisibilityAndArguments(
@@ -41,27 +67,4 @@ class InvalidSizeDimensionsExceptionTest extends BaseTestCase
$exception = InvalidSizeDimensionsException::create($width, $height);
static::assertSame($expectedMessage, $exception->getMessage());
}
-
- public function provideWidthAndHeight()
- {
- $template = 'Dimensions of size should be positive, but they are not: %d, %d. Is there everything ok?';
-
- yield[
- 0,
- 0,
- sprintf($template, 0, 0),
- ];
-
- yield[
- -1,
- -1,
- sprintf($template, -1, -1),
- ];
-
- yield[
- 200,
- 100,
- sprintf($template, 200, 100),
- ];
- }
}
diff --git a/tests/Exception/ValueObject/Template/InvalidContentExceptionTest.php b/tests/Exception/ValueObject/Template/InvalidContentExceptionTest.php
new file mode 100644
index 0000000..6392407
--- /dev/null
+++ b/tests/Exception/ValueObject/Template/InvalidContentExceptionTest.php
@@ -0,0 +1,71 @@
+
+ * @copyright Meritoo
+ *
+ * @internal
+ * @covers \Meritoo\Common\Exception\ValueObject\Template\InvalidContentException
+ */
+class InvalidContentExceptionTest extends BaseTestCase
+{
+ public function provideContent(): ?Generator
+ {
+ $template = 'Content of template \'%s\' is invalid. Did you use string with 1 placeholder at least?';
+
+ yield [
+ 'An empty string',
+ '',
+ sprintf($template, ''),
+ ];
+
+ yield [
+ 'Simple string',
+ 'Lorem ipsum',
+ sprintf($template, 'Lorem ipsum'),
+ ];
+
+ yield [
+ 'One sentence',
+ 'Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh.',
+ sprintf($template, 'Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh.'),
+ ];
+ }
+
+ public function testConstructorVisibilityAndArguments(): void
+ {
+ static::assertConstructorVisibilityAndArguments(
+ InvalidContentException::class,
+ OopVisibilityType::IS_PUBLIC,
+ 3
+ );
+ }
+
+ /**
+ * @param string $description Description of test
+ * @param string $content Invalid content of template
+ * @param string $expectedMessage Expected exception's message
+ *
+ * @dataProvider provideContent
+ */
+ public function testCreate(string $description, string $content, string $expectedMessage): void
+ {
+ $exception = InvalidContentException::create($content);
+ static::assertSame($expectedMessage, $exception->getMessage(), $description);
+ }
+}
diff --git a/tests/Exception/ValueObject/Template/MissingPlaceholdersInValuesExceptionTest.php b/tests/Exception/ValueObject/Template/MissingPlaceholdersInValuesExceptionTest.php
new file mode 100644
index 0000000..86a6602
--- /dev/null
+++ b/tests/Exception/ValueObject/Template/MissingPlaceholdersInValuesExceptionTest.php
@@ -0,0 +1,86 @@
+
+ * @copyright Meritoo
+ *
+ * @internal
+ * @covers \Meritoo\Common\Exception\ValueObject\Template\MissingPlaceholdersInValuesException
+ */
+class MissingPlaceholdersInValuesExceptionTest extends BaseTestCase
+{
+ public function provideContentAndMissingPlaceholders(): ?Generator
+ {
+ $template = 'Cannot fill template \'%s\', because of missing values for placeholder(s): %s. Did you provide all'
+ .' required values?';
+
+ yield [
+ 'Missing 2nd placeholder',
+ '%test1% - %test2%',
+ [
+ 'test2',
+ ],
+ sprintf(
+ $template,
+ '%test1% - %test2%',
+ 'test2'
+ ),
+ ];
+
+ yield [
+ 'Missing 2nd and 3rd placeholder',
+ '%test1% / %test2% / %test3%',
+ [
+ 'test2',
+ 'test3',
+ ],
+ sprintf(
+ $template,
+ '%test1% / %test2% / %test3%',
+ 'test2, test3'
+ ),
+ ];
+ }
+
+ public function testConstructorVisibilityAndArguments(): void
+ {
+ static::assertConstructorVisibilityAndArguments(
+ MissingPlaceholdersInValuesException::class,
+ OopVisibilityType::IS_PUBLIC,
+ 3
+ );
+ }
+
+ /**
+ * @param string $description Description of test
+ * @param string $content Content of template
+ * @param array $missingPlaceholders Missing placeholders in provided values, iow. placeholders without values
+ * @param string $expectedMessage Expected exception's message
+ *
+ * @dataProvider provideContentAndMissingPlaceholders
+ */
+ public function testCreate(
+ string $description,
+ string $content,
+ array $missingPlaceholders,
+ string $expectedMessage
+ ): void {
+ $exception = MissingPlaceholdersInValuesException::create($content, $missingPlaceholders);
+ static::assertSame($expectedMessage, $exception->getMessage(), $description);
+ }
+}
diff --git a/tests/Exception/ValueObject/Template/TemplateNotFoundExceptionTest.php b/tests/Exception/ValueObject/Template/TemplateNotFoundExceptionTest.php
new file mode 100644
index 0000000..4616f7a
--- /dev/null
+++ b/tests/Exception/ValueObject/Template/TemplateNotFoundExceptionTest.php
@@ -0,0 +1,71 @@
+
+ * @copyright Meritoo
+ *
+ * @internal
+ * @covers \Meritoo\Common\Exception\ValueObject\Template\TemplateNotFoundException
+ */
+class TemplateNotFoundExceptionTest extends BaseTestCase
+{
+ public function provideIndexAndException(): ?Generator
+ {
+ $template = 'Template with \'%s\' index was not found. Did you provide all required templates?';
+
+ yield [
+ 'An empty string',
+ '',
+ new TemplateNotFoundException(sprintf($template, '')),
+ ];
+
+ yield [
+ 'Non-empty string',
+ 'test',
+ new TemplateNotFoundException(sprintf($template, 'test')),
+ ];
+
+ yield [
+ 'Integer',
+ '2',
+ new TemplateNotFoundException(sprintf($template, 2)),
+ ];
+ }
+
+ public function testConstructor(): void
+ {
+ static::assertConstructorVisibilityAndArguments(
+ TemplateNotFoundException::class,
+ OopVisibilityType::IS_PUBLIC,
+ 3
+ );
+ }
+
+ /**
+ * @param string $description Description of test
+ * @param string $index Index that should contain template, but it was not found
+ * @param TemplateNotFoundException $expected Expected exception
+ *
+ * @dataProvider provideIndexAndException
+ */
+ public function testCreate(string $description, string $index, TemplateNotFoundException $expected): void
+ {
+ $created = TemplateNotFoundException::create($index);
+ static::assertEquals($expected, $created, $description);
+ }
+}
diff --git a/tests/Test/Base/BaseTestCaseTest.php b/tests/Test/Base/BaseTestCaseTest.php
index 71dc496..83c2308 100644
--- a/tests/Test/Base/BaseTestCaseTest.php
+++ b/tests/Test/Base/BaseTestCaseTest.php
@@ -19,27 +19,61 @@ use Meritoo\Common\Utilities\GeneratorUtility;
*
* @author Meritoo
* @copyright Meritoo
+ *
+ * @internal
+ * @covers \Meritoo\Common\Test\Base\BaseTestCase
*/
class BaseTestCaseTest extends BaseTestCase
{
+ /**
+ * Provides name of file and path of directory containing the file
+ *
+ * @return Generator
+ */
+ public function provideFileNameAndDirectoryPath()
+ {
+ yield [
+ 'abc.jpg',
+ '',
+ ];
+
+ yield [
+ 'abc.def.jpg',
+ '',
+ ];
+
+ yield [
+ 'abc.jpg',
+ 'def',
+ ];
+
+ yield [
+ 'abc.def.jpg',
+ 'def',
+ ];
+ }
+
public function testConstructor()
{
static::assertConstructorVisibilityAndArguments(BaseTestCase::class, OopVisibilityType::IS_PUBLIC, 3);
}
- public function testProvideEmptyValue()
+ /**
+ * @param string $fileName Name of file
+ * @param string $directoryPath Path of directory containing the file
+ *
+ * @dataProvider provideFileNameAndDirectoryPath
+ */
+ public function testGetFilePathForTesting($fileName, $directoryPath)
{
- $elements = [
- [''],
- [' '],
- [null],
- [0],
- [false],
- [[]],
- ];
+ $path = (new SimpleTestCase())->getFilePathForTesting($fileName, $directoryPath);
- $generator = (new SimpleTestCase())->provideEmptyValue();
- self::assertEquals($elements, GeneratorUtility::getGeneratorElements($generator));
+ if (!empty($directoryPath)) {
+ $directoryPath .= '/';
+ }
+
+ $expectedContains = sprintf('/data/tests/%s%s', $directoryPath, $fileName);
+ static::assertStringContainsString($expectedContains, $path);
}
public function testProvideBooleanValue()
@@ -67,16 +101,16 @@ class BaseTestCaseTest extends BaseTestCase
$generator = (new SimpleTestCase())->provideDateTimeInstance();
$generatedElements = GeneratorUtility::getGeneratorElements($generator);
- /* @var DateTime $instance1 */
+ /** @var DateTime $instance1 */
$instance1 = $generatedElements[0][0];
- /* @var DateTime $instance2 */
+ /** @var DateTime $instance2 */
$instance2 = $generatedElements[1][0];
- /* @var DateTime $instance3 */
+ /** @var DateTime $instance3 */
$instance3 = $generatedElements[2][0];
- /* @var DateTime $instance4 */
+ /** @var DateTime $instance4 */
$instance4 = $generatedElements[3][0];
self::assertCount(count($expectedElements), $generatedElements);
@@ -106,6 +140,21 @@ class BaseTestCaseTest extends BaseTestCase
self::assertEquals($elements, GeneratorUtility::getGeneratorElements($generator));
}
+ public function testProvideEmptyValue()
+ {
+ $elements = [
+ [''],
+ [' '],
+ [null],
+ [0],
+ [false],
+ [[]],
+ ];
+
+ $generator = (new SimpleTestCase())->provideEmptyValue();
+ self::assertEquals($elements, GeneratorUtility::getGeneratorElements($generator));
+ }
+
public function testProvideNotExistingFilePath()
{
$elements = [
@@ -117,52 +166,6 @@ class BaseTestCaseTest extends BaseTestCase
$generator = (new SimpleTestCase())->provideNotExistingFilePath();
self::assertEquals($elements, GeneratorUtility::getGeneratorElements($generator));
}
-
- /**
- * @param string $fileName Name of file
- * @param string $directoryPath Path of directory containing the file
- *
- * @dataProvider provideFileNameAndDirectoryPath
- */
- public function testGetFilePathForTesting($fileName, $directoryPath)
- {
- $path = (new SimpleTestCase())->getFilePathForTesting($fileName, $directoryPath);
-
- if (!empty($directoryPath)) {
- $directoryPath .= '/';
- }
-
- $expectedContains = sprintf('/data/tests/%s%s', $directoryPath, $fileName);
- static::assertContains($expectedContains, $path);
- }
-
- /**
- * Provides name of file and path of directory containing the file
- *
- * @return Generator
- */
- public function provideFileNameAndDirectoryPath()
- {
- yield[
- 'abc.jpg',
- '',
- ];
-
- yield[
- 'abc.def.jpg',
- '',
- ];
-
- yield[
- 'abc.jpg',
- 'def',
- ];
-
- yield[
- 'abc.def.jpg',
- 'def',
- ];
- }
}
/**
@@ -170,6 +173,9 @@ class BaseTestCaseTest extends BaseTestCase
*
* @author Meritoo
* @copyright Meritoo
+ *
+ * @internal
+ * @coversNothing
*/
class SimpleTestCase extends BaseTestCase
{
diff --git a/tests/Traits/Test/Base/BaseTestCaseTrait/SimpleTestCase.php b/tests/Traits/Test/Base/BaseTestCaseTrait/SimpleTestCase.php
new file mode 100644
index 0000000..02258b6
--- /dev/null
+++ b/tests/Traits/Test/Base/BaseTestCaseTrait/SimpleTestCase.php
@@ -0,0 +1,26 @@
+
+ * @copyright Meritoo
+ *
+ * @internal
+ * @covers \Meritoo\Common\Traits\Test\Base\BaseTestCaseTrait
+ */
+class BaseTestCaseTraitTest extends BaseTestCase
+{
+ use BaseTestCaseTrait;
+
+ public function testAssertConstructorVisibilityAndArgumentsUsingClassWithoutConstructor(): void
+ {
+ $this->expectException(ClassWithoutConstructorException::class);
+ static::assertConstructorVisibilityAndArguments(SimpleTestCase::class, OopVisibilityType::IS_PUBLIC);
+ }
+
+ public function testAssertHasNoConstructor(): void
+ {
+ static::assertHasNoConstructor(SimpleTestCase::class);
+ }
+
+ public function testAssertMethodVisibility(): void
+ {
+ $method = new ReflectionMethod(SimpleTestCase::class, 'assertMethodVisibility');
+ static::assertMethodVisibility($method, OopVisibilityType::IS_PROTECTED);
+ }
+
+ public function testAssertMethodVisibilityUsingIncorrectVisibility(): void
+ {
+ $this->expectException(UnknownOopVisibilityTypeException::class);
+
+ $method = new ReflectionMethod(SimpleTestCase::class, 'assertMethodVisibility');
+ static::assertMethodVisibility($method, '4');
+ }
+
+ public function testAssertMethodVisibilityUsingPrivate(): void
+ {
+ $method = new ReflectionMethod(SimpleTestCase::class, 'thePrivateMethod');
+ static::assertMethodVisibility($method, OopVisibilityType::IS_PRIVATE);
+ }
+
+ public function testProvideBooleanValue(): void
+ {
+ $testCase = new SimpleTestCase();
+ $values = $testCase->provideBooleanValue();
+
+ $expected = [
+ [false],
+ [true],
+ ];
+
+ foreach ($values as $index => $value) {
+ static::assertSame($expected[$index], $value);
+ }
+ }
+
+ public function testProvideDateTimeInstance(): void
+ {
+ $testCase = new SimpleTestCase();
+ $instances = $testCase->provideDateTimeInstance();
+
+ $expected = [
+ [new DateTime()],
+ [new DateTime('yesterday')],
+ [new DateTime('now')],
+ [new DateTime('tomorrow')],
+ ];
+
+ foreach ($instances as $index => $instance) {
+ /** @var DateTime $expectedInstance */
+ $expectedInstance = $expected[$index][0];
+
+ /** @var DateTime $instance */
+ $instance = $instance[0];
+
+ static::assertInstanceOf(DateTime::class, $instance);
+ static::assertEquals($expectedInstance->getTimestamp(), $instance->getTimestamp());
+ }
+ }
+
+ public function testProvideDateTimeRelativeFormatInstance(): void
+ {
+ $testCase = new SimpleTestCase();
+ $formats = $testCase->provideDateTimeRelativeFormat();
+
+ $expected = [
+ ['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'],
+ ];
+
+ foreach ($formats as $index => $format) {
+ static::assertSame($expected[$index], $format);
+ }
+ }
+
+ public function testProvideEmptyScalarValue(): void
+ {
+ $testCase = new SimpleTestCase();
+ $values = $testCase->provideEmptyScalarValue();
+
+ $expected = [
+ [''],
+ [' '],
+ [null],
+ [0],
+ [false],
+ ];
+
+ foreach ($values as $index => $value) {
+ static::assertSame($expected[$index], $value);
+ }
+ }
+
+ public function testProvideEmptyValue(): void
+ {
+ $testCase = new SimpleTestCase();
+ $values = $testCase->provideEmptyValue();
+
+ $expected = [
+ [''],
+ [' '],
+ [null],
+ [0],
+ [false],
+ [[]],
+ ];
+
+ foreach ($values as $index => $value) {
+ static::assertSame($expected[$index], $value);
+ }
+ }
+
+ public function testProvideNonScalarValue(): void
+ {
+ $testCase = new SimpleTestCase();
+ $values = $testCase->provideNonScalarValue();
+
+ $expected = [
+ [[]],
+ [null],
+ [new stdClass()],
+ ];
+
+ foreach ($values as $index => $value) {
+ static::assertEquals($expected[$index], $value);
+ }
+ }
+
+ public function testProvideNotExistingFilePath(): void
+ {
+ $testCase = new SimpleTestCase();
+ $paths = $testCase->provideNotExistingFilePath();
+
+ $expected = [
+ ['lets-test.doc'],
+ ['lorem/ipsum.jpg'],
+ ['surprise/me/one/more/time.txt'],
+ ];
+
+ foreach ($paths as $index => $path) {
+ static::assertSame($expected[$index], $path);
+ }
+ }
+}
diff --git a/tests/Type/Base/BaseTypeTest.php b/tests/Type/Base/BaseTypeTest.php
index f21a1dc..bf43078 100644
--- a/tests/Type/Base/BaseTypeTest.php
+++ b/tests/Type/Base/BaseTypeTest.php
@@ -17,51 +17,25 @@ use Meritoo\Common\Type\Base\BaseType;
*
* @author Meritoo
* @copyright Meritoo
+ *
+ * @internal
+ * @covers \Meritoo\Common\Type\Base\BaseType
*/
class BaseTypeTest extends BaseTestCase
{
- public function testConstructor()
- {
- static::assertHasNoConstructor(BaseType::class);
- }
-
- /**
- * @param BaseType $type Type of something
- * @param array $expectedTypes Expected concrete types of given instance of type
- *
- * @dataProvider provideType
- */
- public function testGetAll(BaseType $type, array $expectedTypes)
- {
- $all = $type->getAll();
- self::assertEquals($expectedTypes, $all);
- }
-
- /**
- * @param BaseType $type Type of something
- * @param string $toVerifyType Concrete type to verify (of given instance of type)
- * @param bool $isCorrect Expected information if given type is correct
- *
- * @dataProvider provideTypeWithConcreteType
- */
- public function testIsCorrectType(BaseType $type, $toVerifyType, $isCorrect)
- {
- self::assertEquals($isCorrect, $type->isCorrectType($toVerifyType));
- }
-
/**
* Provides type of something for testing the getAll() method
*
* @return Generator
*/
- public function provideType()
+ public function provideType(): ?Generator
{
- yield[
+ yield [
new TestEmptyType(),
[],
];
- yield[
+ yield [
new TestType(),
[
'TEST_1' => TestType::TEST_1,
@@ -75,110 +49,150 @@ class BaseTypeTest extends BaseTestCase
*
* @return Generator
*/
- public function provideTypeWithConcreteType()
+ public function provideTypeToVerifyUsingTestEmptyType(): ?Generator
{
- yield[
- new TestEmptyType(),
+ yield [
null,
false,
];
- yield[
- new TestEmptyType(),
- false,
+ yield [
+ 'null',
false,
];
- yield[
- new TestEmptyType(),
- true,
+ yield [
+ 'false',
false,
];
- yield[
- new TestEmptyType(),
+ yield [
+ 'true',
+ false,
+ ];
+
+ yield [
'',
false,
];
- yield[
- new TestEmptyType(),
- 0,
+ yield [
+ '0',
false,
];
- yield[
- new TestEmptyType(),
- 1,
+ yield [
+ '1',
false,
];
- yield[
- new TestEmptyType(),
+ yield [
'lorem',
false,
];
+ }
- yield[
- new TestType(),
+ /**
+ * Provides type of something for testing the isCorrectType() method
+ *
+ * @return Generator
+ */
+ public function provideTypeToVerifyUsingTestType(): ?Generator
+ {
+ yield [
null,
false,
];
- yield[
- new TestType(),
- false,
+ yield [
+ 'null',
false,
];
- yield[
- new TestType(),
- true,
+ yield [
+ 'false',
false,
];
- yield[
- new TestType(),
+ yield [
+ 'true',
+ false,
+ ];
+
+ yield [
'',
false,
];
- yield[
- new TestType(),
- 0,
+ yield [
+ '0',
false,
];
- yield[
- new TestType(),
- 1,
+ yield [
+ '1',
false,
];
- yield[
- new TestType(),
+ yield [
'lorem',
false,
];
- yield[
- new TestType(),
+ yield [
'test',
false,
];
- yield[
- new TestType(),
- TestType::TEST_1,
+ yield [
+ 'test_1',
true,
];
- yield[
- new TestType(),
- TestType::TEST_2,
+ yield [
+ 'test_2',
true,
];
}
+
+ public function testConstructor(): void
+ {
+ static::assertHasNoConstructor(BaseType::class);
+ }
+
+ /**
+ * @param BaseType $type Type of something
+ * @param array $expectedTypes Expected concrete types of given instance of type
+ *
+ * @dataProvider provideType
+ */
+ public function testGetAll(BaseType $type, array $expectedTypes): void
+ {
+ $all = $type->getAll();
+ self::assertEquals($expectedTypes, $all);
+ }
+
+ /**
+ * @param string $toVerifyType Concrete type to verify
+ * @param bool $isCorrect Expected information if given type is correct
+ *
+ * @dataProvider provideTypeToVerifyUsingTestEmptyType
+ */
+ public function testIsCorrectTypeUsingTestEmptyType(?string $toVerifyType, bool $isCorrect): void
+ {
+ self::assertEquals($isCorrect, TestEmptyType::isCorrectType($toVerifyType));
+ }
+
+ /**
+ * @param string $toVerifyType Concrete type to verify
+ * @param bool $isCorrect Expected information if given type is correct
+ *
+ * @dataProvider provideTypeToVerifyUsingTestType
+ */
+ public function testIsCorrectTypeUsingTestType(?string $toVerifyType, bool $isCorrect): void
+ {
+ self::assertEquals($isCorrect, TestType::isCorrectType($toVerifyType));
+ }
}
/**
@@ -199,7 +213,7 @@ class TestEmptyType extends BaseType
*/
class TestType extends BaseType
{
- const TEST_1 = 'test_1';
+ public const TEST_1 = 'test_1';
- const TEST_2 = 'test_2';
+ public const TEST_2 = 'test_2';
}
diff --git a/tests/Type/DatePartTypeTest.php b/tests/Type/DatePartTypeTest.php
index 782c259..5a24fe1 100644
--- a/tests/Type/DatePartTypeTest.php
+++ b/tests/Type/DatePartTypeTest.php
@@ -8,7 +8,9 @@
namespace Meritoo\Test\Common\Type;
+use Generator;
use Meritoo\Common\Test\Base\BaseTypeTestCase;
+use Meritoo\Common\Type\Base\BaseType;
use Meritoo\Common\Type\DatePartType;
/**
@@ -16,61 +18,64 @@ use Meritoo\Common\Type\DatePartType;
*
* @author Meritoo
* @copyright Meritoo
+ *
+ * @internal
+ * @covers \Meritoo\Common\Type\DatePartType
*/
class DatePartTypeTest extends BaseTypeTestCase
{
/**
* {@inheritdoc}
*/
- public function provideTypeToVerify()
+ public function provideTypeToVerify(): Generator
{
- yield[
- '',
+ yield [
+ DatePartType::isCorrectType(''),
false,
];
- yield[
- null,
+ yield [
+ DatePartType::isCorrectType(null),
false,
];
- yield[
- 0,
+ yield [
+ DatePartType::isCorrectType('0'),
false,
];
- yield[
- 1,
+ yield [
+ DatePartType::isCorrectType('1'),
false,
];
- yield[
- 'day',
+ yield [
+ DatePartType::isCorrectType('day'),
true,
];
- yield[
- 'hour',
+ yield [
+ DatePartType::isCorrectType('hour'),
true,
];
- yield[
- 'minute',
+ yield [
+ DatePartType::isCorrectType('minute'),
true,
];
- yield[
- 'month',
+ yield [
+ DatePartType::isCorrectType('month'),
true,
];
- yield[
- 'second',
+ yield [
+ DatePartType::isCorrectType('second'),
true,
];
- yield[
- 'year',
+ yield [
+ DatePartType::isCorrectType('year'),
true,
];
}
@@ -78,22 +83,22 @@ class DatePartTypeTest extends BaseTypeTestCase
/**
* {@inheritdoc}
*/
- protected function getAllExpectedTypes()
+ protected function getAllExpectedTypes(): array
{
return [
- 'DAY' => DatePartType::DAY,
- 'HOUR' => DatePartType::HOUR,
- 'MINUTE' => DatePartType::MINUTE,
- 'MONTH' => DatePartType::MONTH,
- 'SECOND' => DatePartType::SECOND,
- 'YEAR' => DatePartType::YEAR,
+ 'DAY' => 'day',
+ 'HOUR' => 'hour',
+ 'MINUTE' => 'minute',
+ 'MONTH' => 'month',
+ 'SECOND' => 'second',
+ 'YEAR' => 'year',
];
}
/**
* {@inheritdoc}
*/
- protected function getTestedTypeInstance()
+ protected function getTestedTypeInstance(): BaseType
{
return new DatePartType();
}
diff --git a/tests/Type/DatePeriodTest.php b/tests/Type/DatePeriodTest.php
index a73ceaf..a45bb3d 100644
--- a/tests/Type/DatePeriodTest.php
+++ b/tests/Type/DatePeriodTest.php
@@ -11,6 +11,7 @@ namespace Meritoo\Test\Common\Type;
use DateTime;
use Generator;
use Meritoo\Common\Test\Base\BaseTypeTestCase;
+use Meritoo\Common\Type\Base\BaseType;
use Meritoo\Common\Type\DatePeriod;
use Meritoo\Common\Type\OopVisibilityType;
@@ -19,12 +20,228 @@ use Meritoo\Common\Type\OopVisibilityType;
*
* @author Meritoo
* @copyright Meritoo
+ *
+ * @internal
+ * @covers \Meritoo\Common\Type\DatePeriod
*/
class DatePeriodTest extends BaseTypeTestCase
{
- public function testConstructorVisibilityAndArguments()
+ /**
+ * Provides the start and end date of date period
+ *
+ * @return Generator
+ */
+ public function provideDatePeriod(): Generator
{
- static::assertConstructorVisibilityAndArguments(DatePeriod::class, OopVisibilityType::IS_PUBLIC, 2, 0);
+ $startDate = new DateTime('2001-01-01');
+ $endDate = new DateTime('2002-02-02');
+
+ yield [
+ null,
+ null,
+ ];
+
+ yield [
+ $startDate,
+ $startDate,
+ null,
+ ];
+
+ yield [
+ null,
+ null,
+ $endDate,
+ ];
+
+ yield [
+ $startDate,
+ $endDate,
+ ];
+ }
+
+ /**
+ * Provides period and format of date to verify
+ *
+ * @return Generator
+ */
+ public function provideDatePeriodAndDateFormat(): Generator
+ {
+ $startDate = new DateTime('2001-01-01');
+ $endDate = new DateTime('2002-02-02');
+
+ // For start date
+ yield [
+ new DatePeriod($startDate, $endDate),
+ 'Y',
+ true,
+ '2001',
+ ];
+
+ yield [
+ new DatePeriod($startDate, $endDate),
+ 'D',
+ true,
+ 'Mon',
+ ];
+
+ yield [
+ new DatePeriod($startDate, $endDate),
+ 'Y-m-d',
+ true,
+ '2001-01-01',
+ ];
+
+ yield [
+ new DatePeriod($startDate, $endDate),
+ 'Y-m-d H:i',
+ true,
+ '2001-01-01 00:00',
+ ];
+
+ // For end date
+ yield [
+ new DatePeriod($startDate, $endDate),
+ 'Y',
+ false,
+ '2002',
+ ];
+
+ yield [
+ new DatePeriod($startDate, $endDate),
+ 'D',
+ false,
+ 'Sat',
+ ];
+
+ yield [
+ new DatePeriod($startDate, $endDate),
+ 'Y-m-d',
+ false,
+ '2002-02-02',
+ ];
+
+ yield [
+ new DatePeriod($startDate, $endDate),
+ 'Y-m-d H:i',
+ false,
+ '2002-02-02 00:00',
+ ];
+ }
+
+ /**
+ * Provides period and format of date to verify using the start date
+ *
+ * @return Generator
+ */
+ public function provideDatePeriodAndDateFormatUsingStartDateOnly(): Generator
+ {
+ $startDate = new DateTime('2001-01-01');
+ $endDate = new DateTime('2002-02-02');
+
+ yield [
+ new DatePeriod($startDate, $endDate),
+ 'Y',
+ '2001',
+ ];
+
+ yield [
+ new DatePeriod($startDate, $endDate),
+ 'D',
+ 'Mon',
+ ];
+
+ yield [
+ new DatePeriod($startDate, $endDate),
+ 'Y-m-d',
+ '2001-01-01',
+ ];
+
+ yield [
+ new DatePeriod($startDate, $endDate),
+ 'Y-m-d H:i',
+ '2001-01-01 00:00',
+ ];
+ }
+
+ /**
+ * Provides period and incorrect format of date to verify
+ *
+ * @return Generator
+ */
+ public function provideDatePeriodAndIncorrectDateFormat(): Generator
+ {
+ $startDate = new DateTime('2001-01-01');
+ $endDate = new DateTime('2002-02-02');
+
+ yield [
+ new DatePeriod($startDate, $endDate),
+ '',
+ ];
+
+ yield [
+ new DatePeriod($startDate, $endDate),
+ false,
+ ];
+ }
+
+ public function provideDatePeriodAndUnknownDate(): ?Generator
+ {
+ $date = new DateTime('2001-01-01');
+
+ yield [
+ new DatePeriod(),
+ 'Y-m-d',
+ false,
+ ];
+
+ yield [
+ new DatePeriod(),
+ 'Y-m-d',
+ true,
+ ];
+
+ yield [
+ new DatePeriod($date),
+ 'Y-m-d',
+ false,
+ ];
+
+ yield [
+ new DatePeriod(null, $date),
+ 'Y-m-d',
+ true,
+ ];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function provideTypeToVerify(): Generator
+ {
+ yield [
+ DatePeriod::isCorrectType(''),
+ false,
+ ];
+
+ yield [
+ DatePeriod::isCorrectType('-1'),
+ false,
+ ];
+
+ yield [
+ DatePeriod::isCorrectType('4'),
+ true,
+ ];
+
+ yield [
+ DatePeriod::isCorrectType('3'),
+ true,
+ ];
+
+ yield [
+ DatePeriod::isCorrectType('8'),
+ true,
+ ];
}
/**
@@ -33,7 +250,7 @@ class DatePeriodTest extends BaseTypeTestCase
*
* @dataProvider provideDatePeriod
*/
- public function testConstruct(DateTime $startDate = null, DateTime $endDate = null)
+ public function testConstruct(DateTime $startDate = null, DateTime $endDate = null): void
{
$period = new DatePeriod($startDate, $endDate);
@@ -41,13 +258,70 @@ class DatePeriodTest extends BaseTypeTestCase
self::assertEquals($endDate, $period->getEndDate());
}
+ public function testConstructorVisibilityAndArguments(): void
+ {
+ static::assertConstructorVisibilityAndArguments(
+ DatePeriod::class,
+ OopVisibilityType::IS_PUBLIC,
+ 2
+ );
+ }
+
+ /**
+ * @param DatePeriod $period The date period to verify
+ * @param string $format Format used to format the date
+ * @param bool $startDate If is set to true, start date is formatted. Otherwise - end date.
+ * @param string $expected Expected, formatted date
+ *
+ * @dataProvider provideDatePeriodAndDateFormat
+ */
+ public function testGetFormattedDate(DatePeriod $period, $format, $startDate, $expected): void
+ {
+ self::assertEquals($expected, $period->getFormattedDate($format, $startDate));
+ }
+
+ /**
+ * @param DatePeriod $period The date period to verify
+ * @param string $format Format used to format the date
+ *
+ * @dataProvider provideDatePeriodAndIncorrectDateFormat
+ */
+ public function testGetFormattedDateUsingIncorrectDateFormat(DatePeriod $period, $format): void
+ {
+ self::assertEquals('', $period->getFormattedDate($format));
+ }
+
+ /**
+ * @param DatePeriod $period The date period to verify
+ * @param string $format Format used to format the date
+ * @param string $expected Expected, formatted date
+ *
+ * @dataProvider provideDatePeriodAndDateFormatUsingStartDateOnly
+ */
+ public function testGetFormattedDateUsingStartDateOnly(DatePeriod $period, $format, $expected): void
+ {
+ self::assertEquals($expected, $period->getFormattedDate($format));
+ }
+
+ /**
+ * @param DatePeriod $period The date period to verify
+ * @param string $format Format used to format the date
+ * @param bool $startDate If is set to true, start date is formatted. Otherwise - end date.
+ *
+ * @dataProvider provideDatePeriodAndUnknownDate
+ */
+ public function testGetFormattedDateUsingUnknownDate(DatePeriod $period, $format, $startDate): void
+ {
+ self::assertEquals('', $period->getFormattedDate($format, $startDate));
+ }
+
/**
* @param DateTime $startDate (optional) Start date of period
* @param DateTime $endDate (optional) End date of period
*
* @dataProvider provideDatePeriod
*/
- public function testGettersAndSetters(DateTime $startDate = null, DateTime $endDate = null)
+ public function testGettersAndSetters(DateTime $startDate = null, DateTime $endDate = null): void
{
$period = new DatePeriod();
@@ -58,222 +332,30 @@ class DatePeriodTest extends BaseTypeTestCase
self::assertEquals($endDate, $period->getEndDate());
}
- /**
- * @param DatePeriod $period The date period to verify
- * @param string $format Format used to format the date
- *
- * @dataProvider provideDatePeriodAndIncorrectDateFormat
- */
- public function testGetFormattedDateIncorrectDateFormat(DatePeriod $period, $format)
- {
- self::assertEquals('', $period->getFormattedDate($format));
- }
-
- /**
- * @param DatePeriod $period The date period to verify
- * @param string $format Format used to format the date
- * @param bool $startDate If is set to true, start date is formatted. Otherwise - end date.
- * @param string $expected Expected, formatted date
- *
- * @dataProvider provideDatePeriodAndDateFormat
- */
- public function testGetFormattedDate(DatePeriod $period, $format, $startDate, $expected)
- {
- self::assertEquals($expected, $period->getFormattedDate($format, $startDate));
- }
-
- /**
- * Provides the start and end date of date period
- *
- * @return Generator
- */
- public function provideDatePeriod()
- {
- $startDate = new DateTime('2001-01-01');
- $endDate = new DateTime('2002-02-02');
-
- yield[
- null,
- null,
- ];
-
- yield[
- $startDate,
- $startDate,
- null,
- ];
-
- yield[
- null,
- null,
- $endDate,
- ];
-
- yield[
- $startDate,
- $endDate,
- ];
- }
-
- /**
- * Provides period and incorrect format of date to verify
- *
- * @return Generator
- */
- public function provideDatePeriodAndIncorrectDateFormat()
- {
- $startDate = new DateTime('2001-01-01');
- $endDate = new DateTime('2002-02-02');
-
- yield[
- new DatePeriod($startDate, $endDate),
- '',
- ];
-
- yield[
- new DatePeriod($startDate, $endDate),
- null,
- ];
-
- yield[
- new DatePeriod($startDate, $endDate),
- false,
- ];
- }
-
- /**
- * Provides period and format of date to verify
- *
- * @return Generator
- */
- public function provideDatePeriodAndDateFormat()
- {
- $startDate = new DateTime('2001-01-01');
- $endDate = new DateTime('2002-02-02');
-
- /*
- * For start date
- */
- yield[
- new DatePeriod($startDate, $endDate),
- 'Y',
- true,
- '2001',
- ];
-
- yield[
- new DatePeriod($startDate, $endDate),
- 'D',
- true,
- 'Mon',
- ];
-
- yield[
- new DatePeriod($startDate, $endDate),
- 'Y-m-d',
- true,
- '2001-01-01',
- ];
-
- yield[
- new DatePeriod($startDate, $endDate),
- 'Y-m-d H:i',
- true,
- '2001-01-01 00:00',
- ];
-
- /*
- * For end date
- */
- yield[
- new DatePeriod($startDate, $endDate),
- 'Y',
- false,
- '2002',
- ];
-
- yield[
- new DatePeriod($startDate, $endDate),
- 'D',
- false,
- 'Sat',
- ];
-
- yield[
- new DatePeriod($startDate, $endDate),
- 'Y-m-d',
- false,
- '2002-02-02',
- ];
-
- yield[
- new DatePeriod($startDate, $endDate),
- 'Y-m-d H:i',
- false,
- '2002-02-02 00:00',
- ];
- }
-
- /**
- * {@inheritdoc}
- */
- public function provideTypeToVerify()
- {
- yield[
- '',
- false,
- ];
-
- yield[
- -1,
- false,
- ];
-
- yield[
- true,
- false,
- ];
-
- yield[
- DatePeriod::LAST_MONTH,
- true,
- ];
-
- yield[
- DatePeriod::NEXT_WEEK,
- true,
- ];
-
- yield[
- DatePeriod::THIS_YEAR,
- true,
- ];
- }
-
/**
* Returns all expected types of the tested type
*
* @return array
*/
- protected function getAllExpectedTypes()
+ protected function getAllExpectedTypes(): array
{
return [
- 'LAST_MONTH' => DatePeriod::LAST_MONTH,
- 'LAST_WEEK' => DatePeriod::LAST_WEEK,
- 'LAST_YEAR' => DatePeriod::LAST_YEAR,
- 'NEXT_MONTH' => DatePeriod::NEXT_MONTH,
- 'NEXT_WEEK' => DatePeriod::NEXT_WEEK,
- 'NEXT_YEAR' => DatePeriod::NEXT_YEAR,
- 'THIS_MONTH' => DatePeriod::THIS_MONTH,
- 'THIS_WEEK' => DatePeriod::THIS_WEEK,
- 'THIS_YEAR' => DatePeriod::THIS_YEAR,
+ 'LAST_MONTH' => 4,
+ 'LAST_WEEK' => 1,
+ 'LAST_YEAR' => 7,
+ 'NEXT_MONTH' => 6,
+ 'NEXT_WEEK' => 3,
+ 'NEXT_YEAR' => 9,
+ 'THIS_MONTH' => 5,
+ 'THIS_WEEK' => 2,
+ 'THIS_YEAR' => 8,
];
}
/**
* {@inheritdoc}
*/
- protected function getTestedTypeInstance()
+ protected function getTestedTypeInstance(): BaseType
{
return new DatePeriod();
}
diff --git a/tests/Type/OopVisibilityTypeTest.php b/tests/Type/OopVisibilityTypeTest.php
new file mode 100644
index 0000000..cc929c3
--- /dev/null
+++ b/tests/Type/OopVisibilityTypeTest.php
@@ -0,0 +1,82 @@
+
+ * @copyright Meritoo
+ *
+ * @internal
+ * @covers \Meritoo\Common\Type\OopVisibilityType
+ */
+class OopVisibilityTypeTest extends BaseTypeTestCase
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function provideTypeToVerify(): Generator
+ {
+ yield [
+ OopVisibilityType::isCorrectType(''),
+ false,
+ ];
+
+ yield [
+ OopVisibilityType::isCorrectType(null),
+ false,
+ ];
+
+ yield [
+ OopVisibilityType::isCorrectType('-1'),
+ false,
+ ];
+
+ yield [
+ OopVisibilityType::isCorrectType('1'),
+ true,
+ ];
+
+ yield [
+ OopVisibilityType::isCorrectType('2'),
+ true,
+ ];
+
+ yield [
+ OopVisibilityType::isCorrectType('3'),
+ true,
+ ];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getAllExpectedTypes(): array
+ {
+ return [
+ 'IS_PRIVATE' => 3,
+ 'IS_PROTECTED' => 2,
+ 'IS_PUBLIC' => 1,
+ ];
+ }
+
+ /**
+ *{@inheritdoc}
+ */
+ protected function getTestedTypeInstance(): BaseType
+ {
+ return new OopVisibilityType();
+ }
+}
diff --git a/tests/Utilities/Arrays/SimpleToString.php b/tests/Utilities/Arrays/SimpleToString.php
index dd51827..190f821 100644
--- a/tests/Utilities/Arrays/SimpleToString.php
+++ b/tests/Utilities/Arrays/SimpleToString.php
@@ -14,6 +14,8 @@ namespace Meritoo\Test\Common\Utilities\Arrays;
*
* @author Meritoo
* @copyright Meritoo
+ *
+ * @coversNothing
*/
class SimpleToString
{
diff --git a/tests/Utilities/ArraysTest.php b/tests/Utilities/ArraysTest.php
index 168fac7..e119f82 100644
--- a/tests/Utilities/ArraysTest.php
+++ b/tests/Utilities/ArraysTest.php
@@ -8,8 +8,10 @@
namespace Meritoo\Test\Common\Utilities;
+use Generator;
use Meritoo\Common\Test\Base\BaseTestCase;
use Meritoo\Common\Utilities\Arrays;
+use Meritoo\Common\Utilities\Locale;
use Meritoo\Test\Common\Utilities\Arrays\SimpleToString;
/**
@@ -17,6 +19,9 @@ use Meritoo\Test\Common\Utilities\Arrays\SimpleToString;
*
* @author Meritoo
* @copyright Meritoo
+ *
+ * @internal
+ * @covers \Meritoo\Common\Utilities\Arrays
*/
class ArraysTest extends BaseTestCase
{
@@ -26,241 +31,2320 @@ class ArraysTest extends BaseTestCase
private $complexArray;
private $superComplexArray;
- public function testConstructor()
+ public function provideArrayToQuoteStrings()
{
- static::assertHasNoConstructor(Arrays::class);
- }
-
- /**
- * @param string $description Description of test
- * @param string $expected Expected array converted to string
- * @param array $array Data to be converted
- * @param string $arrayColumnKey (optional) Column name. Default: "".
- * @param string $separator (optional) Separator used between values. Default: ",".
- *
- * @dataProvider provideArrayValues2string
- */
- public function testValues2string($description, $expected, array $array, $arrayColumnKey = '', $separator = ',')
- {
- self::assertSame($expected, Arrays::values2string($array, $arrayColumnKey, $separator), $description);
- }
-
- /**
- * @param string $description Description of test
- * @param string $expected Expected array converted to string
- * @param array $array Data to be converted
- * @param string $separator (optional) Separator used between name-value pairs. Default: ",".
- * @param string $valuesKeysSeparator (optional) Separator used between name and value. Default: "=".
- * @param string $valuesWrapper (optional) Wrapper used to wrap values, e.g. double-quote: key="value".
- * Default: "".
- *
- * @dataProvider provideArrayValuesKeysConverted2string
- */
- public function testValuesKeys2string(
- $description,
- $expected,
- array $array,
- $separator = ',',
- $valuesKeysSeparator = '=',
- $valuesWrapper = ''
- ) {
- self::assertSame(
- $expected,
- Arrays::valuesKeys2string($array, $separator, $valuesKeysSeparator, $valuesWrapper),
- $description
- );
-
- self::assertSame(
- '0=Lorem,1=ipsum,2=dolor,3=sit,4=amet',
- Arrays::valuesKeys2string($this->simpleArray),
- 'Simple array'
- );
-
- self::assertSame(
- '0=Lorem;1=ipsum;2=dolor;3=sit;4=amet',
- Arrays::valuesKeys2string($this->simpleArray, ';'),
- 'Simple array (with custom separator)'
- );
-
- self::assertSame(
- '0=Lorem 1=ipsum 2=dolor 3=sit 4=amet',
- Arrays::valuesKeys2string($this->simpleArray, ' '),
- 'Simple array (with custom separator)'
- );
-
- self::assertSame(
- '0="Lorem" 1="ipsum" 2="dolor" 3="sit" 4="amet"',
- Arrays::valuesKeys2string($this->simpleArray, ' ', '=', '"'),
- 'Simple array (with custom separators)'
- );
-
- self::assertSame(
- '0="Lorem", 1="ipsum", 2="dolor", 3="sit", 4="amet"',
- Arrays::valuesKeys2string($this->simpleArray, ', ', '=', '"'),
- 'Simple array (with custom separators)'
- );
- }
-
- /**
- * @param string $description Description of test
- * @param string $expected Expected array converted to csv string
- * @param array $array Data to be converted. It have to be an array that represents database table.
- * @param string $separator (optional) Separator used between values. Default: ",".
- *
- * @dataProvider provideArrayValues2csv
- */
- public function testValues2csv($description, $expected, array $array, $separator = ',')
- {
- self::assertSame($expected, Arrays::values2csv($array, $separator), $description);
- self::assertSame('', Arrays::values2csv($this->simpleArray), 'Simple array');
-
- self::assertSame("lorem,ipsum,dolor,sit,amet\n"
- . "consectetur,adipiscing,elit\n"
- . 'donec,sagittis,fringilla,eleifend',
- Arrays::values2csv($this->twoDimensionsArray),
- 'Two dimensions array'
- );
- }
-
- public function testGetFirstKey()
- {
- /*
- * Negative cases
- */
- self::assertNull(Arrays::getFirstKey([]));
-
- /*
- * Positive cases
- */
- self::assertEquals(0, Arrays::getFirstKey($this->simpleArray));
- self::assertEquals('lorem', Arrays::getFirstKey($this->complexArray));
- }
-
- public function testGetLastKey()
- {
- self::assertNull(Arrays::getLastKey([]));
- self::assertEquals(4, Arrays::getLastKey($this->simpleArray));
- self::assertEquals('amet', Arrays::getLastKey($this->complexArray));
- }
-
- public function testGetFirstElement()
- {
- /*
- * Negative cases
- */
- self::assertNull(Arrays::getFirstElement([]));
-
- /*
- * Positive cases
- */
- self::assertEquals('Lorem', Arrays::getFirstElement($this->simpleArray));
- self::assertEquals('Lorem', Arrays::getFirstElement($this->simpleArray));
- self::assertEquals('lorem', Arrays::getFirstElement($this->twoDimensionsArray, false));
- self::assertEquals('sit', Arrays::getFirstElement($this->complexArray, false));
- }
-
- public function testIsFirstElement()
- {
- self::assertTrue(Arrays::isFirstElement($this->simpleArray, 'Lorem'));
- self::assertFalse(Arrays::isFirstElement($this->simpleArray, 'dolor'));
- self::assertFalse(Arrays::isFirstElement($this->simpleArray, ' '));
- self::assertFalse(Arrays::isFirstElement($this->simpleArray, null));
- }
-
- public function testGetLastElement()
- {
- /*
- * Negative cases
- */
- self::assertNull(Arrays::getLastElement([]));
-
- /*
- * Positive cases
- */
- self::assertEquals('amet', Arrays::getLastElement($this->simpleArray));
- self::assertEquals('eleifend', Arrays::getLastElement($this->twoDimensionsArray, false));
- self::assertEquals('primis', Arrays::getLastElement($this->complexArray, false));
- }
-
- public function testIsLastElement()
- {
- self::assertTrue(Arrays::isLastElement($this->simpleArray, 'amet'));
- self::assertFalse(Arrays::isLastElement($this->simpleArray, 'ipsum'));
- self::assertFalse(Arrays::isLastElement($this->simpleArray, ''));
- self::assertFalse(Arrays::isLastElement($this->simpleArray, null));
- }
-
- public function testGetLastElementBreadCrumb()
- {
- self::assertNull(Arrays::getLastElementBreadCrumb([]));
- self::assertEquals('4/amet', Arrays::getLastElementBreadCrumb($this->simpleArray));
- self::assertEquals('2/3/eleifend', Arrays::getLastElementBreadCrumb($this->twoDimensionsArray));
- self::assertEquals('amet/1/primis', Arrays::getLastElementBreadCrumb($this->complexArray));
- }
-
- public function testGetLastRow()
- {
- /*
- * Negative cases
- */
- self::assertNull(Arrays::getLastRow([]));
-
- /*
- * Positive cases
- */
- self::assertEquals([], Arrays::getLastRow($this->simpleArray));
- self::assertEquals([], Arrays::getLastRow($this->simpleArrayWithKeys));
-
- self::assertEquals([
- 'donec',
- 'sagittis',
- 'fringilla',
- 'eleifend',
- ], Arrays::getLastRow($this->twoDimensionsArray));
-
- self::assertEquals([
- 'iaculis',
- 'primis',
- ], Arrays::getLastRow($this->complexArray));
- }
-
- public function testReplaceArrayKeys()
- {
- $effect = [
- 'nullam' => 'donec',
- 'x' => [
- 'vitae' => [
- 'x' => 'quis',
- ],
- ],
- 'elit',
+ yield [
+ 'An empty array',
+ null,
+ [],
];
- $dataArray = $this->complexArray['sit'];
- self::assertEquals($effect, Arrays::replaceArrayKeys($dataArray, '|.*li.*|', 'x'));
+ yield [
+ 'Simple array',
+ [
+ 1,
+ 2,
+ 3,
+ '\'1\'',
+ '\'2\'',
+ ],
+ [
+ 1,
+ 2,
+ 3,
+ '1',
+ '2',
+ ],
+ ];
- self::assertEquals([
- 'x' => 'sit',
- 4 => 'amet',
- ], Arrays::replaceArrayKeys($this->simpleArray, '|[0-3]+|', 'x'));
+ yield [
+ 'Complex array',
+ [
+ 123,
+ '\'456\'',
+ [
+ 'x' => [
+ 0,
+ '\'0\'',
+ 1 => '\'1\'',
+ 2 => 2,
+ ],
+ '\'y\'',
+ ],
+ 444 => '\'\'',
+ [
+ [
+ [
+ '\'test\'',
+ ],
+ ],
+ ],
+ ],
+ [
+ 123,
+ '456',
+ [
+ 'x' => [
+ 0,
+ '0',
+ 1 => '1',
+ 2 => 2,
+ ],
+ 'y',
+ ],
+ 444 => '',
+ [
+ [
+ [
+ 'test',
+ ],
+ ],
+ ],
+ ],
+ ];
}
- public function testMakeArray()
+ public function provideArrayToRemoveMarginalElement(): Generator
{
- self::assertSame($this->simpleArray, Arrays::makeArray($this->simpleArray));
- self::assertSame(['test'], Arrays::makeArray('test'));
+ yield [
+ 'An empty array - remove last element',
+ [],
+ true,
+ null,
+ ];
+
+ yield [
+ 'An empty array - remove first element',
+ [],
+ false,
+ null,
+ ];
+
+ yield [
+ 'One-dimensional array - remove last element',
+ [
+ 'Lorem',
+ 'ipsum',
+ 'dolor',
+ 'sit',
+ 'amet',
+ ],
+ true,
+ [
+ 0 => 'Lorem',
+ 1 => 'ipsum',
+ 2 => 'dolor',
+ 3 => 'sit',
+ ],
+ ];
+
+ yield [
+ 'One-dimensional array - remove first element',
+ [
+ 'Lorem',
+ 'ipsum',
+ 'dolor',
+ 'sit',
+ 'amet',
+ ],
+ false,
+ [
+ 1 => 'ipsum',
+ 2 => 'dolor',
+ 3 => 'sit',
+ 4 => 'amet',
+ ],
+ ];
+
+ yield [
+ 'Multi-dimensional array - remove last element',
+ [
+ 'lorem' => [
+ 'ipsum' => [
+ 'dolor' => 'sit',
+ 'diam' => [
+ 'non' => 'egestas',
+ ],
+ ],
+ ],
+ 'consectetur' => 'adipiscing',
+ 'mollis' => 1234,
+ 2 => [],
+ 'sit' => [
+ 'nullam' => 'donec',
+ 'aliquet' => [
+ 'vitae' => [
+ 'ligula' => 'quis',
+ ],
+ ],
+ 'elit',
+ ],
+ 'amet' => [
+ 'iaculis',
+ 'primis',
+ ],
+ ],
+ true,
+ [
+ 'lorem' => [
+ 'ipsum' => [
+ 'dolor' => 'sit',
+ 'diam' => [
+ 'non' => 'egestas',
+ ],
+ ],
+ ],
+ 'consectetur' => 'adipiscing',
+ 'mollis' => 1234,
+ 2 => [],
+ 'sit' => [
+ 'nullam' => 'donec',
+ 'aliquet' => [
+ 'vitae' => [
+ 'ligula' => 'quis',
+ ],
+ ],
+ 'elit',
+ ],
+ ],
+ ];
+
+ yield [
+ 'Multi-dimensional array - remove first element',
+ [
+ 'lorem' => [
+ 'ipsum' => [
+ 'dolor' => 'sit',
+ 'diam' => [
+ 'non' => 'egestas',
+ ],
+ ],
+ ],
+ 'consectetur' => 'adipiscing',
+ 'mollis' => 1234,
+ 2 => [],
+ 'sit' => [
+ 'nullam' => 'donec',
+ 'aliquet' => [
+ 'vitae' => [
+ 'ligula' => 'quis',
+ ],
+ ],
+ 'elit',
+ ],
+ 'amet' => [
+ 'iaculis',
+ 'primis',
+ ],
+ ],
+ false,
+ [
+ 'consectetur' => 'adipiscing',
+ 'mollis' => 1234,
+ 2 => [],
+ 'sit' => [
+ 'nullam' => 'donec',
+ 'aliquet' => [
+ 'vitae' => [
+ 'ligula' => 'quis',
+ ],
+ ],
+ 'elit',
+ ],
+ 'amet' => [
+ 'iaculis',
+ 'primis',
+ ],
+ ],
+ ];
}
- public function testArray2JavaScript()
+ public function provideArrayToReplaceKeys(): Generator
{
+ yield [
+ 'An empty array',
+ [],
+ '',
+ '',
+ null,
+ ];
+
+ yield [
+ '1st case',
+ [
+ 'nullam' => 'donec',
+ 'aliquet' => [
+ 'vitae' => [
+ 'ligula' => 'quis',
+ ],
+ ],
+ 'elit',
+ ],
+ '|.*li.*|',
+ 'x',
+ [
+ 'nullam' => 'donec',
+ 'x' => [
+ 'vitae' => [
+ 'x' => 'quis',
+ ],
+ ],
+ 'elit',
+ ],
+ ];
+
+ yield [
+ '2nd case',
+ [
+ 'Lorem',
+ 'ipsum',
+ 'dolor',
+ 'sit',
+ 'amet',
+ ],
+ '|[0-3]+|',
+ 'x',
+ [
+ 'x' => 'sit',
+ 4 => 'amet',
+ ],
+ ];
+ }
+
+ public function provideArrayToVerifyIfContainsEmptyStringsOnly(): ?Generator
+ {
+ yield [
+ [],
+ false,
+ ];
+
+ yield [
+ [
+ '',
+ 1,
+ ],
+ false,
+ ];
+
+ yield [
+ [
+ '',
+ null,
+ 1,
+ ],
+ false,
+ ];
+
+ yield [
+ [
+ '',
+ null,
+ ],
+ true,
+ ];
+
+ yield [
+ [
+ '',
+ null,
+ '',
+ ],
+ true,
+ ];
+ }
+
+ public function provideArrayValues2csv(): ?Generator
+ {
+ yield [
+ 'An empty array',
+ null,
+ [],
+ ];
+
+ yield [
+ 'Empty string, and empty array and null as row',
+ "1,2,3\n5,6,",
+ [
+ 'test_1' => '',
+ 'test_2' => [],
+ 'test_3' => null,
+ 'test_4' => [
+ 'aa' => 1,
+ 'bb' => 2,
+ 'cc' => 3,
+ ],
+ [
+ 'dd' => 5,
+ 'ee' => 6,
+ 'ff' => '',
+ ],
+ ],
+ ];
+
+ yield [
+ 'Empty string, and empty array and null as row (with custom separator)',
+ "1, 2, 3\n5, 6, ",
+ [
+ 'test_1' => '',
+ 'test_2' => [],
+ 'test_3' => null,
+ 'test_4' => [
+ 'aa' => 1,
+ 'bb' => 2,
+ 'cc' => 3,
+ ],
+ [
+ 'dd' => 5,
+ 'ee' => 6,
+ 'ff' => '',
+ ],
+ ],
+ ', ',
+ ];
+
+ yield [
+ 'Empty string as key, non-array as value',
+ "1,2,3\n5,6,",
+ [
+ '' => 'test_1',
+ 1 => 'test_2',
+ '3' => [
+ 'aa' => 1,
+ 'bb' => 2,
+ 'cc' => 3,
+ ],
+ [
+ 'dd' => 5,
+ 'ee' => 6,
+ 'ff' => '',
+ ],
+ ],
+ ];
+
+ yield [
+ 'Empty string as key, non-array as value (with custom separator)',
+ "1 | 2 | 3\n5 | 6 | ",
+ [
+ '' => 'test_1',
+ 1 => 'test_2',
+ '3' => [
+ 'aa' => 1,
+ 'bb' => 2,
+ 'cc' => 3,
+ ],
+ [
+ 'dd' => 5,
+ 'ee' => 6,
+ 'ff' => '',
+ ],
+ ],
+ ' | ',
+ ];
+
+ yield [
+ 'Invalid structure, not like database table',
+ "1,2,3\n5,6\n7,8,9,10",
+ [
+ [
+ 'aa' => 1,
+ 'bb' => 2,
+ 'cc' => 3,
+ ],
+ [
+ 'dd' => 5,
+ 'ee' => 6,
+ ],
+ [
+ 7,
+ 8,
+ 9,
+ 10,
+ ],
+ ],
+ ];
+
+ yield [
+ 'Invalid structure, not like database table (with custom separator)',
+ "1 <-> 2 <-> 3\n5 <-> 6\n7 <-> 8 <-> 9 <-> 10",
+ [
+ [
+ 'aa' => 1,
+ 'bb' => 2,
+ 'cc' => 3,
+ ],
+ [
+ 'dd' => 5,
+ 'ee' => 6,
+ ],
+ [
+ 7,
+ 8,
+ 9,
+ 10,
+ ],
+ ],
+ ' <-> ',
+ ];
+
+ yield [
+ 'Mixed types of keys and values',
+ "1,2,3.45\n5,6,\n7,8,9,,10",
+ [
+ [
+ 'aa' => 1,
+ 'bb' => 2,
+ 'cc' => 3.45,
+ ],
+ [
+ 'dd' => 5,
+ 'ee' => 6,
+ null,
+ ],
+ [
+ 7,
+ 8,
+ 'qq' => 9,
+ '',
+ 10,
+ ],
+ ],
+ ];
+
+ yield [
+ 'Mixed types of keys and values (with custom separator)',
+ "1 // 2 // 3.45\n5 // 6 // \n7 // 8 // 9 // // 10",
+ [
+ [
+ 'aa' => 1,
+ 'bb' => 2,
+ 'cc' => 3.45,
+ ],
+ [
+ 'dd' => 5,
+ 'ee' => 6,
+ null,
+ ],
+ [
+ 7,
+ 8,
+ 'qq' => 9,
+ '',
+ 10,
+ ],
+ ],
+ ' // ',
+ ];
+
+ yield [
+ 'With HTML code',
+ "abc
,def,ghi
\nc,d",
+ [
+ [
+ '<div>abc</div>',
+ 'def',
+ '<div>ghi</div>',
+ ],
+ [
+ 'c',
+ 'd',
+ ],
+ ],
+ ];
+ }
+
+ public function provideArrayValues2string()
+ {
+ yield [
+ 'An empty array',
+ null,
+ [],
+ ];
+
+ yield [
+ 'Simple array',
+ 'Test 1,Test 2,Test 3',
+ [
+ 1 => 'Test 1',
+ 2 => 'Test 2',
+ 3 => 'Test 3',
+ ],
+ ];
+
+ yield [
+ 'Simple array (with custom separator)',
+ 'Test 1.Test 2.Test 3',
+ [
+ 1 => 'Test 1',
+ 2 => 'Test 2',
+ 3 => 'Test 3',
+ ],
+ '',
+ '.',
+ ];
+
+ yield [
+ 'Simple array (concrete column)',
+ 'Test 2',
+ [
+ 1 => 'Test 1',
+ 2 => 'Test 2',
+ 3 => 'Test 3',
+ ],
+ 2,
+ ];
+
+ yield [
+ 'Simple array (concrete column with custom separator)',
+ 'Test 2',
+ [
+ 1 => 'Test 1',
+ 2 => 'Test 2',
+ 3 => 'Test 3',
+ ],
+ 2,
+ '.',
+ ];
+
+ yield [
+ 'Complex array',
+ '1,2,3,test 1,test 2,test 3,,test 4,,bbb,3.45',
+ [
+ [
+ 1,
+ 2,
+ 3,
+ ],
+ [
+ 'test 1',
+ 'test 2',
+ [
+ 'test 3',
+ '',
+ 'test 4',
+ ],
+ ],
+ [],
+ [
+ 'a' => '',
+ 'b' => 'bbb',
+ [],
+ 'c' => 3.45,
+ ],
+ ],
+ ];
+
+ yield [
+ '1st complex array (concrete column)',
+ '2,test 2,',
+ [
+ [
+ 1,
+ 2,
+ 3,
+ ],
+ [
+ 'test 1',
+ 'test 2',
+ [
+ 'test 3',
+ '',
+ 'test 4',
+ ],
+ ],
+ [],
+ [
+ 'a' => '',
+ 'b' => 'bbb',
+ [],
+ 'c' => 3.45,
+ ],
+ ],
+ 1,
+ ];
+
+ yield [
+ '2nd complex array (concrete column)',
+ 'bb,1234,0xb',
+ [
+ [
+ 1,
+ 2,
+ 3,
+ ],
+ [
+ 'a' => 'aa',
+ 'b' => 'bb',
+ 'c' => 'cc',
+ ],
+ [
+ 'a',
+ 'b',
+ 'c',
+ ],
+ [
+ 'a' => '',
+ 'b' => 1234,
+ ],
+ [
+ 'c' => 5678,
+ 'b' => '0xb',
+ ],
+ ],
+ 'b',
+ ];
+
+ yield [
+ '3rd complex array (concrete column with custom separator)',
+ 'bb - 1234 - 3xb - bbb',
+ [
+ [
+ 1,
+ 2,
+ 3,
+ ],
+ [
+ 'a' => 'aa',
+ 'b' => 'bb',
+ 'c' => 'cc',
+ ],
+ [
+ 'a',
+ 'b' => [],
+ 'c',
+ ],
+ [
+ 'a' => '',
+ 'b' => 1234,
+ ],
+ [
+ 'c' => 5678,
+ 'b' => [
+ 'b1' => '0xb',
+ 'b2' => '1xb',
+ 'b' => '3xb',
+ ],
+ [
+ 1,
+ 2,
+ 'a' => 'aaa',
+ 'b' => 'bbb',
+ ],
+ ],
+ ],
+ 'b',
+ ' - ',
+ ];
+ }
+
+ public function provideArrayValuesKeysConverted2string()
+ {
+ yield [
+ 'An empty array',
+ null,
+ [],
+ ];
+
+ yield [
+ 'Empty string and null as value',
+ 'test_1=,test_2=,test_3=3',
+ [
+ 'test_1' => null,
+ 'test_2' => '',
+ 'test_3' => '3',
+ ],
+ ];
+
+ yield [
+ 'Empty string and null as value (with custom separators)',
+ 'test_1="" test_2="" test_3="3"',
+ [
+ 'test_1' => null,
+ 'test_2' => '',
+ 'test_3' => '3',
+ ],
+ ' ',
+ '=',
+ '"',
+ ];
+
+ yield [
+ 'Empty string as key',
+ '1=test_1,=test_2,3=test_3',
+ [
+ 1 => 'test_1',
+ '' => 'test_2',
+ '3' => 'test_3',
+ ],
+ ];
+
+ yield [
+ 'Empty string as key (with custom separators)',
+ '1 => "test_1"; => "test_2"; 3 => "test_3"',
+ [
+ 1 => 'test_1',
+ '' => 'test_2',
+ '3' => 'test_3',
+ ],
+ '; ',
+ ' => ',
+ '"',
+ ];
+
+ yield [
+ 'Mixed types of keys and values',
+ 'test_1=test test,test_2=2,test_3=3.45',
+ [
+ 'test_1' => 'test test',
+ 'test_2' => 2,
+ 'test_3' => 3.45,
+ ],
+ ];
+
+ yield [
+ 'Mixed types of keys and values (with custom separators)',
+ 'test_1 --> *test test* | test_2 --> *2* | test_3 --> *3.45*',
+ [
+ 'test_1' => 'test test',
+ 'test_2' => 2,
+ 'test_3' => 3.45,
+ ],
+ ' | ',
+ ' --> ',
+ '*',
+ ];
+ }
+
+ /**
+ * Provides an array with duplicated values to set/replace values with keys
+ *
+ * @return Generator
+ */
+ public function provideArrayWithDuplicatedValuesToSetKeysAsValues()
+ {
+ yield [
+ [
+ 'lorem' => 'ipsum',
+ 'dolor' => 'ipsum',
+ 'sit' => 'amet',
+ 'diam' => 'non',
+ 'elit' => 'non',
+ 'in' => 'non',
+ ],
+ [
+ 'ipsum' => [
+ 'lorem',
+ 'dolor',
+ ],
+ 'amet' => 'sit',
+ 'non' => [
+ 'diam',
+ 'elit',
+ 'in',
+ ],
+ ],
+ ];
+
+ yield [
+ [
+ 'lorem' => [
+ 'diam' => 'non',
+ 'elit' => 'non',
+ 'in' => 'non',
+ ],
+ 'dolor1' => 'ipsum',
+ 'dolor2' => 'ipsum',
+ 'sit' => 'amet',
+ ],
+ [
+ 'lorem' => [
+ 'non' => [
+ 'diam',
+ 'elit',
+ 'in',
+ ],
+ ],
+ 'ipsum' => [
+ 'dolor1',
+ 'dolor2',
+ ],
+ 'amet' => 'sit',
+ ],
+ ];
+ }
+
+ public function provideFirstElement(): ?Generator
+ {
+ yield [
+ 'An empty array (first level only)',
+ null,
+ [],
+ ];
+
+ yield [
+ 'An empty array',
+ null,
+ [],
+ false,
+ ];
+
+ yield [
+ 'Multidimensional array (first level only)',
+ [
+ [
+ 'abc',
+ 2,
+ 'def',
+ ],
+ 4,
+ ],
+ [
+ [
+ [
+ 'abc',
+ 2,
+ 'def',
+ ],
+ 4,
+ ],
+ '---',
+ [
+ 'ghi',
+ 7,
+ [
+ 'jkl',
+ '...',
+ 10,
+ ],
+ ],
+ ],
+ ];
+
+ yield [
+ 'Multidimensional array',
+ 'abc',
+ [
+ [
+ [
+ 'abc',
+ 2,
+ 'def',
+ ],
+ 4,
+ ],
+ '---',
+ [
+ 'ghi',
+ 7,
+ [
+ 'jkl',
+ '...',
+ 10,
+ ],
+ ],
+ ],
+ false,
+ ];
+ }
+
+ public function provideIsFirstElement(): ?Generator
+ {
+ yield [
+ 'An empty array (first level only)',
+ false,
+ [],
+ '',
+ ];
+
+ yield [
+ 'An empty array',
+ false,
+ [],
+ '',
+ false,
+ ];
+
+ yield [
+ 'Non-existing integer in array with integers (first level only)',
+ false,
+ [
+ 1,
+ 2,
+ 3,
+ ],
+ 4,
+ ];
+
+ yield [
+ 'Existing integer in array with integers (first level only)',
+ true,
+ [
+ 1,
+ 2,
+ 3,
+ ],
+ 1,
+ ];
+
+ yield [
+ 'Existing integer in array with integers',
+ true,
+ [
+ 1,
+ 2,
+ 3,
+ ],
+ 1,
+ false,
+ ];
+
+ yield [
+ 'Non-existing integer in multidimensional array with integers (first level only)',
+ false,
+ [
+ [
+ [
+ 1,
+ 2,
+ 3,
+ ],
+ 4,
+ ],
+ 5,
+ [
+ 6,
+ 7,
+ [
+ 8,
+ 9,
+ 10,
+ ],
+ ],
+ ],
+ 9,
+ ];
+
+ yield [
+ 'Non-existing integer in multidimensional array with integers',
+ false,
+ [
+ [
+ [
+ 1,
+ 2,
+ 3,
+ ],
+ 4,
+ ],
+ 5,
+ [
+ 6,
+ 7,
+ [
+ 8,
+ 9,
+ 10,
+ ],
+ ],
+ ],
+ 9,
+ false,
+ ];
+
+ yield [
+ 'Existing integer in multidimensional array with integers, but first level only checked',
+ false,
+ [
+ [
+ [
+ 1,
+ 2,
+ 3,
+ ],
+ 4,
+ ],
+ 5,
+ [
+ 6,
+ 7,
+ [
+ 8,
+ 9,
+ 10,
+ ],
+ ],
+ ],
+ 1,
+ ];
+
+ yield [
+ 'Existing integer in multidimensional array with integers',
+ true,
+ [
+ [
+ [
+ 1,
+ 2,
+ 3,
+ ],
+ 4,
+ ],
+ 5,
+ [
+ 6,
+ 7,
+ [
+ 8,
+ 9,
+ 10,
+ ],
+ ],
+ ],
+ 1,
+ false,
+ ];
+
+ yield [
+ 'Non-existing element in multidimensional array (first level only)',
+ false,
+ [
+ [
+ [
+ 'abc',
+ 2,
+ 'def',
+ ],
+ 4,
+ ],
+ '---',
+ [
+ 'ghi',
+ 7,
+ [
+ 'jkl',
+ '...',
+ 10,
+ ],
+ ],
+ ],
+ 9,
+ ];
+
+ yield [
+ 'Existing element in multidimensional array, but first level only checked',
+ false,
+ [
+ [
+ [
+ 'abc',
+ 2,
+ 'def',
+ ],
+ 4,
+ ],
+ '---',
+ [
+ 'ghi',
+ 7,
+ [
+ 'jkl',
+ '...',
+ 10,
+ ],
+ ],
+ ],
+ 'abc',
+ ];
+
+ yield [
+ 'Existing element in multidimensional array',
+ true,
+ [
+ [
+ [
+ 'abc',
+ 2,
+ 'def',
+ ],
+ 4,
+ ],
+ '---',
+ [
+ 'ghi',
+ 7,
+ [
+ 'jkl',
+ '...',
+ 10,
+ ],
+ ],
+ ],
+ 'abc',
+ false,
+ ];
+ }
+
+ public function provideIsLastElement(): ?Generator
+ {
+ yield [
+ 'An empty array (first level only)',
+ false,
+ [],
+ '',
+ ];
+
+ yield [
+ 'An empty array',
+ false,
+ [],
+ '',
+ false,
+ ];
+
+ yield [
+ 'Non-existing integer in array with integers (first level only)',
+ false,
+ [
+ 1,
+ 2,
+ 3,
+ ],
+ 4,
+ ];
+
+ yield [
+ 'Existing integer in array with integers (first level only)',
+ true,
+ [
+ 1,
+ 2,
+ 3,
+ ],
+ 3,
+ ];
+
+ yield [
+ 'Existing integer in array with integers',
+ true,
+ [
+ 1,
+ 2,
+ 3,
+ ],
+ 3,
+ false,
+ ];
+
+ yield [
+ 'Non-existing integer in multidimensional array with integers (first level only)',
+ false,
+ [
+ [
+ [
+ 1,
+ 2,
+ 3,
+ ],
+ 4,
+ ],
+ 5,
+ [
+ 6,
+ 7,
+ [
+ 8,
+ 9,
+ 10,
+ ],
+ ],
+ ],
+ 11,
+ ];
+
+ yield [
+ 'Non-existing integer in multidimensional array with integers',
+ false,
+ [
+ [
+ [
+ 1,
+ 2,
+ 3,
+ ],
+ 4,
+ ],
+ 5,
+ [
+ 6,
+ 7,
+ [
+ 8,
+ 9,
+ 10,
+ ],
+ ],
+ ],
+ 11,
+ false,
+ ];
+
+ yield [
+ 'Existing integer in multidimensional array with integers, but first level only checked',
+ false,
+ [
+ [
+ [
+ 1,
+ 2,
+ 3,
+ ],
+ 4,
+ ],
+ 5,
+ [
+ 6,
+ 7,
+ [
+ 8,
+ 9,
+ 10,
+ ],
+ ],
+ ],
+ 10,
+ ];
+
+ yield [
+ 'Existing integer in multidimensional array with integers',
+ true,
+ [
+ [
+ [
+ 1,
+ 2,
+ 3,
+ ],
+ 4,
+ ],
+ 5,
+ [
+ 6,
+ 7,
+ [
+ 8,
+ 9,
+ 10,
+ ],
+ ],
+ ],
+ 10,
+ false,
+ ];
+
+ yield [
+ 'Non-existing element in multidimensional array (first level only)',
+ false,
+ [
+ [
+ [
+ 'abc',
+ 2,
+ 'def',
+ ],
+ 4,
+ ],
+ '---',
+ [
+ 'ghi',
+ 7,
+ [
+ 'jkl',
+ '...',
+ 10,
+ ],
+ ],
+ ],
+ 9,
+ ];
+
+ yield [
+ 'Existing element in multidimensional array, but first level only checked',
+ false,
+ [
+ [
+ [
+ 'abc',
+ 2,
+ 'def',
+ ],
+ 4,
+ ],
+ '---',
+ [
+ 'ghi',
+ 7,
+ [
+ 10,
+ '...',
+ 'jkl',
+ ],
+ ],
+ ],
+ 'jkl',
+ ];
+
+ yield [
+ 'Existing element in multidimensional array',
+ true,
+ [
+ [
+ [
+ 'abc',
+ 2,
+ 'def',
+ ],
+ 4,
+ ],
+ '---',
+ [
+ 'ghi',
+ 7,
+ [
+ 10,
+ '...',
+ 'jkl',
+ ],
+ ],
+ ],
+ 'jkl',
+ false,
+ ];
+ }
+
+ public function provideLastElement(): ?Generator
+ {
+ yield [
+ 'An empty array (first level only)',
+ null,
+ [],
+ ];
+
+ yield [
+ 'An empty array',
+ null,
+ [],
+ false,
+ ];
+
+ yield [
+ 'One-dimensional array (first level only)',
+ 3,
+ [
+ 1,
+ 2,
+ 3,
+ ],
+ ];
+
+ yield [
+ 'One-dimensional array (first level only)',
+ 3,
+ [
+ 1,
+ 2,
+ 3,
+ ],
+ false,
+ ];
+
+ yield [
+ 'Multidimensional array (first level only)',
+ [
+ 'ghi',
+ 7,
+ [
+ 'jkl',
+ '...',
+ 10,
+ ],
+ ],
+ [
+ [
+ [
+ 'abc',
+ 2,
+ 'def',
+ ],
+ 4,
+ ],
+ '---',
+ [
+ 'ghi',
+ 7,
+ [
+ 'jkl',
+ '...',
+ 10,
+ ],
+ ],
+ ],
+ ];
+
+ yield [
+ 'Multidimensional array',
+ 10,
+ [
+ [
+ [
+ 'abc',
+ 2,
+ 'def',
+ ],
+ 4,
+ ],
+ '---',
+ [
+ 'ghi',
+ 7,
+ [
+ 'jkl',
+ '...',
+ 10,
+ ],
+ ],
+ ],
+ false,
+ ];
+ }
+
+ public function provideLastRow(): ?Generator
+ {
+ yield [
+ 'An empty array',
+ null,
+ [],
+ ];
+
+ yield [
+ 'One-dimensional array',
+ [],
+ [
+ 'a',
+ 'b',
+ 1,
+ 2,
+ ],
+ ];
+
+ yield [
+ 'Multidimensional array with scalar as last element',
+ [],
+ [
+ 'a',
+ [
+ 'b',
+ 'c',
+ ],
+ [
+ 'e',
+ 'f',
+ ],
+ 1,
+ 2,
+ ],
+ ];
+
+ yield [
+ 'Multidimensional array with an empty array as last element',
+ [],
+ [
+ 'a',
+ [
+ 'b',
+ 'c',
+ ],
+ 1,
+ 2,
+ [],
+ ],
+ ];
+
+ yield [
+ 'Multidimensional array',
+ [
+ 'e',
+ 'f',
+ ],
+ [
+ 'a',
+ [
+ 'b',
+ 'c',
+ ],
+ 1,
+ 2,
+ [
+ 'e',
+ 'f',
+ ],
+ ],
+ ];
+ }
+
+ /**
+ * Provides simple array to set/replace values with keys
+ *
+ * @return Generator
+ */
+ public function provideSimpleArrayToSetKeysAsValues()
+ {
+ yield [
+ [
+ 1,
+ 2,
+ 3,
+ 4,
+ ],
+ [
+ 1 => 0,
+ 2 => 1,
+ 3 => 2,
+ 4 => 3,
+ ],
+ ];
+
+ yield [
+ [
+ 'Lorem',
+ 'ipsum',
+ 'dolor',
+ 'sit',
+ 'amet',
+ ],
+ [
+ 'Lorem' => 0,
+ 'ipsum' => 1,
+ 'dolor' => 2,
+ 'sit' => 3,
+ 'amet' => 4,
+ ],
+ ];
+ }
+
+ /**
+ * Provides patterns of keys or paths that matched will stop the process and the expected array for the
+ * getLastElementsPaths() method
+ *
+ * @return Generator
+ */
+ public function provideStopIfMatchedByForGetLastElementsPaths(): ?Generator
+ {
+ // Special exception: do not use, stop recursive on the "diam" key
+ yield [
+ ['diam'],
+ '.',
+ [
+ 'ipsum.quis.vestibulum.porta-1.0' => 'turpis',
+ 'ipsum.quis.vestibulum.porta-1.1' => 'urna',
+ 'ipsum.quis.vestibulum.porta-2.tortor.in.0' => 'dui',
+ 'ipsum.quis.vestibulum.porta-2.tortor.in.dolor.0' => 'aliquam',
+ 'ipsum.quis.vestibulum.porta-3.0' => 1,
+ 'ipsum.quis.vestibulum.porta-3.1' => 2,
+ 'ipsum.quis.vestibulum.porta-3.2' => 3,
+ 'primis.0.0' => 'in',
+ 'primis.0.1' => 'faucibus',
+ 'primis.0.2' => 'orci',
+ 'primis.1.0' => 'luctus',
+ 'primis.1.1' => 'et',
+ 'primis.1.2' => 'ultrices',
+ ],
+ ];
+
/*
- * Negative cases
+ * Stop building of paths on these keys:
+ * - "tortor"
+ * - "primis"
*/
+ yield [
+ [
+ 'tortor',
+ 'primis',
+ ],
+ ' . ',
+ [
+ 'ipsum . quis . vestibulum . porta-1 . 0' => 'turpis',
+ 'ipsum . quis . vestibulum . porta-1 . 1' => 'urna',
+ 'ipsum . quis . vestibulum . porta-2 . tortor' => [
+ 'in' => [
+ 'dui',
+ 'dolor' => [
+ 'aliquam',
+ ],
+ ],
+ ],
+ 'ipsum . quis . vestibulum . porta-3 . 0' => 1,
+ 'ipsum . quis . vestibulum . porta-3 . 1' => 2,
+ 'ipsum . quis . vestibulum . porta-3 . 2' => 3,
+ 'primis' => [
+ [
+ 'in',
+ 'faucibus',
+ 'orci',
+ ],
+ [
+ 'luctus',
+ 'et',
+ 'ultrices',
+ ],
+ ],
+ ],
+ ];
+
+ // Stop building of paths on more sophisticated keys
+ yield [
+ [
+ 'porta\-\d+',
+ '^\d+$',
+ ],
+ ' > ',
+ [
+ 'ipsum > quis > vestibulum > porta-1' => [
+ 'turpis',
+ 'urna',
+ ],
+ 'ipsum > quis > vestibulum > porta-2' => [
+ 'tortor' => [
+ 'in' => [
+ 'dui',
+ 'dolor' => [
+ 'aliquam',
+ ],
+ ],
+ ],
+ ],
+ 'ipsum > quis > vestibulum > porta-3' => [
+ 1,
+ 2,
+ 3,
+ ],
+ 'primis > 0' => [
+ 'in',
+ 'faucibus',
+ 'orci',
+ ],
+ 'primis > 1' => [
+ 'luctus',
+ 'et',
+ 'ultrices',
+ ],
+ ],
+ ];
+
+ /*
+ * Stop building of paths on these:
+ * - keys
+ * and
+ * - paths (verify paths too)
+ */
+ yield [
+ [
+ 'porta-1',
+ 'porta-2 > tortor > in',
+ ],
+ ' > ',
+ [
+ 'ipsum > quis > vestibulum > porta-1' => [
+ 'turpis',
+ 'urna',
+ ],
+ 'ipsum > quis > vestibulum > porta-2 > tortor > in' => [
+ 'dui',
+ 'dolor' => [
+ 'aliquam',
+ ],
+ ],
+ 'ipsum > quis > vestibulum > porta-3 > 0' => 1,
+ 'ipsum > quis > vestibulum > porta-3 > 1' => 2,
+ 'ipsum > quis > vestibulum > porta-3 > 2' => 3,
+ 'primis > 0 > 0' => 'in',
+ 'primis > 0 > 1' => 'faucibus',
+ 'primis > 0 > 2' => 'orci',
+ 'primis > 1 > 0' => 'luctus',
+ 'primis > 1 > 1' => 'et',
+ 'primis > 1 > 2' => 'ultrices',
+ ],
+ ];
+
+ // Stop building of paths on these paths (verify paths only)
+ yield [
+ [
+ 'ipsum > quis > vestibulum > porta-1',
+ 'ipsum > quis > vestibulum > porta-2 > tortor',
+ 'primis > 1',
+ ],
+ ' > ',
+ [
+ 'ipsum > quis > vestibulum > porta-1' => [
+ 'turpis',
+ 'urna',
+ ],
+ 'ipsum > quis > vestibulum > porta-2 > tortor' => [
+ 'in' => [
+ 'dui',
+ 'dolor' => [
+ 'aliquam',
+ ],
+ ],
+ ],
+ 'ipsum > quis > vestibulum > porta-3 > 0' => 1,
+ 'ipsum > quis > vestibulum > porta-3 > 1' => 2,
+ 'ipsum > quis > vestibulum > porta-3 > 2' => 3,
+ 'primis > 0 > 0' => 'in',
+ 'primis > 0 > 1' => 'faucibus',
+ 'primis > 0 > 2' => 'orci',
+ 'primis > 1' => [
+ 'luctus',
+ 'et',
+ 'ultrices',
+ ],
+ ],
+ ];
+
+ // Stop building of paths if path contains any of these part (verify part of paths only)
+ yield [
+ [
+ 'vestibulum > porta-1',
+ 'tortor > in',
+ '[a-z]+ > \d+',
+ ],
+ ' > ',
+ [
+ 'ipsum > quis > vestibulum > porta-1' => [
+ 'turpis',
+ 'urna',
+ ],
+ 'ipsum > quis > vestibulum > porta-2 > tortor > in' => [
+ 'dui',
+ 'dolor' => [
+ 'aliquam',
+ ],
+ ],
+ 'ipsum > quis > vestibulum > porta-3 > 0' => 1,
+ 'ipsum > quis > vestibulum > porta-3 > 1' => 2,
+ 'ipsum > quis > vestibulum > porta-3 > 2' => 3,
+ 'primis > 0' => [
+ 'in',
+ 'faucibus',
+ 'orci',
+ ],
+ 'primis > 1' => [
+ 'luctus',
+ 'et',
+ 'ultrices',
+ ],
+ ],
+ ];
+ }
+
+ public function provideValueToIsEmptyArray(): ?Generator
+ {
+ yield [
+ 'An empty string',
+ '',
+ false,
+ ];
+
+ yield [
+ 'Non-empty string',
+ 'test',
+ false,
+ ];
+
+ yield [
+ 'Null',
+ null,
+ false,
+ ];
+
+ yield [
+ 'An integer equals 0',
+ 1234,
+ false,
+ ];
+
+ yield [
+ 'An integer greater than 0',
+ 1234,
+ false,
+ ];
+
+ yield [
+ 'An empty array',
+ [],
+ true,
+ ];
+
+ yield [
+ 'Non-empty array',
+ [
+ 'test',
+ ],
+ false,
+ ];
+ }
+
+ public function provideValueToIsNotEmptyArray(): ?Generator
+ {
+ yield [
+ 'An empty string',
+ '',
+ false,
+ ];
+
+ yield [
+ 'Non-empty string',
+ 'test',
+ false,
+ ];
+
+ yield [
+ 'Null',
+ null,
+ false,
+ ];
+
+ yield [
+ 'An integer equals 0',
+ 1234,
+ false,
+ ];
+
+ yield [
+ 'An integer greater than 0',
+ 1234,
+ false,
+ ];
+
+ yield [
+ 'An empty array',
+ [],
+ false,
+ ];
+
+ yield [
+ 'Non-empty array',
+ [
+ 'test',
+ ],
+ true,
+ ];
+ }
+
+ /**
+ * Provide values to filter and get non-empty values
+ *
+ * @return Generator
+ */
+ public function provideValuesToFilterNonEmpty(): ?Generator
+ {
+ $simpleObject = new SimpleToString('1234');
+
+ yield [
+ 'All values are empty',
+ [
+ '',
+ null,
+ [],
+ ],
+ [],
+ ];
+
+ yield [
+ '5 values with 2 empty strings',
+ [
+ 'test 1',
+ '',
+ 'test 2',
+ 'test 3',
+ '',
+ ],
+ [
+ 0 => 'test 1',
+ 2 => 'test 2',
+ 3 => 'test 3',
+ ],
+ ];
+
+ yield [
+ '"0" shouldn\'t be treated like an empty value',
+ [
+ 123,
+ 0,
+ 456,
+ ],
+ [
+ 123,
+ 0,
+ 456,
+ ],
+ ];
+
+ yield [
+ 'Object shouldn\'t be treated like an empty value',
+ [
+ 'test 1',
+ $simpleObject,
+ 'test 2',
+ null,
+ 'test 3',
+ ],
+ [
+ 0 => 'test 1',
+ 1 => $simpleObject,
+ 2 => 'test 2',
+ 4 => 'test 3',
+ ],
+ ];
+
+ yield [
+ 'Mixed values (non-empty, empty, strings, integers, objects)',
+ [
+ 'test 1',
+ '',
+ 123,
+ null,
+ 'test 2',
+ 'test 3',
+ 0,
+ $simpleObject,
+ 456,
+ [],
+ $simpleObject,
+ ],
+ [
+ 0 => 'test 1',
+ 2 => 123,
+ 4 => 'test 2',
+ 5 => 'test 3',
+ 6 => 0,
+ 7 => $simpleObject,
+ 8 => 456,
+ 10 => $simpleObject,
+ ],
+ ];
+ }
+
+ /**
+ * Provide values to filter and get non-empty values concatenated by given separator
+ *
+ * @return Generator
+ */
+ public function provideValuesToFilterNonEmptyAsString()
+ {
+ yield [
+ 'An empty array (no values to filter)',
+ [],
+ ' | ',
+ null,
+ ];
+
+ yield [
+ 'All values are empty',
+ [
+ '',
+ null,
+ [],
+ ],
+ ' | ',
+ '',
+ ];
+
+ yield [
+ '5 values with 2 empty strings',
+ [
+ 'test 1',
+ '',
+ 'test 2',
+ 'test 3',
+ '',
+ ],
+ ' | ',
+ 'test 1 | test 2 | test 3',
+ ];
+
+ yield [
+ 'Numbers with "0" that shouldn\'t be treated like an empty value',
+ [
+ 123,
+ 0,
+ 456,
+ ],
+ ' <-> ',
+ '123 <-> 0 <-> 456',
+ ];
+
+ yield [
+ 'Object shouldn\'t be treated like an empty value',
+ [
+ 'test 1',
+ new SimpleToString('1234'),
+ 'test 2',
+ null,
+ 'test 3',
+ ],
+ ' | ',
+ 'test 1 | Instance with ID: 1234 | test 2 | test 3',
+ ];
+
+ yield [
+ 'Mixed values (non-empty, empty, strings, integers, objects)',
+ [
+ 'test 1',
+ '',
+ 123,
+ null,
+ 'test 2',
+ 'test 3',
+ 0,
+ new SimpleToString('A1XC90Z'),
+ 456,
+ [],
+ new SimpleToString('FF-45-0Z'),
+ ],
+ ';',
+ 'test 1;123;test 2;test 3;0;Instance with ID: A1XC90Z;456;Instance with ID: FF-45-0Z',
+ ];
+ }
+
+ /**
+ * Provide values to filter and get non-empty values concatenated by default separator
+ *
+ * @return Generator
+ */
+ public function provideValuesToFilterNonEmptyAsStringUsingDefaultSeparator()
+ {
+ yield [
+ 'An empty array (no values to filter)',
+ [],
+ null,
+ ];
+
+ yield [
+ 'All values are empty',
+ [
+ '',
+ null,
+ [],
+ ],
+ '',
+ ];
+
+ yield [
+ '5 values with 2 empty strings',
+ [
+ 'test 1',
+ '',
+ 'test 2',
+ 'test 3',
+ '',
+ ],
+ 'test 1, test 2, test 3',
+ ];
+
+ yield [
+ 'Numbers with "0" that shouldn\'t be treated like an empty value',
+ [
+ 123,
+ 0,
+ 456,
+ ],
+ '123, 0, 456',
+ ];
+
+ yield [
+ 'Object shouldn\'t be treated like an empty value',
+ [
+ 'test 1',
+ new SimpleToString('1234'),
+ 'test 2',
+ null,
+ 'test 3',
+ ],
+ 'test 1, Instance with ID: 1234, test 2, test 3',
+ ];
+
+ yield [
+ 'Mixed values (non-empty, empty, strings, integers, objects)',
+ [
+ 'test 1',
+ '',
+ 123,
+ null,
+ 'test 2',
+ 'test 3',
+ 0,
+ new SimpleToString('A1XC90Z'),
+ 456,
+ [],
+ new SimpleToString('FF-45-0Z'),
+ ],
+ 'test 1, 123, test 2, test 3, 0, Instance with ID: A1XC90Z, 456, Instance with ID: FF-45-0Z',
+ ];
+ }
+
+ public function testAreAllKeysIntegers()
+ {
+ self::assertFalse(Arrays::areAllKeysIntegers([]));
+ self::assertEquals(1, Arrays::areAllKeysIntegers($this->simpleArray));
+ self::assertEquals(2, Arrays::areAllKeysIntegers($this->simpleArray));
+ self::assertEquals('', Arrays::areAllKeysIntegers($this->complexArray));
+ }
+
+ public function testAreAllKeysMatchedByPattern(): void
+ {
+ $pattern = '\d+';
+
+ // Empty array
+ self::assertFalse(Arrays::areAllKeysMatchedByPattern([], $pattern));
+
+ // Simple array with integers as keys only
+ self::assertTrue(Arrays::areAllKeysMatchedByPattern($this->simpleArray, $pattern));
+
+ // Complex array with strings and integers as keys
+ self::assertFalse(Arrays::areAllKeysMatchedByPattern($this->complexArray, $pattern));
+
+ $array = [
+ 'a' => 'b',
+ 'c' => 'd',
+ ];
+
+ // Yet another simple array, but with strings as keys
+ self::assertFalse(Arrays::areAllKeysMatchedByPattern($array, $pattern));
+
+ // The same array with another pattern
+ $pattern = '\w+';
+ self::assertTrue(Arrays::areAllKeysMatchedByPattern($array, $pattern));
+
+ // The same array with mixed keys (strings and integers as keys)
+ $array[1] = 'x';
+ $pattern = '\d+';
+ self::assertFalse(Arrays::areAllKeysMatchedByPattern($array, $pattern));
+
+ // Multidimensional array - negative case
+ $array['e'] = ['f' => 'g'];
+ self::assertFalse(Arrays::areAllKeysMatchedByPattern($array, $pattern));
+
+ // Multidimensional array - positive case
+ unset($array[1]);
+ $pattern = '\w+';
+ self::assertTrue(Arrays::areAllKeysMatchedByPattern($array, $pattern));
+ }
+
+ public function testAreAllValuesEmpty()
+ {
+ // Negative cases
+ self::assertFalse(Arrays::areAllValuesEmpty([]));
+ self::assertFalse(Arrays::areAllValuesEmpty([], true));
+ self::assertFalse(Arrays::areAllValuesEmpty($this->simpleArray));
+ self::assertFalse(Arrays::areAllValuesEmpty($this->simpleArray, true));
+
+ $array = [
+ null,
+ 0,
+ ];
+ self::assertFalse(Arrays::areAllValuesEmpty($array, true));
+
+ $array = [
+ null,
+ [
+ null,
+ ],
+ ];
+ self::assertFalse(Arrays::areAllValuesEmpty($array, true));
+
+ // Positive cases
+ $array = [
+ '',
+ 0,
+ ];
+ self::assertTrue(Arrays::areAllValuesEmpty($array));
+
+ $array = [
+ null,
+ null,
+ ];
+ self::assertTrue(Arrays::areAllValuesEmpty($array, true));
+ }
+
+ public function testAreKeysInArray(): void
+ {
+ // Negative cases
+ self::assertFalse(Arrays::areKeysInArray([], []));
+ self::assertFalse(Arrays::areKeysInArray([null], $this->simpleArray));
+ self::assertFalse(Arrays::areKeysInArray([''], $this->simpleArray));
+ self::assertFalse(Arrays::areKeysInArray(['dolorrr'], $this->simpleArrayWithKeys));
+
+ $keys1 = [
+ 1,
+ 3,
+ 9,
+ ];
+
+ self::assertFalse(Arrays::areKeysInArray($keys1, $this->simpleArray));
+ self::assertFalse(Arrays::areKeysInArray($keys1, $this->complexArray));
+ self::assertFalse(Arrays::areKeysInArray($keys1, $this->complexArray, false));
+
+ // Positive cases
+ $keys12 = [
+ 2,
+ 'mollis',
+ ];
+
+ $keys13 = [
+ 1,
+ 3,
+ ];
+
+ $keys14 = [
+ 'dolor',
+ 'amet',
+ ];
+
+ $keys15 = [
+ 'dolor',
+ 'amet',
+ ];
+
+ $keys16 = [
+ 'a' => 'lorem',
+ 11 => 'amet',
+ ];
+
+ $keys17 = [
+ 'a' => 'lorem',
+ 11 => 'amet',
+ 'c' => 'sit__',
+ ];
+
+ self::assertTrue(Arrays::areKeysInArray([1], $this->simpleArray));
+ self::assertTrue(Arrays::areKeysInArray($keys12, $this->simpleArray, false));
+ self::assertTrue(Arrays::areKeysInArray($keys12, $this->complexArray));
+ self::assertTrue(Arrays::areKeysInArray($keys13, $this->simpleArray));
+ self::assertTrue(Arrays::areKeysInArray($keys14, $this->simpleArrayWithKeys));
+ self::assertTrue(Arrays::areKeysInArray($keys15, $this->simpleArrayWithKeys));
+
+ self::assertTrue(Arrays::areKeysInArray(['a' => 'dolor'], $this->simpleArrayWithKeys));
+ self::assertTrue(Arrays::areKeysInArray(['a' => 'dolor'], $this->simpleArrayWithKeys, false));
+
+ self::assertTrue(Arrays::areKeysInArray($keys16, $this->complexArray));
+ self::assertTrue(Arrays::areKeysInArray($keys17, $this->complexArray, false));
+ }
+
+ public function testArray2JavaScript(): void
+ {
+ // Negative cases
self::assertNull(Arrays::array2JavaScript([]));
- /*
- * Positive cases
- */
+ // Positive cases
self::assertEquals('new Array(\'Lorem\', \'ipsum\', \'dolor\', \'sit\', \'amet\');', Arrays::array2JavaScript($this->simpleArray));
self::assertEquals('var letsTest = new Array(\'Lorem\', \'ipsum\', \'dolor\', \'sit\', \'amet\');', Arrays::array2JavaScript($this->simpleArray, 'letsTest'));
@@ -326,1038 +2410,29 @@ letsTest[2] = value_2;';
self::assertEquals($effect, Arrays::array2JavaScript($this->twoDimensionsArray, 'letsTest', true));
}
- /**
- * @param string $description Description of test case
- * @param array|null $expected Expected new array (with quoted elements)
- * @param array $array The array to check for string values
- *
- * @dataProvider provideArrayToQuoteStrings
- */
- public function testQuoteStrings($description, $expected, array $array)
+ public function testConstructor()
{
- self::assertSame($expected, Arrays::quoteStrings($array), $description);
- }
-
- public function testRemoveMarginalElement()
- {
- $array = $this->simpleArray;
- $string = 'Lorem ipsum';
-
- /*
- * Removing first element
- */
- self::assertSame([
- 0 => 'Lorem',
- 1 => 'ipsum',
- 2 => 'dolor',
- 3 => 'sit',
- ], Arrays::removeMarginalElement($array));
- self::assertEquals('Lorem ipsu', Arrays::removeMarginalElement($string));
-
- /*
- * Removing last element
- */
- self::assertSame([
- 1 => 'ipsum',
- 2 => 'dolor',
- 3 => 'sit',
- 4 => 'amet',
- ], Arrays::removeMarginalElement($array, false));
- self::assertEquals('orem ipsum', Arrays::removeMarginalElement($string, false));
- }
-
- public function testRemoveElements()
- {
- $array1 = $this->simpleArray;
- $array2 = $this->simpleArray;
-
- Arrays::removeElements($array1, 'ipsum');
- self::assertSame([
- 1 => 'ipsum',
- 2 => 'dolor',
- 3 => 'sit',
- 4 => 'amet',
- ], $array1);
-
- Arrays::removeElements($array2, 'sit', false);
- self::assertSame([
- 0 => 'Lorem',
- 1 => 'ipsum',
- 2 => 'dolor',
- 3 => 'sit',
- ], $array2);
-
- Arrays::removeElements($this->complexArray['lorem'], 'sit', false);
- self::assertSame(['ipsum' => ['dolor' => 'sit']], $this->complexArray['lorem']);
- }
-
- public function testRemoveElement()
- {
- self::assertFalse(Arrays::removeElement($this->simpleArray, 'eeee'));
- self::assertTrue(is_array(Arrays::removeElement($this->simpleArray, 'Lorem')));
-
- Arrays::removeElement($this->simpleArray, 'amet');
- self::assertFalse(isset($this->simpleArray['amet']));
- }
-
- public function testSetKeysAsValuesEmptyArray()
- {
- self::assertNull(Arrays::setKeysAsValues([]));
- }
-
- public function testSetKeysAsValuesSameKeysValues()
- {
- $array = [
- 0,
- 1,
- 2,
- 3,
- ];
-
- self::assertEquals($array, Arrays::setKeysAsValues($array));
+ static::assertHasNoConstructor(Arrays::class);
}
/**
- * @param array $array The array to change values with keys
- * @param array $replaced The array with replaced values with keys
+ * @param array $array
+ * @param bool $expected
*
- * @dataProvider provideSimpleArrayToSetKeysAsValues
+ * @dataProvider provideArrayToVerifyIfContainsEmptyStringsOnly
*/
- public function testSetKeysAsValuesSimpleArray($array, $replaced)
+ public function testContainsEmptyStringsOnly(array $array, bool $expected): void
{
- self::assertEquals($replaced, Arrays::setKeysAsValues($array));
- }
-
- public function testSetKeysAsValuesTwoDimensionsArray()
- {
- $replaced = [
- [
- 'lorem' => 0,
- 'ipsum' => 1,
- 'dolor' => 2,
- 'sit' => 3,
- 'amet' => 4,
- ],
- [
- 'consectetur' => 0,
- 'adipiscing' => 1,
- 'elit' => 2,
- ],
- [
- 'donec' => 0,
- 'sagittis' => 1,
- 'fringilla' => 2,
- 'eleifend' => 3,
- ],
- ];
-
- self::assertEquals($replaced, Arrays::setKeysAsValues($this->twoDimensionsArray));
- }
-
- /**
- * @param array $array The array to change values with keys
- * @param array $replaced The array with replaced values with keys
- *
- * @dataProvider provideArrayWithDuplicatedValuesToSetKeysAsValues
- */
- public function testSetKeysAsValuesDuplicatedValues($array, $replaced)
- {
- self::assertEquals($replaced, Arrays::setKeysAsValues($array, false));
- }
-
- public function testGetNonArrayElementsCount()
- {
- /*
- * Negative cases
- */
- self::assertNull(Arrays::getNonArrayElementsCount([]));
-
- /*
- * Positive cases
- */
- self::assertEquals(5, Arrays::getNonArrayElementsCount($this->simpleArray));
- self::assertEquals(3, Arrays::getNonArrayElementsCount($this->simpleArrayWithKeys));
- self::assertEquals(12, Arrays::getNonArrayElementsCount($this->twoDimensionsArray));
- }
-
- public function testString2array()
- {
- /*
- * Negative cases
- */
- self::assertNull(Arrays::string2array(''));
- self::assertNull(Arrays::string2array(null));
-
- /*
- * Positive cases
- */
- $array = [
- 'light' => '#fff',
- 'dark' => '#000',
- ];
-
- self::assertEquals($array, Arrays::string2array('light:#fff|dark:#000'));
- self::assertEquals($array, Arrays::string2array('light: #fff | dark: #000'));
-
- $array = [
- 'red' => '#f00',
- 'green' => '#0f0',
- 'blue' => '#00f',
- ];
-
- self::assertEquals($array, Arrays::string2array('red:#f00|green:#0f0|blue:#00f'));
- self::assertEquals($array, Arrays::string2array('red: #f00 | green: #0f0 | blue: #00f'));
- self::assertEquals($array, Arrays::string2array('red : #f00 | green : #0f0 | blue : #00f'));
- }
-
- public function testAreKeysInArray()
- {
- /*
- * Negative cases
- */
- self::assertFalse(Arrays::areKeysInArray([], []));
- self::assertFalse(Arrays::areKeysInArray([null], $this->simpleArray));
- self::assertFalse(Arrays::areKeysInArray([''], $this->simpleArray));
- self::assertFalse(Arrays::areKeysInArray(['dolorrr'], $this->simpleArrayWithKeys));
-
- $keys1 = [
- 1,
- 3,
- 9,
- ];
-
- self::assertFalse(Arrays::areKeysInArray($keys1, $this->simpleArray));
- self::assertFalse(Arrays::areKeysInArray($keys1, $this->complexArray));
- self::assertFalse(Arrays::areKeysInArray($keys1, $this->complexArray, false));
-
- /*
- * Positive cases
- */
- $keys12 = [
- 2,
- 'mollis',
- ];
-
- $keys13 = [
- 1,
- 3,
- ];
-
- $keys14 = [
- 'dolor',
- 'amet',
- ];
-
- $keys15 = [
- 'dolor',
- 'amet',
- ];
-
- $keys16 = [
- 'a' => 'lorem',
- 11 => 'amet',
- ];
-
- $keys17 = [
- 'a' => 'lorem',
- 11 => 'amet',
- 'c' => 'sit__',
- ];
-
- self::assertTrue(Arrays::areKeysInArray([1], $this->simpleArray));
- self::assertTrue(Arrays::areKeysInArray($keys12, $this->simpleArray, false));
- self::assertTrue(Arrays::areKeysInArray($keys12, $this->complexArray));
- self::assertTrue(Arrays::areKeysInArray($keys13, $this->simpleArray));
- self::assertTrue(Arrays::areKeysInArray($keys14, $this->simpleArrayWithKeys));
- self::assertTrue(Arrays::areKeysInArray($keys15, $this->simpleArrayWithKeys));
-
- self::assertTrue(Arrays::areKeysInArray(['a' => 'dolor'], $this->simpleArrayWithKeys));
- self::assertTrue(Arrays::areKeysInArray(['a' => 'dolor'], $this->simpleArrayWithKeys, false));
-
- self::assertTrue(Arrays::areKeysInArray($keys16, $this->complexArray));
- self::assertTrue(Arrays::areKeysInArray($keys17, $this->complexArray, false));
- }
-
- public function testGetLastElementsPathsUsingEmptyArray()
- {
- self::assertNull(Arrays::getLastElementsPaths([]));
- }
-
- public function testGetLastElementsPathsUsingDefaults()
- {
- /*
- * Using default separator and other default arguments
- */
- $expected = [
- 'lorem.ipsum.dolor' => 'sit',
- 'lorem.ipsum.diam.non' => 'egestas',
- 'consectetur' => 'adipiscing',
- 'mollis' => 1234,
- 2 => [],
- 'sit.nullam' => 'donec',
- 'sit.aliquet.vitae.ligula' => 'quis',
- 'sit.0' => 'elit',
- 'amet.0' => 'iaculis',
- 'amet.1' => 'primis',
- ];
-
- self::assertEquals($expected, Arrays::getLastElementsPaths($this->complexArray));
- }
-
- public function testGetLastElementsPathsUsingCustomSeparator()
- {
- /*
- * Using custom separator
- */
- $separator = ' -> ';
- $expected = [
- sprintf('lorem%sipsum%sdolor', $separator, $separator) => 'sit',
- sprintf('lorem%sipsum%sdiam%snon', $separator, $separator, $separator) => 'egestas',
- 'consectetur' => 'adipiscing',
- 'mollis' => 1234,
- 2 => [],
- sprintf('sit%snullam', $separator) => 'donec',
- sprintf('sit%saliquet%svitae%sligula', $separator, $separator, $separator) => 'quis',
- sprintf('sit%s0', $separator) => 'elit',
- sprintf('amet%s0', $separator) => 'iaculis',
- sprintf('amet%s1', $separator) => 'primis',
- ];
-
- self::assertEquals($expected, Arrays::getLastElementsPaths($this->complexArray, $separator));
- }
-
- /**
- * @param string|array $stopIfMatchedBy 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)
- * @param string $separator Separator used in resultant strings. Default: ".".
- * @param array $expected Expected array
- *
- * @dataProvider provideStopIfMatchedByForGetLastElementsPaths
- */
- public function testGetLastElementsPathsUsingStopIfMatchedBy($stopIfMatchedBy, $separator, array $expected)
- {
- self::assertEquals($expected, Arrays::getLastElementsPaths($this->superComplexArray, $separator, '', $stopIfMatchedBy));
- }
-
- public function testAreAllKeysMatchedByPattern()
- {
- $pattern = '\d+';
-
- /*
- * Empty array
- */
- self::assertFalse(Arrays::areAllKeysMatchedByPattern([], $pattern));
-
- /*
- * Simple array with integers as keys only
- */
- self::assertTrue(Arrays::areAllKeysMatchedByPattern($this->simpleArray, $pattern));
-
- /*
- * Complex array with strings and integers as keys
- */
- self::assertFalse(Arrays::areAllKeysMatchedByPattern($this->complexArray, $pattern));
-
- $array = [
- 'a' => 'b',
- 'c' => 'd',
- ];
-
- /*
- * Yet another simple array, but with strings as keys
- */
- self::assertFalse(Arrays::areAllKeysMatchedByPattern($array, $pattern));
-
- /*
- * The same array with another pattern
- */
- $pattern = '\w+';
- self::assertTrue(Arrays::areAllKeysMatchedByPattern($array, $pattern));
-
- /*
- * The same array with mixed keys (strings and integers as keys)
- */
- $array[1] = 'x';
- $pattern = '\d+';
- self::assertFalse(Arrays::areAllKeysMatchedByPattern($array, $pattern));
-
- /*
- * Multidimensional array - negative case
- */
- $array['e'] = ['f' => 'g'];
- self::assertFalse(Arrays::areAllKeysMatchedByPattern($array, $pattern));
-
- /*
- * Multidimensional array - positive case
- */
- unset($array[1]);
- $pattern = '\w+';
- self::assertTrue(Arrays::areAllKeysMatchedByPattern($array, $pattern));
- }
-
- public function testAreAllKeysIntegers()
- {
- self::assertFalse(Arrays::areAllKeysIntegers([]));
- self::assertEquals(1, Arrays::areAllKeysIntegers($this->simpleArray));
- self::assertEquals(2, Arrays::areAllKeysIntegers($this->simpleArray));
- self::assertEquals('', Arrays::areAllKeysIntegers($this->complexArray));
- }
-
- public function testIssetRecursive()
- {
- /*
- * Negative cases
- */
- self::assertFalse(Arrays::issetRecursive([], []));
-
- /*
- * Positive cases
- */
- $unExistingKeys = [
- 'a',
- 'b',
- 3,
- ];
-
- $existingKeys = [
- 'simpleArray' => [
- 1,
- 3,
- 4,
- ],
- 'simpleArrayWithKeys' => [
- 'dolor',
- 'amet',
- ],
- 'twoDimensionsArray' => [
- 2,
- 3,
- ],
- 'complexArray' => [
- 'sit',
- 'aliquet',
- 'vitae',
- ],
- ];
-
- self::assertFalse(Arrays::issetRecursive($this->simpleArray, $unExistingKeys));
- self::assertTrue(Arrays::issetRecursive($this->simpleArray, $existingKeys['simpleArray']));
-
- self::assertFalse(Arrays::issetRecursive($this->simpleArrayWithKeys, $unExistingKeys));
- self::assertTrue(Arrays::issetRecursive($this->simpleArrayWithKeys, $existingKeys['simpleArrayWithKeys']));
-
- self::assertFalse(Arrays::issetRecursive($this->twoDimensionsArray, $unExistingKeys));
- self::assertTrue(Arrays::issetRecursive($this->twoDimensionsArray, $existingKeys['twoDimensionsArray']));
-
- self::assertFalse(Arrays::issetRecursive($this->complexArray, $unExistingKeys));
- self::assertTrue(Arrays::issetRecursive($this->complexArray, $existingKeys['complexArray']));
- }
-
- public function testGetValueByKeysPath()
- {
- /*
- * Negative cases
- */
- self::assertNull(Arrays::getValueByKeysPath([], []));
-
- /*
- * Positive cases
- */
- self::assertNull(Arrays::getValueByKeysPath($this->simpleArray, []));
- self::assertEquals('ipsum', Arrays::getValueByKeysPath($this->simpleArray, [1]));
- self::assertEquals('sit', Arrays::getValueByKeysPath($this->simpleArray, [3]));
- self::assertEquals('sit', Arrays::getValueByKeysPath($this->simpleArrayWithKeys, ['dolor']));
-
- $keys = [
- 'twoDimensionsArray' => [
- 2,
- 2,
- ],
- 'complexArray' => [
- [
- 'lorem',
- 'ipsum',
- 'diam',
- ],
- [
- 'sit',
- 'aliquet',
- ],
- ],
- ];
-
- $value = [
- [
- 'non' => 'egestas',
- ],
- [
- 'vitae' => [
- 'ligula' => 'quis',
- ],
- ],
- ];
-
- self::assertEquals('fringilla', Arrays::getValueByKeysPath($this->twoDimensionsArray, $keys['twoDimensionsArray']));
- self::assertEquals($value[0], Arrays::getValueByKeysPath($this->complexArray, $keys['complexArray'][0]));
- self::assertEquals($value[1], Arrays::getValueByKeysPath($this->complexArray, $keys['complexArray'][1]));
- }
-
- public function testGetAllValuesOfKeyEmptyValue()
- {
- self::assertNull(Arrays::getAllValuesOfKey([], ''));
- self::assertNull(Arrays::getAllValuesOfKey([], 'test'));
- }
-
- public function testGetAllValuesOfKeyNotExistingKey()
- {
- self::assertNull(Arrays::getAllValuesOfKey([], 'ipsum'));
- self::assertEquals([], Arrays::getAllValuesOfKey($this->simpleArray, 'ipsum'));
- }
-
- public function testGetAllValuesOfKey()
- {
- /*
- * Positive case - 1-dimension array
- */
- self::assertEquals(['ipsum'], Arrays::getAllValuesOfKey($this->simpleArray, 1));
-
- /*
- * Positive case - 2-dimensions array
- */
- $effect = [
- [
- 'lorem',
- 'ipsum',
- 'dolor',
- 'sit',
- 'amet',
- ],
- 1 => 'consectetur',
- 2 => 'donec',
- ];
-
- self::assertEquals($effect, Arrays::getAllValuesOfKey($this->twoDimensionsArray, 0));
-
- /*
- * Positive case - multi-dimensions array
- */
- self::assertEquals(['primis'], Arrays::getAllValuesOfKey($this->complexArray, 1));
-
- /*
- * Positive case - multi-dimensions array
- */
- $effect = [
- 0 => [
- 'in' => [
- 'dui',
- 'dolor' => [
- 'aliquam',
- ],
- ],
- ],
- ];
-
- self::assertEquals($effect, Arrays::getAllValuesOfKey($this->superComplexArray, 'tortor'));
- }
-
- public function testKsortRecursive()
- {
- /*
- * Negative cases
- */
- $array = [];
- self::assertNull(Arrays::ksortRecursive($array));
-
- /*
- * Positive cases
- */
- self::assertEquals($this->simpleArray, Arrays::ksortRecursive($this->simpleArray));
- self::assertEquals($this->simpleArray, Arrays::ksortRecursive($this->simpleArray, SORT_NUMERIC));
- self::assertEquals($this->twoDimensionsArray, Arrays::ksortRecursive($this->twoDimensionsArray));
-
- /*
- * Positive case - multi-dimensions array
- */
- $effect = [
- 'amet' => [
- 'iaculis',
- 'primis',
- ],
- 'consectetur' => 'adipiscing',
- 'lorem' => [
- 'ipsum' => [
- 'dolor' => 'sit',
- 'diam' => [
- 'non' => 'egestas',
- ],
- ],
- ],
- 'mollis' => 1234,
- 'sit' => [
- 'nullam' => 'donec',
- 'aliquet' => [
- 'vitae' => [
- 'ligula' => 'quis',
- ],
- ],
- 'elit',
- ],
- 2 => [],
- ];
-
- self::assertEquals($effect, Arrays::ksortRecursive($this->complexArray));
-
- /*
- * Positive case - multi-dimensions array - with options of ksort() function
- */
- $effect = [
- 2 => [],
- 'amet' => [
- 'iaculis',
- 'primis',
- ],
- 'consectetur' => 'adipiscing',
- 'lorem' => [
- 'ipsum' => [
- 'dolor' => 'sit',
- 'diam' => [
- 'non' => 'egestas',
- ],
- ],
- ],
- 'mollis' => 1234,
- 'sit' => [
- 'nullam' => 'donec',
- 'aliquet' => [
- 'vitae' => [
- 'ligula' => 'quis',
- ],
- ],
- 'elit',
- ],
- ];
-
- self::assertEquals($effect, Arrays::ksortRecursive($this->complexArray, SORT_STRING & SORT_NATURAL));
- }
-
- public function testSetPositions()
- {
- /*
- * Negative cases
- */
- self::assertNull(Arrays::setPositions([]));
-
- /*
- * Positive case - 1-dimension array
- */
- $array = [
- 'abc',
- ];
-
- self::assertEquals($array, Arrays::setPositions($array));
-
- /*
- * Positive case - 2-dimensions array
- */
- $effect = $this->twoDimensionsArray;
- $effect[0][Arrays::POSITION_KEY_NAME] = 1;
- $effect[1][Arrays::POSITION_KEY_NAME] = 2;
- $effect[2][Arrays::POSITION_KEY_NAME] = 3;
-
- self::assertEquals($effect, Arrays::setPositions($this->twoDimensionsArray));
-
- /*
- * Positive case - multi-level array
- */
- $array = [
- 'lorem',
- 'ipsum' => [
- 'dolor',
- 'sit',
- ],
- 'amet' => [
- 'consectetur',
- 'adipiscing' => [
- 'elit' => [
- 'cras',
- 'quis',
- 'ligula',
- ],
- ],
- ],
- ];
-
- $effect = [
- 'lorem',
- 'ipsum' => [
- 'dolor',
- 'sit',
- Arrays::POSITION_KEY_NAME => 1,
- ],
- 'amet' => [
- 'consectetur',
- 'adipiscing' => [
- 'elit' => [
- 'cras',
- 'quis',
- 'ligula',
- Arrays::POSITION_KEY_NAME => 1,
- ],
- Arrays::POSITION_KEY_NAME => 1,
- ],
- Arrays::POSITION_KEY_NAME => 2,
- ],
- ];
-
- self::assertEquals($effect, Arrays::setPositions($array));
-
- /*
- * Positive case - non-default name of key with position value & 2-dimensions array
- */
- $keyName = 'level';
- $effect = $this->twoDimensionsArray;
-
- $effect[0][$keyName] = 1;
- $effect[1][$keyName] = 2;
- $effect[2][$keyName] = 3;
-
- self::assertEquals($effect, Arrays::setPositions($this->twoDimensionsArray, $keyName));
-
- /*
- * Positive case - non-default start value of position & 2-dimensions array
- */
- $startPosition = 5;
- $effect = $this->twoDimensionsArray;
-
- $effect[Arrays::POSITION_KEY_NAME] = $startPosition;
- $effect[0][Arrays::POSITION_KEY_NAME] = 1;
- $effect[1][Arrays::POSITION_KEY_NAME] = 2;
- $effect[2][Arrays::POSITION_KEY_NAME] = 3;
-
- self::assertEquals($effect, Arrays::setPositions($this->twoDimensionsArray, Arrays::POSITION_KEY_NAME, $startPosition));
- }
-
- public function testTrimRecursive()
- {
- /*
- * Negative cases
- */
- self::assertSame([], Arrays::trimRecursive([]));
-
- /*
- * Positive cases
- */
- self::assertEquals(['a'], Arrays::trimRecursive([' a ']));
- self::assertEquals([
- 'a',
- 'b',
- ], Arrays::trimRecursive([
- ' a ',
- 'b ',
- ]));
-
- $array = [
- 'abc ',
- [
- 'def',
- 'ghi ',
- ],
- ];
-
- $result = [
- 'abc',
- [
- 'def',
- 'ghi',
- ],
- ];
-
- self::assertEquals($result, Arrays::trimRecursive($array));
-
- $array = [
- 'abc ',
- [
- ' def ',
- 'ghi ',
- 'oo' => [
- ' ee ',
- 'g' => 'h hhh ',
- ],
- ],
- ];
-
- $result = [
- 'abc',
- [
- 'def',
- 'ghi',
- 'oo' => [
- 'ee',
- 'g' => 'h hhh',
- ],
- ],
- ];
-
- self::assertEquals($result, Arrays::trimRecursive($array));
- }
-
- public function testSortByCustomKeysOrder()
- {
- /*
- * Negative cases
- */
- self::assertNull(Arrays::sortByCustomKeysOrder([], []));
-
- /*
- * Positive cases
- */
- self::assertEquals([0], Arrays::sortByCustomKeysOrder([0], []));
- self::assertEquals($this->simpleArray, Arrays::sortByCustomKeysOrder($this->simpleArray, []));
-
- $keysOrder = [
- 'amet',
- 'dolor',
- 'Lorem',
- ];
-
- $sorted = [
- 'dolor' => 'sit',
- 'amet' => 'consectetur',
- 'Lorem' => 'ipsum',
- ];
-
- self::assertEquals($sorted, Arrays::sortByCustomKeysOrder($this->simpleArrayWithKeys, $keysOrder));
-
- $array = [
- 'Lorem',
- 'ipsum',
- 'dolor',
- 'sit',
- 'amet',
- ];
-
- $keysOrder = [
- 0,
- 3,
- 1,
- 2,
- ];
-
- $sorted = [
- 0 => 'Lorem',
- 3 => 'sit',
- 1 => 'ipsum',
- 2 => 'dolor',
- 4 => 'amet',
- ];
-
- self::assertEquals($sorted, Arrays::sortByCustomKeysOrder($array, $keysOrder));
-
- $array = [
- 'Lorem',
- 'ipsum',
- 'dolor',
- 'sit',
- 'amet',
- ];
-
- $keysOrder = [
- 0,
- 3,
- ];
-
- $sorted = [
- 0 => 'Lorem',
- 3 => 'sit',
- 1 => 'ipsum',
- 2 => 'dolor',
- 4 => 'amet',
- ];
-
- self::assertEquals($sorted, Arrays::sortByCustomKeysOrder($array, $keysOrder));
- }
-
- public function testImplodeSmart()
- {
- $separator = '/';
-
- /*
- * Empty array
- */
- self::assertNull(Arrays::implodeSmart([], $separator));
-
- /*
- * Simple, one-dimension array
- */
- self::assertEquals(implode($separator, $this->simpleArray), Arrays::implodeSmart($this->simpleArray, $separator));
-
- /*
- * An array with elements that contain separator
- */
- $array = [
- 'lorem' . $separator,
- 'ipsum',
- $separator . 'dolor',
- ];
-
- self::assertEquals(implode($separator, [
- 'lorem',
- 'ipsum',
- 'dolor',
- ]), Arrays::implodeSmart($array, $separator));
-
- /*
- * Complex array
- */
- self::assertEquals(implode($separator, [
- 'donec',
- 'quis',
- 'elit',
- ]), Arrays::implodeSmart($this->complexArray['sit'], $separator));
- }
-
- public function testGetNextElement()
- {
- /*
- * Negative cases
- */
- self::assertNull(Arrays::getNextElement($this->simpleArray, 'amet'));
- self::assertNull(Arrays::getNextElement($this->simpleArray, 'xyz'));
- self::assertNull(Arrays::getNextElement($this->simpleArray, 0));
- self::assertNull(Arrays::getNextElement([], ''));
- self::assertNull(Arrays::getNextElement([], null));
-
- /*
- * Positive cases
- */
- self::assertEquals('ipsum', Arrays::getNextElement($this->simpleArray, 'Lorem'));
- self::assertEquals('sit', Arrays::getNextElement($this->simpleArray, 'dolor'));
- }
-
- public function testGetPreviousElement()
- {
- /*
- * Negative cases
- */
- self::assertNull(Arrays::getPreviousElement($this->simpleArray, 'Lorem'));
- self::assertNull(Arrays::getPreviousElement($this->simpleArray, 'xyz'));
- self::assertNull(Arrays::getPreviousElement($this->simpleArray, 0));
- self::assertNull(Arrays::getPreviousElement([], ''));
- self::assertNull(Arrays::getPreviousElement([], null));
-
- /*
- * Positive cases
- */
- self::assertEquals('ipsum', Arrays::getPreviousElement($this->simpleArray, 'dolor'));
- self::assertEquals('sit', Arrays::getPreviousElement($this->simpleArray, 'amet'));
- }
-
- public function testGetIndexOf()
- {
- /*
- * Negative cases
- */
- self::assertFalse(Arrays::getIndexOf([], 'a'));
- self::assertNull(Arrays::getIndexOf($this->simpleArray, 'loremmm'));
-
- /*
- * Positive cases
- */
- self::assertEquals(1, Arrays::getIndexOf($this->simpleArray, 'ipsum'));
- self::assertEquals('dolor', Arrays::getIndexOf($this->simpleArrayWithKeys, 'sit'));
- self::assertEquals('mollis', Arrays::getIndexOf($this->complexArray, 1234));
- }
-
- public function testIncrementIndexes()
- {
- /*
- * Negative cases
- */
- self::assertNull(Arrays::incrementIndexes([]));
-
- /*
- * Positive cases
- */
- $array = [
- 1 => 'Lorem',
- 2 => 'ipsum',
- 3 => 'dolor',
- 4 => 'sit',
- 5 => 'amet',
- ];
- self::assertEquals($array, Arrays::incrementIndexes($this->simpleArray));
-
- $array = [
- 0 => 'Lorem',
- 2 => 'ipsum',
- 3 => 'dolor',
- 4 => 'sit',
- 5 => 'amet',
- ];
- self::assertEquals($array, Arrays::incrementIndexes($this->simpleArray, 1));
-
- $array = [
- 0 => 'Lorem',
- 1 => 'ipsum',
- 3 => 'dolor',
- 4 => 'sit',
- 5 => 'amet',
- ];
- self::assertEquals($array, Arrays::incrementIndexes($this->simpleArray, 2));
- }
-
- public function testAreAllValuesEmpty()
- {
- /*
- * Negative cases
- */
- self::assertFalse(Arrays::areAllValuesEmpty([]));
- self::assertFalse(Arrays::areAllValuesEmpty([], true));
- self::assertFalse(Arrays::areAllValuesEmpty($this->simpleArray));
- self::assertFalse(Arrays::areAllValuesEmpty($this->simpleArray, true));
-
- $array = [
- null,
- 0,
- ];
- self::assertFalse(Arrays::areAllValuesEmpty($array, true));
-
- $array = [
- null,
- [
- null,
- ],
- ];
- self::assertFalse(Arrays::areAllValuesEmpty($array, true));
-
- /*
- * Positive cases
- */
- $array = [
- '',
- 0,
- ];
- self::assertTrue(Arrays::areAllValuesEmpty($array));
-
- $array = [
- null,
- null,
- ];
- self::assertTrue(Arrays::areAllValuesEmpty($array, true));
+ static::assertSame($expected, Arrays::containsEmptyStringsOnly($array));
}
public function testDiffRecursive()
{
- /*
- * Negative cases
- */
+ // Negative cases
self::assertEquals([], Arrays::arrayDiffRecursive([], []));
self::assertEquals([], Arrays::arrayDiffRecursive([], [], true));
- /*
- * Positive cases - full comparison (keys and values)
- */
+ // Positive cases - full comparison (keys and values)
self::assertEquals(['a'], Arrays::arrayDiffRecursive(['a'], []));
self::assertEquals([], Arrays::arrayDiffRecursive([], ['a']));
self::assertEquals([], Arrays::arrayDiffRecursive($this->simpleArray, $this->simpleArray));
@@ -1410,9 +2485,7 @@ letsTest[2] = value_2;';
self::assertEquals($this->twoDimensionsArray[1], Arrays::arrayDiffRecursive($this->twoDimensionsArray[1], $this->twoDimensionsArray));
- /*
- * Positive cases - simple comparison (values only)
- */
+ // Positive cases - simple comparison (values only)
self::assertEquals(['a'], Arrays::arrayDiffRecursive(['a'], [], true));
$array = [
@@ -1509,47 +2582,454 @@ letsTest[2] = value_2;';
self::assertEquals($diff, Arrays::arrayDiffRecursive($array, $this->twoDimensionsArray, true));
}
+ public function testGetAllValuesOfKey()
+ {
+ // Positive case - 1-dimension array
+ self::assertEquals(['ipsum'], Arrays::getAllValuesOfKey($this->simpleArray, 1));
+
+ // Positive case - 2-dimensions array
+ $effect = [
+ [
+ 'lorem',
+ 'ipsum',
+ 'dolor',
+ 'sit',
+ 'amet',
+ ],
+ 1 => 'consectetur',
+ 2 => 'donec',
+ ];
+
+ self::assertEquals($effect, Arrays::getAllValuesOfKey($this->twoDimensionsArray, 0));
+
+ // Positive case - multi-dimensions array
+ self::assertEquals(['primis'], Arrays::getAllValuesOfKey($this->complexArray, 1));
+
+ // Positive case - multi-dimensions array
+ $effect = [
+ 0 => [
+ 'in' => [
+ 'dui',
+ 'dolor' => [
+ 'aliquam',
+ ],
+ ],
+ ],
+ ];
+
+ self::assertEquals($effect, Arrays::getAllValuesOfKey($this->superComplexArray, 'tortor'));
+ }
+
+ public function testGetAllValuesOfKeyEmptyValue()
+ {
+ self::assertNull(Arrays::getAllValuesOfKey([], ''));
+ self::assertNull(Arrays::getAllValuesOfKey([], 'test'));
+ }
+
+ public function testGetAllValuesOfKeyNotExistingKey()
+ {
+ self::assertNull(Arrays::getAllValuesOfKey([], 'ipsum'));
+ self::assertEquals([], Arrays::getAllValuesOfKey($this->simpleArray, 'ipsum'));
+ }
+
public function testGetDimensionsCount()
{
- /*
- * Basic cases
- */
+ // Basic cases
self::assertEquals(0, Arrays::getDimensionsCount([]));
self::assertEquals(1, Arrays::getDimensionsCount(['']));
- /*
- * Simple cases
- */
+ // Simple cases
self::assertEquals(1, Arrays::getDimensionsCount($this->simpleArray));
self::assertEquals(1, Arrays::getDimensionsCount($this->simpleArrayWithKeys));
- /*
- * Complex cases
- */
+ // Complex cases
self::assertEquals(2, Arrays::getDimensionsCount($this->twoDimensionsArray));
self::assertEquals(4, Arrays::getDimensionsCount($this->complexArray));
}
- public function testIsMultiDimensional()
+ public function testGetElementsFromLevel(): void
{
- /*
- * Negative cases
- */
- self::assertNull(Arrays::isMultiDimensional([]));
+ $array = [
+ // Level 1:
+ 'ab',
+ [
+ // Level 2:
+ 'cd',
+ 'ef',
+ ],
- /*
- * Positive cases
- */
- self::assertFalse(Arrays::isMultiDimensional($this->simpleArray));
- self::assertFalse(Arrays::isMultiDimensional($this->simpleArrayWithKeys));
+ // Level 1:
+ [
+ // Level 2:
+ 'gh',
+ [
+ // Level 3:
+ 'ij',
+ 'kl',
+ ],
+ ],
- self::assertTrue(Arrays::isMultiDimensional($this->twoDimensionsArray));
- self::assertTrue(Arrays::isMultiDimensional($this->complexArray));
+ // Level 1:
+ [
+ // Level 2:
+ [
+ // Level 3:
+ 'mn',
+ 'op',
+ ],
+ ],
+ ];
+
+ $expectedLevel1 = [
+ 'ab',
+ [
+ 'cd',
+ 'ef',
+ ],
+ [
+ 'gh',
+ [
+ 'ij',
+ 'kl',
+ ],
+ ],
+ [
+ [
+ 'mn',
+ 'op',
+ ],
+ ],
+ ];
+
+ $expectedLevel2 = [
+ 'cd',
+ 'ef',
+ 'gh',
+ [
+ 'ij',
+ 'kl',
+ ],
+ [
+ 'mn',
+ 'op',
+ ],
+ ];
+
+ $expectedLevel3 = [
+ 'ij',
+ 'kl',
+ 'mn',
+ 'op',
+ ];
+
+ self::assertSame($expectedLevel1, Arrays::getElementsFromLevel($array, 1));
+ self::assertSame($expectedLevel2, Arrays::getElementsFromLevel($array, 2));
+ self::assertSame($expectedLevel3, Arrays::getElementsFromLevel($array, 3));
}
- public function testGetNonEmptyValuesUsingEmptyArray()
+ public function testGetElementsFromLevelIfArrayHasOneLevelOnly(): void
{
- self::assertNull(Arrays::getNonEmptyValues([]));
+ $array = [
+ // Level 1:
+ 'ab',
+ 'cd',
+ 'ef',
+ ];
+
+ self::assertSame($array, Arrays::getElementsFromLevel($array, 1));
+ }
+
+ public function testGetElementsFromLevelIfArrayIsEmpty(): void
+ {
+ self::assertNull(Arrays::getElementsFromLevel([], -1));
+ self::assertNull(Arrays::getElementsFromLevel([], 0));
+ self::assertNull(Arrays::getElementsFromLevel([], 1));
+ }
+
+ public function testGetElementsFromLevelIfGivenKeyDoesNotExist(): void
+ {
+ $array = [
+ 'test1' => [1, 2, 3],
+ 'test2' => [4, 5, 6],
+ 'test3' => [
+ 'xy',
+ 'test4' => [7, 8, 9],
+ 'test5' => [
+ 'test6' => [10, 11, 12],
+ ],
+ ],
+ ];
+
+ self::assertSame([], Arrays::getElementsFromLevel($array, 2, 'X'));
+ }
+
+ public function testGetElementsFromLevelIfGivenLevelIsNotPositiveValue(): void
+ {
+ self::assertNull(Arrays::getElementsFromLevel([1, 2, 3], -1));
+ self::assertNull(Arrays::getElementsFromLevel([1, 2, 3], 0));
+ }
+
+ public function testGetElementsFromLevelIfThereIsNoGivenLevel(): void
+ {
+ self::assertSame([], Arrays::getElementsFromLevel([1, 2, 3], 9999));
+ }
+
+ public function testGetElementsFromLevelWithGivenKey(): void
+ {
+ $array = [
+ // Level 1:
+ [
+ 'a',
+ 'b',
+
+ // Level 2:
+ 'c' => [
+ 1,
+ 2,
+
+ // Level 3:
+ 'c' => [
+ 4,
+ 5,
+ ],
+ ],
+ ],
+
+ // Level 1:
+ [
+ 'd',
+ 'e',
+
+ // Level 2:
+ 'c' => [
+ 6,
+ 7,
+
+ // Level 3:
+ 'c' => [
+ 8,
+ 9,
+ ],
+ ],
+ ],
+ ];
+
+ $expected2 = [
+ [
+ 1,
+ 2,
+ 'c' => [
+ 4,
+ 5,
+ ],
+ ],
+ [
+ 6,
+ 7,
+ 'c' => [
+ 8,
+ 9,
+ ],
+ ],
+ ];
+
+ $expected3 = [
+ [
+ 4,
+ 5,
+ ],
+ [
+ 8,
+ 9,
+ ],
+ ];
+
+ self::assertSame([], Arrays::getElementsFromLevel($array, 1, 'c'));
+ self::assertSame($expected2, Arrays::getElementsFromLevel($array, 2, 'c'));
+ self::assertSame($expected3, Arrays::getElementsFromLevel($array, 3, 'c'));
+ self::assertSame([], Arrays::getElementsFromLevel($array, 4, 'c'));
+ }
+
+ /**
+ * @param string $description
+ * @param $expected
+ * @param array $array
+ * @param null|bool $firstLevelOnly
+ *
+ * @dataProvider provideFirstElement
+ */
+ public function testGetFirstElement(
+ string $description,
+ $expected,
+ array $array,
+ ?bool $firstLevelOnly = null
+ ): void {
+ if (null === $firstLevelOnly) {
+ static::assertSame($expected, Arrays::getFirstElement($array), $description);
+
+ return;
+ }
+
+ static::assertSame($expected, Arrays::getFirstElement($array, $firstLevelOnly), $description);
+ }
+
+ public function testGetFirstKey()
+ {
+ // Negative cases
+ self::assertNull(Arrays::getFirstKey([]));
+
+ // Positive cases
+ self::assertEquals(0, Arrays::getFirstKey($this->simpleArray));
+ self::assertEquals('lorem', Arrays::getFirstKey($this->complexArray));
+ }
+
+ public function testGetIndexOf()
+ {
+ // Negative cases
+ self::assertFalse(Arrays::getIndexOf([], 'a'));
+ self::assertNull(Arrays::getIndexOf($this->simpleArray, 'loremmm'));
+
+ // Positive cases
+ self::assertEquals(1, Arrays::getIndexOf($this->simpleArray, 'ipsum'));
+ self::assertEquals('dolor', Arrays::getIndexOf($this->simpleArrayWithKeys, 'sit'));
+ self::assertEquals('mollis', Arrays::getIndexOf($this->complexArray, 1234));
+ }
+
+ /**
+ * @param string $description
+ * @param $expected
+ * @param array $array
+ * @param null|bool $firstLevelOnly
+ *
+ * @dataProvider provideLastElement
+ */
+ public function testGetLastElement(
+ string $description,
+ $expected,
+ array $array,
+ ?bool $firstLevelOnly = null
+ ): void {
+ if (null === $firstLevelOnly) {
+ static::assertSame($expected, Arrays::getLastElement($array), $description);
+
+ return;
+ }
+
+ static::assertSame($expected, Arrays::getLastElement($array, $firstLevelOnly), $description);
+ }
+
+ public function testGetLastElementBreadCrumb()
+ {
+ self::assertNull(Arrays::getLastElementBreadCrumb([]));
+ self::assertEquals('4/amet', Arrays::getLastElementBreadCrumb($this->simpleArray));
+ self::assertEquals('2/3/eleifend', Arrays::getLastElementBreadCrumb($this->twoDimensionsArray));
+ self::assertEquals('amet/1/primis', Arrays::getLastElementBreadCrumb($this->complexArray));
+ }
+
+ public function testGetLastElementsPathsUsingCustomSeparator(): void
+ {
+ // Using custom separator
+ $separator = ' -> ';
+ $expected = [
+ sprintf('lorem%sipsum%sdolor', $separator, $separator) => 'sit',
+ sprintf('lorem%sipsum%sdiam%snon', $separator, $separator, $separator) => 'egestas',
+ 'consectetur' => 'adipiscing',
+ 'mollis' => 1234,
+ 2 => [],
+ sprintf('sit%snullam', $separator) => 'donec',
+ sprintf('sit%saliquet%svitae%sligula', $separator, $separator, $separator) => 'quis',
+ sprintf('sit%s0', $separator) => 'elit',
+ sprintf('amet%s0', $separator) => 'iaculis',
+ sprintf('amet%s1', $separator) => 'primis',
+ ];
+
+ self::assertEquals($expected, Arrays::getLastElementsPaths($this->complexArray, $separator));
+ }
+
+ public function testGetLastElementsPathsUsingDefaults(): void
+ {
+ // Using default separator and other default arguments
+ $expected = [
+ 'lorem.ipsum.dolor' => 'sit',
+ 'lorem.ipsum.diam.non' => 'egestas',
+ 'consectetur' => 'adipiscing',
+ 'mollis' => 1234,
+ 2 => [],
+ 'sit.nullam' => 'donec',
+ 'sit.aliquet.vitae.ligula' => 'quis',
+ 'sit.0' => 'elit',
+ 'amet.0' => 'iaculis',
+ 'amet.1' => 'primis',
+ ];
+
+ self::assertEquals($expected, Arrays::getLastElementsPaths($this->complexArray));
+ }
+
+ public function testGetLastElementsPathsUsingEmptyArray(): void
+ {
+ self::assertNull(Arrays::getLastElementsPaths([]));
+ }
+
+ /**
+ * @param array $stopIfMatchedBy 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)
+ * @param string $separator Separator used in resultant strings. Default: ".".
+ * @param array $expected Expected array
+ *
+ * @dataProvider provideStopIfMatchedByForGetLastElementsPaths
+ */
+ public function testGetLastElementsPathsUsingStopIfMatchedBy(
+ array $stopIfMatchedBy,
+ string $separator,
+ array $expected
+ ): void {
+ $paths = Arrays::getLastElementsPaths($this->superComplexArray, $separator, '', $stopIfMatchedBy);
+ self::assertEquals($expected, $paths);
+ }
+
+ public function testGetLastKey()
+ {
+ self::assertNull(Arrays::getLastKey([]));
+ self::assertEquals(4, Arrays::getLastKey($this->simpleArray));
+ self::assertEquals('amet', Arrays::getLastKey($this->complexArray));
+ }
+
+ /**
+ * @param string $description
+ * @param null|array $expected
+ * @param array $array
+ *
+ * @dataProvider provideLastRow
+ */
+ public function testGetLastRow(string $description, ?array $expected, array $array): void
+ {
+ static::assertSame($expected, Arrays::getLastRow($array), $description);
+ }
+
+ public function testGetNextElement()
+ {
+ // Negative cases
+ self::assertNull(Arrays::getNextElement($this->simpleArray, 'amet'));
+ self::assertNull(Arrays::getNextElement($this->simpleArray, 'xyz'));
+ self::assertNull(Arrays::getNextElement($this->simpleArray, 0));
+ self::assertNull(Arrays::getNextElement([], ''));
+ self::assertNull(Arrays::getNextElement([], null));
+
+ // Positive cases
+ self::assertEquals('ipsum', Arrays::getNextElement($this->simpleArray, 'Lorem'));
+ self::assertEquals('sit', Arrays::getNextElement($this->simpleArray, 'dolor'));
+ }
+
+ public function testGetNonArrayElementsCount(): void
+ {
+ // Negative cases
+ self::assertNull(Arrays::getNonArrayElementsCount([]));
+
+ // Positive cases
+ self::assertEquals(5, Arrays::getNonArrayElementsCount($this->simpleArray));
+ self::assertEquals(3, Arrays::getNonArrayElementsCount($this->simpleArrayWithKeys));
+ self::assertEquals(12, Arrays::getNonArrayElementsCount($this->twoDimensionsArray));
}
/**
@@ -1564,18 +3044,6 @@ letsTest[2] = value_2;';
self::assertSame($expected, Arrays::getNonEmptyValues($values), $description);
}
- /**
- * @param string $description Description of test case
- * @param array $values The values to filter
- * @param string $expected Expected non-empty values (as string)
- *
- * @dataProvider provideValuesToFilterNonEmptyAsStringUsingDefaultSeparator
- */
- public function testGetNonEmptyValuesAsStringUsingDefaultSeparator($description, array $values, $expected)
- {
- self::assertSame($expected, Arrays::getNonEmptyValuesAsString($values), $description);
- }
-
/**
* @param string $description Description of test case
* @param array $values The values to filter
@@ -1590,1100 +3058,850 @@ letsTest[2] = value_2;';
}
/**
- * Provides simple array to set/replace values with keys
+ * @param string $description Description of test case
+ * @param array $values The values to filter
+ * @param string $expected Expected non-empty values (as string)
*
- * @return \Generator
+ * @dataProvider provideValuesToFilterNonEmptyAsStringUsingDefaultSeparator
*/
- public function provideSimpleArrayToSetKeysAsValues()
+ public function testGetNonEmptyValuesAsStringUsingDefaultSeparator($description, array $values, $expected)
{
- yield[
- [
- 1,
+ self::assertSame($expected, Arrays::getNonEmptyValuesAsString($values), $description);
+ }
+
+ public function testGetNonEmptyValuesUsingEmptyArray()
+ {
+ self::assertNull(Arrays::getNonEmptyValues([]));
+ }
+
+ public function testGetPreviousElement()
+ {
+ // Negative cases
+ self::assertNull(Arrays::getPreviousElement($this->simpleArray, 'Lorem'));
+ self::assertNull(Arrays::getPreviousElement($this->simpleArray, 'xyz'));
+ self::assertNull(Arrays::getPreviousElement($this->simpleArray, 0));
+ self::assertNull(Arrays::getPreviousElement([], ''));
+ self::assertNull(Arrays::getPreviousElement([], null));
+
+ // Positive cases
+ self::assertEquals('ipsum', Arrays::getPreviousElement($this->simpleArray, 'dolor'));
+ self::assertEquals('sit', Arrays::getPreviousElement($this->simpleArray, 'amet'));
+ }
+
+ public function testGetValueByKeysPath()
+ {
+ // Negative cases
+ self::assertNull(Arrays::getValueByKeysPath([], []));
+
+ // Positive cases
+ self::assertNull(Arrays::getValueByKeysPath($this->simpleArray, []));
+ self::assertEquals('ipsum', Arrays::getValueByKeysPath($this->simpleArray, [1]));
+ self::assertEquals('sit', Arrays::getValueByKeysPath($this->simpleArray, [3]));
+ self::assertEquals('sit', Arrays::getValueByKeysPath($this->simpleArrayWithKeys, ['dolor']));
+
+ $keys = [
+ 'twoDimensionsArray' => [
2,
+ 2,
+ ],
+ 'complexArray' => [
+ [
+ 'lorem',
+ 'ipsum',
+ 'diam',
+ ],
+ [
+ 'sit',
+ 'aliquet',
+ ],
+ ],
+ ];
+
+ $value = [
+ [
+ 'non' => 'egestas',
+ ],
+ [
+ 'vitae' => [
+ 'ligula' => 'quis',
+ ],
+ ],
+ ];
+
+ self::assertEquals('fringilla', Arrays::getValueByKeysPath($this->twoDimensionsArray, $keys['twoDimensionsArray']));
+ self::assertEquals($value[0], Arrays::getValueByKeysPath($this->complexArray, $keys['complexArray'][0]));
+ self::assertEquals($value[1], Arrays::getValueByKeysPath($this->complexArray, $keys['complexArray'][1]));
+ }
+
+ public function testImplodeSmart()
+ {
+ $separator = '/';
+
+ // Empty array
+ self::assertNull(Arrays::implodeSmart([], $separator));
+
+ // Simple, One-dimensional array
+ self::assertEquals(implode($separator, $this->simpleArray), Arrays::implodeSmart($this->simpleArray, $separator));
+
+ // An array with elements that contain separator
+ $array = [
+ 'lorem'.$separator,
+ 'ipsum',
+ $separator.'dolor',
+ ];
+
+ self::assertEquals(implode($separator, [
+ 'lorem',
+ 'ipsum',
+ 'dolor',
+ ]), Arrays::implodeSmart($array, $separator));
+
+ // Complex array
+ self::assertEquals(implode($separator, [
+ 'donec',
+ 'quis',
+ 'elit',
+ ]), Arrays::implodeSmart($this->complexArray['sit'], $separator));
+ }
+
+ public function testIncrementIndexes()
+ {
+ // Negative cases
+ self::assertNull(Arrays::incrementIndexes([]));
+
+ // Positive cases
+ $array = [
+ 1 => 'Lorem',
+ 2 => 'ipsum',
+ 3 => 'dolor',
+ 4 => 'sit',
+ 5 => 'amet',
+ ];
+ self::assertEquals($array, Arrays::incrementIndexes($this->simpleArray));
+
+ $array = [
+ 0 => 'Lorem',
+ 2 => 'ipsum',
+ 3 => 'dolor',
+ 4 => 'sit',
+ 5 => 'amet',
+ ];
+ self::assertEquals($array, Arrays::incrementIndexes($this->simpleArray, 1));
+
+ $array = [
+ 0 => 'Lorem',
+ 1 => 'ipsum',
+ 3 => 'dolor',
+ 4 => 'sit',
+ 5 => 'amet',
+ ];
+ self::assertEquals($array, Arrays::incrementIndexes($this->simpleArray, 2));
+ }
+
+ /**
+ * @param string $description Description of test case
+ * @param mixed $value The value to verify
+ * @param bool $expected Expected information
+ *
+ * @dataProvider provideValueToIsEmptyArray
+ */
+ public function testIsEmptyArray(string $description, $value, bool $expected): void
+ {
+ self::assertSame($expected, Arrays::isEmptyArray($value), $description);
+ }
+
+ /**
+ * @param string $description
+ * @param bool $expected
+ * @param array $array
+ * @param $element
+ * @param bool $firstLevelOnly
+ *
+ * @dataProvider provideIsFirstElement
+ */
+ public function testIsFirstElement(
+ string $description,
+ bool $expected,
+ array $array,
+ $element,
+ ?bool $firstLevelOnly = null
+ ): void {
+ if (null === $firstLevelOnly) {
+ static::assertSame($expected, Arrays::isFirstElement($array, $element), $description);
+
+ return;
+ }
+
+ static::assertSame($expected, Arrays::isFirstElement($array, $element, $firstLevelOnly), $description);
+ }
+
+ /**
+ * @param string $description
+ * @param bool $expected
+ * @param array $array
+ * @param $element
+ * @param null|bool $firstLevelOnly
+ *
+ * @dataProvider provideIsLastElement
+ */
+ public function testIsLastElement(
+ string $description,
+ bool $expected,
+ array $array,
+ $element,
+ ?bool $firstLevelOnly = null
+ ): void {
+ if (null === $firstLevelOnly) {
+ static::assertSame($expected, Arrays::isLastElement($array, $element), $description);
+
+ return;
+ }
+
+ static::assertSame($expected, Arrays::isLastElement($array, $element, $firstLevelOnly), $description);
+ }
+
+ public function testIsMultiDimensional()
+ {
+ // Negative cases
+ self::assertNull(Arrays::isMultiDimensional([]));
+
+ // Positive cases
+ self::assertFalse(Arrays::isMultiDimensional($this->simpleArray));
+ self::assertFalse(Arrays::isMultiDimensional($this->simpleArrayWithKeys));
+
+ self::assertTrue(Arrays::isMultiDimensional($this->twoDimensionsArray));
+ self::assertTrue(Arrays::isMultiDimensional($this->complexArray));
+ }
+
+ /**
+ * @param string $description Description of test case
+ * @param mixed $value The value to verify
+ * @param bool $expected Expected information
+ *
+ * @dataProvider provideValueToIsNotEmptyArray
+ */
+ public function testIsNotEmptyArray(string $description, $value, bool $expected): void
+ {
+ self::assertSame($expected, Arrays::isNotEmptyArray($value), $description);
+ }
+
+ public function testIssetRecursive()
+ {
+ // Negative cases
+ self::assertFalse(Arrays::issetRecursive([], []));
+
+ // Positive cases
+ $unExistingKeys = [
+ 'a',
+ 'b',
+ 3,
+ ];
+
+ $existingKeys = [
+ 'simpleArray' => [
+ 1,
3,
4,
],
- [
- 1 => 0,
- 2 => 1,
- 3 => 2,
- 4 => 3,
- ],
- ];
-
- yield[
- [
- 'Lorem',
- 'ipsum',
+ 'simpleArrayWithKeys' => [
'dolor',
- 'sit',
'amet',
],
- [
- 'Lorem' => 0,
- 'ipsum' => 1,
- 'dolor' => 2,
- 'sit' => 3,
- 'amet' => 4,
+ 'twoDimensionsArray' => [
+ 2,
+ 3,
+ ],
+ 'complexArray' => [
+ 'sit',
+ 'aliquet',
+ 'vitae',
],
];
+
+ self::assertFalse(Arrays::issetRecursive($this->simpleArray, $unExistingKeys));
+ self::assertTrue(Arrays::issetRecursive($this->simpleArray, $existingKeys['simpleArray']));
+
+ self::assertFalse(Arrays::issetRecursive($this->simpleArrayWithKeys, $unExistingKeys));
+ self::assertTrue(Arrays::issetRecursive($this->simpleArrayWithKeys, $existingKeys['simpleArrayWithKeys']));
+
+ self::assertFalse(Arrays::issetRecursive($this->twoDimensionsArray, $unExistingKeys));
+ self::assertTrue(Arrays::issetRecursive($this->twoDimensionsArray, $existingKeys['twoDimensionsArray']));
+
+ self::assertFalse(Arrays::issetRecursive($this->complexArray, $unExistingKeys));
+ self::assertTrue(Arrays::issetRecursive($this->complexArray, $existingKeys['complexArray']));
}
- /**
- * Provides an array with duplicated values to set/replace values with keys
- *
- * @return \Generator
- */
- public function provideArrayWithDuplicatedValuesToSetKeysAsValues()
+ public function testKsortRecursive()
{
- yield[
- [
- 'lorem' => 'ipsum',
- 'dolor' => 'ipsum',
- 'sit' => 'amet',
- 'diam' => 'non',
- 'elit' => 'non',
- 'in' => 'non',
- ],
- [
- 'ipsum' => [
- 'lorem',
- 'dolor',
- ],
- 'amet' => 'sit',
- 'non' => [
- 'diam',
- 'elit',
- 'in',
- ],
- ],
- ];
+ // Negative cases
+ $array = [];
+ self::assertNull(Arrays::ksortRecursive($array));
- yield[
- [
- 'lorem' => [
- 'diam' => 'non',
- 'elit' => 'non',
- 'in' => 'non',
- ],
- 'dolor1' => 'ipsum',
- 'dolor2' => 'ipsum',
- 'sit' => 'amet',
- ],
- [
- 'lorem' => [
- 'non' => [
- 'diam',
- 'elit',
- 'in',
- ],
- ],
- 'ipsum' => [
- 'dolor1',
- 'dolor2',
- ],
- 'amet' => 'sit',
- ],
- ];
- }
+ // Positive cases
+ self::assertEquals($this->simpleArray, Arrays::ksortRecursive($this->simpleArray));
+ self::assertEquals($this->simpleArray, Arrays::ksortRecursive($this->simpleArray, SORT_NUMERIC));
+ self::assertEquals($this->twoDimensionsArray, Arrays::ksortRecursive($this->twoDimensionsArray));
- /**
- * Provides patterns of keys or paths that matched will stop the process and the expected array for the
- * getLastElementsPaths() method
- *
- * @return \Generator
- */
- public function provideStopIfMatchedByForGetLastElementsPaths()
- {
- /*
- * Special exception: do not use, stop recursive on the "diam" key
- */
- yield[
- 'diam',
- '.',
- [
- 'ipsum.quis.vestibulum.porta-1.0' => 'turpis',
- 'ipsum.quis.vestibulum.porta-1.1' => 'urna',
- 'ipsum.quis.vestibulum.porta-2.tortor.in.0' => 'dui',
- 'ipsum.quis.vestibulum.porta-2.tortor.in.dolor.0' => 'aliquam',
- 'ipsum.quis.vestibulum.porta-3.0' => 1,
- 'ipsum.quis.vestibulum.porta-3.1' => 2,
- 'ipsum.quis.vestibulum.porta-3.2' => 3,
- 'primis.0.0' => 'in',
- 'primis.0.1' => 'faucibus',
- 'primis.0.2' => 'orci',
- 'primis.1.0' => 'luctus',
- 'primis.1.1' => 'et',
- 'primis.1.2' => 'ultrices',
- ],
- ];
-
- /*
- * Stop building of paths on these keys:
- * - "tortor"
- * - "primis"
- */
- yield[
- [
- 'tortor',
+ // Positive case - multi-dimensions array
+ $effect = [
+ 'amet' => [
+ 'iaculis',
'primis',
],
- ' . ',
- [
- 'ipsum . quis . vestibulum . porta-1 . 0' => 'turpis',
- 'ipsum . quis . vestibulum . porta-1 . 1' => 'urna',
- 'ipsum . quis . vestibulum . porta-2 . tortor' => [
- 'in' => [
- 'dui',
- 'dolor' => [
- 'aliquam',
- ],
+ 'consectetur' => 'adipiscing',
+ 'lorem' => [
+ 'ipsum' => [
+ 'dolor' => 'sit',
+ 'diam' => [
+ 'non' => 'egestas',
],
],
- 'ipsum . quis . vestibulum . porta-3 . 0' => 1,
- 'ipsum . quis . vestibulum . porta-3 . 1' => 2,
- 'ipsum . quis . vestibulum . porta-3 . 2' => 3,
- 'primis' => [
- [
- 'in',
- 'faucibus',
- 'orci',
- ],
- [
- 'luctus',
- 'et',
- 'ultrices',
+ ],
+ 'mollis' => 1234,
+ 'sit' => [
+ 'nullam' => 'donec',
+ 'aliquet' => [
+ 'vitae' => [
+ 'ligula' => 'quis',
],
],
+ 'elit',
+ ],
+ 2 => [],
+ ];
+
+ self::assertEquals($effect, Arrays::ksortRecursive($this->complexArray));
+
+ // Positive case - multi-dimensions array - with options of ksort() function
+ $effect = [
+ 2 => [],
+ 'amet' => [
+ 'iaculis',
+ 'primis',
+ ],
+ 'consectetur' => 'adipiscing',
+ 'lorem' => [
+ 'ipsum' => [
+ 'dolor' => 'sit',
+ 'diam' => [
+ 'non' => 'egestas',
+ ],
+ ],
+ ],
+ 'mollis' => 1234,
+ 'sit' => [
+ 'nullam' => 'donec',
+ 'aliquet' => [
+ 'vitae' => [
+ 'ligula' => 'quis',
+ ],
+ ],
+ 'elit',
],
];
- /*
- * Stop building of paths on more sophisticated keys
- */
- yield[
- [
- 'porta\-\d+',
- '^\d+$',
- ],
- ' > ',
- [
- 'ipsum > quis > vestibulum > porta-1' => [
- 'turpis',
- 'urna',
- ],
- 'ipsum > quis > vestibulum > porta-2' => [
- 'tortor' => [
- 'in' => [
- 'dui',
- 'dolor' => [
- 'aliquam',
- ],
- ],
- ],
- ],
- 'ipsum > quis > vestibulum > porta-3' => [
- 1,
- 2,
- 3,
- ],
- 'primis > 0' => [
- 'in',
- 'faucibus',
- 'orci',
- ],
- 'primis > 1' => [
- 'luctus',
- 'et',
- 'ultrices',
- ],
- ],
- ];
+ self::assertEquals($effect, Arrays::ksortRecursive($this->complexArray, SORT_STRING & SORT_NATURAL));
+ }
- /*
- * Stop building of paths on these:
- * - keys
- * and
- * - paths (verify paths too)
- */
- yield[
- [
- 'porta-1',
- 'porta-2 > tortor > in',
- ],
- ' > ',
- [
- 'ipsum > quis > vestibulum > porta-1' => [
- 'turpis',
- 'urna',
- ],
- 'ipsum > quis > vestibulum > porta-2 > tortor > in' => [
- 'dui',
- 'dolor' => [
- 'aliquam',
- ],
- ],
- 'ipsum > quis > vestibulum > porta-3 > 0' => 1,
- 'ipsum > quis > vestibulum > porta-3 > 1' => 2,
- 'ipsum > quis > vestibulum > porta-3 > 2' => 3,
- 'primis > 0 > 0' => 'in',
- 'primis > 0 > 1' => 'faucibus',
- 'primis > 0 > 2' => 'orci',
- 'primis > 1 > 0' => 'luctus',
- 'primis > 1 > 1' => 'et',
- 'primis > 1 > 2' => 'ultrices',
- ],
- ];
-
- /*
- * Stop building of paths on these paths (verify paths only)
- */
- yield[
- [
- 'ipsum > quis > vestibulum > porta-1',
- 'ipsum > quis > vestibulum > porta-2 > tortor',
- 'primis > 1',
- ],
- ' > ',
- [
- 'ipsum > quis > vestibulum > porta-1' => [
- 'turpis',
- 'urna',
- ],
- 'ipsum > quis > vestibulum > porta-2 > tortor' => [
- 'in' => [
- 'dui',
- 'dolor' => [
- 'aliquam',
- ],
- ],
- ],
- 'ipsum > quis > vestibulum > porta-3 > 0' => 1,
- 'ipsum > quis > vestibulum > porta-3 > 1' => 2,
- 'ipsum > quis > vestibulum > porta-3 > 2' => 3,
- 'primis > 0 > 0' => 'in',
- 'primis > 0 > 1' => 'faucibus',
- 'primis > 0 > 2' => 'orci',
- 'primis > 1' => [
- 'luctus',
- 'et',
- 'ultrices',
- ],
- ],
- ];
-
- /*
- * Stop building of paths if path contains any of these part (verify part of paths only)
- */
- yield[
- [
- 'vestibulum > porta-1',
- 'tortor > in',
- '[a-z]+ > \d+',
- ],
- ' > ',
- [
- 'ipsum > quis > vestibulum > porta-1' => [
- 'turpis',
- 'urna',
- ],
- 'ipsum > quis > vestibulum > porta-2 > tortor > in' => [
- 'dui',
- 'dolor' => [
- 'aliquam',
- ],
- ],
- 'ipsum > quis > vestibulum > porta-3 > 0' => 1,
- 'ipsum > quis > vestibulum > porta-3 > 1' => 2,
- 'ipsum > quis > vestibulum > porta-3 > 2' => 3,
- 'primis > 0' => [
- 'in',
- 'faucibus',
- 'orci',
- ],
- 'primis > 1' => [
- 'luctus',
- 'et',
- 'ultrices',
- ],
- ],
- ];
+ public function testMakeArray(): void
+ {
+ self::assertSame($this->simpleArray, Arrays::makeArray($this->simpleArray));
+ self::assertSame(['test'], Arrays::makeArray('test'));
}
/**
- * Provide values to filter and get non-empty values
+ * @param string $description Description of test case
+ * @param null|array $expected Expected new array (with quoted elements)
+ * @param array $array The array to check for string values
*
- * @return \Generator
+ * @dataProvider provideArrayToQuoteStrings
*/
- public function provideValuesToFilterNonEmpty()
+ public function testQuoteStrings(string $description, ?array $expected, array $array): void
{
- $simpleObject = new SimpleToString('1234');
+ self::assertSame($expected, Arrays::quoteStrings($array), $description);
+ }
- yield[
- 'All values are empty',
- [
- '',
- null,
- [],
- ],
- [],
- ];
+ public function testRemoveElement()
+ {
+ self::assertFalse(Arrays::removeElement($this->simpleArray, 'eeee'));
+ self::assertTrue(is_array(Arrays::removeElement($this->simpleArray, 'Lorem')));
- yield[
- '5 values with 2 empty strings',
- [
- 'test 1',
- '',
- 'test 2',
- 'test 3',
- '',
- ],
- [
- 0 => 'test 1',
- 2 => 'test 2',
- 3 => 'test 3',
- ],
- ];
+ Arrays::removeElement($this->simpleArray, 'amet');
+ self::assertFalse(isset($this->simpleArray['amet']));
+ }
- yield[
- '"0" shouldn\'t be treated like an empty value',
- [
- 123,
- 0,
- 456,
- ],
- [
- 123,
- 0,
- 456,
- ],
- ];
+ public function testRemoveElements(): void
+ {
+ $array1 = $this->simpleArray;
+ $array2 = $this->simpleArray;
- yield[
- 'Object shouldn\'t be treated like an empty value',
- [
- 'test 1',
- $simpleObject,
- 'test 2',
- null,
- 'test 3',
- ],
- [
- 0 => 'test 1',
- 1 => $simpleObject,
- 2 => 'test 2',
- 4 => 'test 3',
- ],
- ];
+ Arrays::removeElements($array1, 'ipsum');
+ self::assertSame([
+ 1 => 'ipsum',
+ 2 => 'dolor',
+ 3 => 'sit',
+ 4 => 'amet',
+ ], $array1);
- yield[
- 'Mixed values (non-empty, empty, strings, integers, objects)',
- [
- 'test 1',
- '',
- 123,
- null,
- 'test 2',
- 'test 3',
- 0,
- $simpleObject,
- 456,
- [],
- $simpleObject,
- ],
- [
- 0 => 'test 1',
- 2 => 123,
- 4 => 'test 2',
- 5 => 'test 3',
- 6 => 0,
- 7 => $simpleObject,
- 8 => 456,
- 10 => $simpleObject,
- ],
- ];
+ Arrays::removeElements($array2, 'sit', false);
+ self::assertSame([
+ 0 => 'Lorem',
+ 1 => 'ipsum',
+ 2 => 'dolor',
+ 3 => 'sit',
+ ], $array2);
+
+ Arrays::removeElements($this->complexArray['lorem'], 'sit', false);
+ self::assertSame(['ipsum' => ['dolor' => 'sit']], $this->complexArray['lorem']);
}
/**
- * Provide values to filter and get non-empty values concatenated by default separator
+ * @param string $description Description of test case
+ * @param array $array The array which should be shortened
+ * @param bool $last If is set to true, last element is removed (default behaviour). Otherwise - first.
+ * @param null|array $expected Expected result
*
- * @return \Generator
+ * @dataProvider provideArrayToRemoveMarginalElement
*/
- public function provideValuesToFilterNonEmptyAsStringUsingDefaultSeparator()
+ public function testRemoveMarginalElement(string $description, array $array, bool $last, ?array $expected): void
{
- yield[
- 'An empty array (no values to filter)',
- [],
- null,
- ];
-
- yield[
- 'All values are empty',
- [
- '',
- null,
- [],
- ],
- '',
- ];
-
- yield[
- '5 values with 2 empty strings',
- [
- 'test 1',
- '',
- 'test 2',
- 'test 3',
- '',
- ],
- 'test 1, test 2, test 3',
- ];
-
- yield[
- 'Numbers with "0" that shouldn\'t be treated like an empty value',
- [
- 123,
- 0,
- 456,
- ],
- '123, 0, 456',
- ];
-
- yield[
- 'Object shouldn\'t be treated like an empty value',
- [
- 'test 1',
- new SimpleToString('1234'),
- 'test 2',
- null,
- 'test 3',
- ],
- 'test 1, Instance with ID: 1234, test 2, test 3',
- ];
-
- yield[
- 'Mixed values (non-empty, empty, strings, integers, objects)',
- [
- 'test 1',
- '',
- 123,
- null,
- 'test 2',
- 'test 3',
- 0,
- new SimpleToString('A1XC90Z'),
- 456,
- [],
- new SimpleToString('FF-45-0Z'),
- ],
- 'test 1, 123, test 2, test 3, 0, Instance with ID: A1XC90Z, 456, Instance with ID: FF-45-0Z',
- ];
+ self::assertSame($expected, Arrays::removeMarginalElement($array, $last), $description);
}
/**
- * Provide values to filter and get non-empty values concatenated by given separator
+ * @param string $description Description of test case
+ * @param array $array Array which keys should be replaced
+ * @param string $oldKeyPattern Regular expression of the old key
+ * @param string $newKey Name of the new key
+ * @param array $expected Expected result
*
- * @return \Generator
+ * @dataProvider provideArrayToReplaceKeys
*/
- public function provideValuesToFilterNonEmptyAsString()
- {
- yield[
- 'An empty array (no values to filter)',
- [],
- ' | ',
- null,
- ];
-
- yield[
- 'All values are empty',
- [
- '',
- null,
- [],
- ],
- ' | ',
- '',
- ];
-
- yield[
- '5 values with 2 empty strings',
- [
- 'test 1',
- '',
- 'test 2',
- 'test 3',
- '',
- ],
- ' | ',
- 'test 1 | test 2 | test 3',
- ];
-
- yield[
- 'Numbers with "0" that shouldn\'t be treated like an empty value',
- [
- 123,
- 0,
- 456,
- ],
- ' <-> ',
- '123 <-> 0 <-> 456',
- ];
-
- yield[
- 'Object shouldn\'t be treated like an empty value',
- [
- 'test 1',
- new SimpleToString('1234'),
- 'test 2',
- null,
- 'test 3',
- ],
- ' | ',
- 'test 1 | Instance with ID: 1234 | test 2 | test 3',
- ];
-
- yield[
- 'Mixed values (non-empty, empty, strings, integers, objects)',
- [
- 'test 1',
- '',
- 123,
- null,
- 'test 2',
- 'test 3',
- 0,
- new SimpleToString('A1XC90Z'),
- 456,
- [],
- new SimpleToString('FF-45-0Z'),
- ],
- ';',
- 'test 1;123;test 2;test 3;0;Instance with ID: A1XC90Z;456;Instance with ID: FF-45-0Z',
- ];
+ public function testReplaceKeys(
+ string $description,
+ array $array,
+ string $oldKeyPattern,
+ string $newKey,
+ ?array $expected
+ ): void {
+ self::assertSame($expected, Arrays::replaceKeys($array, $oldKeyPattern, $newKey), $description);
}
- public function provideArrayValuesKeysConverted2string()
+ /**
+ * @param array $array The array to change values with keys
+ * @param array $replaced The array with replaced values with keys
+ *
+ * @dataProvider provideArrayWithDuplicatedValuesToSetKeysAsValues
+ */
+ public function testSetKeysAsValuesDuplicatedValues($array, $replaced)
{
- yield[
- 'An empty array',
- null,
- [],
- ];
-
- yield[
- 'Empty string and null as value',
- 'test_1=,test_2=,test_3=3',
- [
- 'test_1' => null,
- 'test_2' => '',
- 'test_3' => '3',
- ],
- ];
-
- yield[
- 'Empty string and null as value (with custom separators)',
- 'test_1="" test_2="" test_3="3"',
- [
- 'test_1' => null,
- 'test_2' => '',
- 'test_3' => '3',
- ],
- ' ',
- '=',
- '"',
- ];
-
- yield[
- 'Empty string as key',
- '1=test_1,=test_2,3=test_3',
- [
- 1 => 'test_1',
- '' => 'test_2',
- '3' => 'test_3',
- ],
- ];
-
- yield[
- 'Empty string as key (with custom separators)',
- '1 => "test_1"; => "test_2"; 3 => "test_3"',
- [
- 1 => 'test_1',
- '' => 'test_2',
- '3' => 'test_3',
- ],
- '; ',
- ' => ',
- '"',
- ];
-
- yield[
- 'Mixed types of keys and values',
- 'test_1=test test,test_2=2,test_3=3.45',
- [
- 'test_1' => 'test test',
- 'test_2' => 2,
- 'test_3' => 3.45,
- ],
- ];
-
- yield[
- 'Mixed types of keys and values (with custom separators)',
- 'test_1 --> *test test* | test_2 --> *2* | test_3 --> *3.45*',
- [
- 'test_1' => 'test test',
- 'test_2' => 2,
- 'test_3' => 3.45,
- ],
- ' | ',
- ' --> ',
- '*',
- ];
+ self::assertEquals($replaced, Arrays::setKeysAsValues($array, false));
}
- public function provideArrayValues2csv()
+ public function testSetKeysAsValuesEmptyArray()
{
- yield[
- 'An empty array',
- null,
- [],
- ];
-
- yield[
- 'Empty string, and empty array and null as row',
- "1,2,3\n5,6,",
- [
- 'test_1' => '',
- 'test_2' => [],
- 'test_3' => null,
- 'test_4' => [
- 'aa' => 1,
- 'bb' => 2,
- 'cc' => 3,
- ],
- [
- 'dd' => 5,
- 'ee' => 6,
- 'ff' => '',
- ],
- ],
- ];
-
- yield[
- 'Empty string, and empty array and null as row (with custom separator)',
- "1, 2, 3\n5, 6, ",
- [
- 'test_1' => '',
- 'test_2' => [],
- 'test_3' => null,
- 'test_4' => [
- 'aa' => 1,
- 'bb' => 2,
- 'cc' => 3,
- ],
- [
- 'dd' => 5,
- 'ee' => 6,
- 'ff' => '',
- ],
- ],
- ', ',
- ];
-
- yield[
- 'Empty string as key, non-array as value',
- "1,2,3\n5,6,",
- [
- '' => 'test_1',
- 1 => 'test_2',
- '3' => [
- 'aa' => 1,
- 'bb' => 2,
- 'cc' => 3,
- ],
- [
- 'dd' => 5,
- 'ee' => 6,
- 'ff' => '',
- ],
- ],
- ];
-
- yield[
- 'Empty string as key, non-array as value (with custom separator)',
- "1 | 2 | 3\n5 | 6 | ",
- [
- '' => 'test_1',
- 1 => 'test_2',
- '3' => [
- 'aa' => 1,
- 'bb' => 2,
- 'cc' => 3,
- ],
- [
- 'dd' => 5,
- 'ee' => 6,
- 'ff' => '',
- ],
- ],
- ' | ',
- ];
-
- yield[
- 'Invalid structure, not like database table',
- "1,2,3\n5,6\n7,8,9,10",
- [
- [
- 'aa' => 1,
- 'bb' => 2,
- 'cc' => 3,
- ],
- [
- 'dd' => 5,
- 'ee' => 6,
- ],
- [
- 7,
- 8,
- 9,
- 10,
- ],
- ],
- ];
-
- yield[
- 'Invalid structure, not like database table (with custom separator)',
- "1 <-> 2 <-> 3\n5 <-> 6\n7 <-> 8 <-> 9 <-> 10",
- [
- [
- 'aa' => 1,
- 'bb' => 2,
- 'cc' => 3,
- ],
- [
- 'dd' => 5,
- 'ee' => 6,
- ],
- [
- 7,
- 8,
- 9,
- 10,
- ],
- ],
- ' <-> ',
- ];
-
- yield[
- 'Mixed types of keys and values',
- "1,2,3.45\n5,6,\n7,8,9,,10",
- [
- [
- 'aa' => 1,
- 'bb' => 2,
- 'cc' => 3.45,
- ],
- [
- 'dd' => 5,
- 'ee' => 6,
- null,
- ],
- [
- 7,
- 8,
- 'qq' => 9,
- '',
- 10,
- ],
- ],
- ];
-
- yield[
- 'Mixed types of keys and values (with custom separator)',
- "1 // 2 // 3.45\n5 // 6 // \n7 // 8 // 9 // // 10",
- [
- [
- 'aa' => 1,
- 'bb' => 2,
- 'cc' => 3.45,
- ],
- [
- 'dd' => 5,
- 'ee' => 6,
- null,
- ],
- [
- 7,
- 8,
- 'qq' => 9,
- '',
- 10,
- ],
- ],
- ' // ',
- ];
+ self::assertNull(Arrays::setKeysAsValues([]));
}
- public function provideArrayValues2string()
+ public function testSetKeysAsValuesSameKeysValues()
{
- yield[
- 'An empty array',
- null,
- [],
- ];
-
- yield[
- 'Simple array',
- 'Test 1,Test 2,Test 3',
- [
- 1 => 'Test 1',
- 2 => 'Test 2',
- 3 => 'Test 3',
- ],
- ];
-
- yield[
- 'Simple array (with custom separator)',
- 'Test 1.Test 2.Test 3',
- [
- 1 => 'Test 1',
- 2 => 'Test 2',
- 3 => 'Test 3',
- ],
- '',
- '.',
- ];
-
- yield[
- 'Simple array (concrete column)',
- 'Test 2',
- [
- 1 => 'Test 1',
- 2 => 'Test 2',
- 3 => 'Test 3',
- ],
- 2,
- ];
-
- yield[
- 'Simple array (concrete column with custom separator)',
- 'Test 2',
- [
- 1 => 'Test 1',
- 2 => 'Test 2',
- 3 => 'Test 3',
- ],
- 2,
- '.',
- ];
-
- yield[
- 'Complex array',
- '1,2,3,test 1,test 2,test 3,,test 4,,bbb,3.45',
- [
- [
- 1,
- 2,
- 3,
- ],
- [
- 'test 1',
- 'test 2',
- [
- 'test 3',
- '',
- 'test 4',
- ],
- ],
- [],
- [
- 'a' => '',
- 'b' => 'bbb',
- [],
- 'c' => 3.45,
- ],
- ],
- ];
-
- yield[
- '1st complex array (concrete column)',
- '2,test 2,',
- [
- [
- 1,
- 2,
- 3,
- ],
- [
- 'test 1',
- 'test 2',
- [
- 'test 3',
- '',
- 'test 4',
- ],
- ],
- [],
- [
- 'a' => '',
- 'b' => 'bbb',
- [],
- 'c' => 3.45,
- ],
- ],
+ $array = [
+ 0,
1,
+ 2,
+ 3,
];
- yield[
- '2nd complex array (concrete column)',
- 'bb,1234,0xb',
- [
- [
- 1,
- 2,
- 3,
- ],
- [
- 'a' => 'aa',
- 'b' => 'bb',
- 'c' => 'cc',
- ],
- [
- 'a',
- 'b',
- 'c',
- ],
- [
- 'a' => '',
- 'b' => 1234,
- ],
- [
- 'c' => 5678,
- 'b' => '0xb',
- ],
- ],
- 'b',
- ];
-
- yield[
- '3rd complex array (concrete column with custom separator)',
- 'bb - 1234 - 3xb - bbb',
- [
- [
- 1,
- 2,
- 3,
- ],
- [
- 'a' => 'aa',
- 'b' => 'bb',
- 'c' => 'cc',
- ],
- [
- 'a',
- 'b' => [],
- 'c',
- ],
- [
- 'a' => '',
- 'b' => 1234,
- ],
- [
- 'c' => 5678,
- 'b' => [
- 'b1' => '0xb',
- 'b2' => '1xb',
- 'b' => '3xb',
- ],
- [
- 1,
- 2,
- 'a' => 'aaa',
- 'b' => 'bbb',
- ],
- ],
- ],
- 'b',
- ' - ',
- ];
+ self::assertEquals($array, Arrays::setKeysAsValues($array));
}
- public function provideArrayToQuoteStrings()
+ /**
+ * @param array $array The array to change values with keys
+ * @param array $replaced The array with replaced values with keys
+ *
+ * @dataProvider provideSimpleArrayToSetKeysAsValues
+ */
+ public function testSetKeysAsValuesSimpleArray($array, $replaced)
{
- yield[
- 'An empty array',
- null,
- [],
- ];
+ self::assertEquals($replaced, Arrays::setKeysAsValues($array));
+ }
- yield[
- 'Simple array',
+ public function testSetKeysAsValuesTwoDimensionsArray()
+ {
+ $replaced = [
[
- 1,
- 2,
- 3,
- '\'1\'',
- '\'2\'',
+ 'lorem' => 0,
+ 'ipsum' => 1,
+ 'dolor' => 2,
+ 'sit' => 3,
+ 'amet' => 4,
],
[
- 1,
- 2,
- 3,
- '1',
- '2',
+ 'consectetur' => 0,
+ 'adipiscing' => 1,
+ 'elit' => 2,
+ ],
+ [
+ 'donec' => 0,
+ 'sagittis' => 1,
+ 'fringilla' => 2,
+ 'eleifend' => 3,
],
];
- yield[
- 'Complex array',
- [
- 123,
- '\'456\'',
- [
- 'x' => [
- 0,
- '\'0\'',
- 1 => '\'1\'',
- 2 => 2,
- ],
- '\'y\'',
- ],
- 444 => '\'\'',
- [
- [
- [
- '\'test\'',
- ],
- ],
- ],
+ self::assertEquals($replaced, Arrays::setKeysAsValues($this->twoDimensionsArray));
+ }
+
+ public function testSetPositions()
+ {
+ // Negative cases
+ self::assertNull(Arrays::setPositions([]));
+
+ // Positive case - 1-dimension array
+ $array = [
+ 'abc',
+ ];
+
+ self::assertEquals($array, Arrays::setPositions($array));
+
+ // Positive case - 2-dimensions array
+ $effect = $this->twoDimensionsArray;
+ $effect[0][Arrays::POSITION_KEY_NAME] = 1;
+ $effect[1][Arrays::POSITION_KEY_NAME] = 2;
+ $effect[2][Arrays::POSITION_KEY_NAME] = 3;
+
+ self::assertEquals($effect, Arrays::setPositions($this->twoDimensionsArray));
+
+ // Positive case - multidimensional array
+ $array = [
+ 'lorem',
+ 'ipsum' => [
+ 'dolor',
+ 'sit',
],
- [
- 123,
- '456',
- [
- 'x' => [
- 0,
- '0',
- 1 => '1',
- 2 => 2,
- ],
- 'y',
- ],
- 444 => '',
- [
- [
- [
- 'test',
- ],
+ 'amet' => [
+ 'consectetur',
+ 'adipiscing' => [
+ 'elit' => [
+ 'cras',
+ 'quis',
+ 'ligula',
],
],
],
];
+
+ $effect = [
+ 'lorem',
+ 'ipsum' => [
+ 'dolor',
+ 'sit',
+ Arrays::POSITION_KEY_NAME => 1,
+ ],
+ 'amet' => [
+ 'consectetur',
+ 'adipiscing' => [
+ 'elit' => [
+ 'cras',
+ 'quis',
+ 'ligula',
+ Arrays::POSITION_KEY_NAME => 1,
+ ],
+ Arrays::POSITION_KEY_NAME => 1,
+ ],
+ Arrays::POSITION_KEY_NAME => 2,
+ ],
+ ];
+
+ self::assertEquals($effect, Arrays::setPositions($array));
+
+ // Positive case - non-default name of key with position value & 2-dimensions array
+ $keyName = 'level';
+ $effect = $this->twoDimensionsArray;
+
+ $effect[0][$keyName] = 1;
+ $effect[1][$keyName] = 2;
+ $effect[2][$keyName] = 3;
+
+ self::assertEquals($effect, Arrays::setPositions($this->twoDimensionsArray, $keyName));
+
+ // Positive case - non-default start value of position & 2-dimensions array
+ $startPosition = 5;
+ $effect = $this->twoDimensionsArray;
+
+ $effect[Arrays::POSITION_KEY_NAME] = $startPosition;
+ $effect[0][Arrays::POSITION_KEY_NAME] = 1;
+ $effect[1][Arrays::POSITION_KEY_NAME] = 2;
+ $effect[2][Arrays::POSITION_KEY_NAME] = 3;
+
+ self::assertEquals($effect, Arrays::setPositions($this->twoDimensionsArray, Arrays::POSITION_KEY_NAME, $startPosition));
+ }
+
+ public function testSortByCustomKeysOrder()
+ {
+ // Negative cases
+ self::assertNull(Arrays::sortByCustomKeysOrder([], []));
+
+ // Positive cases
+ self::assertEquals([0], Arrays::sortByCustomKeysOrder([0], []));
+ self::assertEquals($this->simpleArray, Arrays::sortByCustomKeysOrder($this->simpleArray, []));
+
+ $keysOrder = [
+ 'amet',
+ 'dolor',
+ 'Lorem',
+ ];
+
+ $sorted = [
+ 'dolor' => 'sit',
+ 'amet' => 'consectetur',
+ 'Lorem' => 'ipsum',
+ ];
+
+ self::assertEquals($sorted, Arrays::sortByCustomKeysOrder($this->simpleArrayWithKeys, $keysOrder));
+
+ $array = [
+ 'Lorem',
+ 'ipsum',
+ 'dolor',
+ 'sit',
+ 'amet',
+ ];
+
+ $keysOrder = [
+ 0,
+ 3,
+ 1,
+ 2,
+ ];
+
+ $sorted = [
+ 0 => 'Lorem',
+ 3 => 'sit',
+ 1 => 'ipsum',
+ 2 => 'dolor',
+ 4 => 'amet',
+ ];
+
+ self::assertEquals($sorted, Arrays::sortByCustomKeysOrder($array, $keysOrder));
+
+ $array = [
+ 'Lorem',
+ 'ipsum',
+ 'dolor',
+ 'sit',
+ 'amet',
+ ];
+
+ $keysOrder = [
+ 0,
+ 3,
+ ];
+
+ $sorted = [
+ 0 => 'Lorem',
+ 3 => 'sit',
+ 1 => 'ipsum',
+ 2 => 'dolor',
+ 4 => 'amet',
+ ];
+
+ self::assertEquals($sorted, Arrays::sortByCustomKeysOrder($array, $keysOrder));
+ }
+
+ public function testString2array(): void
+ {
+ // Negative cases
+ self::assertNull(Arrays::string2array(''));
+
+ // Positive cases
+ $array = [
+ 'light' => '#fff',
+ 'dark' => '#000',
+ ];
+
+ self::assertEquals($array, Arrays::string2array('light:#fff|dark:#000'));
+ self::assertEquals($array, Arrays::string2array('light: #fff | dark: #000'));
+
+ $array = [
+ 'red' => '#f00',
+ 'green' => '#0f0',
+ 'blue' => '#00f',
+ ];
+
+ self::assertEquals($array, Arrays::string2array('red:#f00|green:#0f0|blue:#00f'));
+ self::assertEquals($array, Arrays::string2array('red: #f00 | green: #0f0 | blue: #00f'));
+ self::assertEquals($array, Arrays::string2array('red : #f00 | green : #0f0 | blue : #00f'));
+ }
+
+ public function testTrimRecursive()
+ {
+ // Negative cases
+ self::assertSame([], Arrays::trimRecursive([]));
+
+ // Positive cases
+ self::assertEquals(['a'], Arrays::trimRecursive([' a ']));
+ self::assertEquals([
+ 'a',
+ 'b',
+ ], Arrays::trimRecursive([
+ ' a ',
+ 'b ',
+ ]));
+
+ $array = [
+ 'abc ',
+ [
+ 'def',
+ 'ghi ',
+ ],
+ ];
+
+ $result = [
+ 'abc',
+ [
+ 'def',
+ 'ghi',
+ ],
+ ];
+
+ self::assertEquals($result, Arrays::trimRecursive($array));
+
+ $array = [
+ 'abc ',
+ [
+ ' def ',
+ 'ghi ',
+ 'oo' => [
+ ' ee ',
+ 'g' => 'h hhh ',
+ ],
+ ],
+ ];
+
+ $result = [
+ 'abc',
+ [
+ 'def',
+ 'ghi',
+ 'oo' => [
+ 'ee',
+ 'g' => 'h hhh',
+ ],
+ ],
+ ];
+
+ self::assertEquals($result, Arrays::trimRecursive($array));
+ }
+
+ /**
+ * @param string $description Description of test
+ * @param string $expected Expected array converted to csv string
+ * @param array $array Data to be converted. It have to be an array that represents database table.
+ * @param string $separator (optional) Separator used between values. Default: ",".
+ *
+ * @dataProvider provideArrayValues2csv
+ */
+ public function testValues2csv(string $description, ?string $expected, array $array, string $separator = ','): void
+ {
+ // Required to avoid failure:
+ //
+ // Failed asserting that two strings are identical
+ // 1,2,3.45 - expected
+ // 1,2,3,45 - actual
+ Locale::setLocale(LC_ALL, 'en', 'US');
+
+ static::assertSame($expected, Arrays::values2csv($array, $separator), $description);
+ }
+
+ /**
+ * @param string $description Description of test
+ * @param string $expected Expected array converted to string
+ * @param array $array Data to be converted
+ * @param string $arrayColumnKey (optional) Column name. Default: "".
+ * @param string $separator (optional) Separator used between values. Default: ",".
+ *
+ * @dataProvider provideArrayValues2string
+ */
+ public function testValues2string($description, $expected, array $array, $arrayColumnKey = '', $separator = ',')
+ {
+ // Required to avoid failure:
+ //
+ // Failed asserting that two strings are identical
+ // 1,2,3,test 1,test 2,test 3,,test 4,,bbb,3.45 - expected
+ // 1,2,3,test 1,test 2,test 3,,test 4,,bbb,3,45 - actual
+ Locale::setLocale(LC_ALL, 'en', 'US');
+
+ self::assertSame($expected, Arrays::values2string($array, $arrayColumnKey, $separator), $description);
+ }
+
+ /**
+ * @param string $description Description of test
+ * @param string $expected Expected array converted to string
+ * @param array $array Data to be converted
+ * @param string $separator (optional) Separator used between name-value pairs. Default: ",".
+ * @param string $valuesKeysSeparator (optional) Separator used between name and value. Default: "=".
+ * @param string $valuesWrapper (optional) Wrapper used to wrap values, e.g. double-quote: key="value".
+ * Default: "".
+ *
+ * @dataProvider provideArrayValuesKeysConverted2string
+ */
+ public function testValuesKeys2string(
+ $description,
+ $expected,
+ array $array,
+ $separator = ',',
+ $valuesKeysSeparator = '=',
+ $valuesWrapper = ''
+ ) {
+ // Required to avoid failure:
+ //
+ // Failed asserting that two strings are identical
+ // test_1=test test,test_2=2,test_3=3.45 - expected
+ // test_1=test test,test_2=2,test_3=3,45 - actual
+ Locale::setLocale(LC_ALL, 'en', 'US');
+
+ self::assertSame(
+ $expected,
+ Arrays::valuesKeys2string($array, $separator, $valuesKeysSeparator, $valuesWrapper),
+ $description
+ );
+
+ self::assertSame(
+ '0=Lorem,1=ipsum,2=dolor,3=sit,4=amet',
+ Arrays::valuesKeys2string($this->simpleArray),
+ 'Simple array'
+ );
+
+ self::assertSame(
+ '0=Lorem;1=ipsum;2=dolor;3=sit;4=amet',
+ Arrays::valuesKeys2string($this->simpleArray, ';'),
+ 'Simple array (with custom separator)'
+ );
+
+ self::assertSame(
+ '0=Lorem 1=ipsum 2=dolor 3=sit 4=amet',
+ Arrays::valuesKeys2string($this->simpleArray, ' '),
+ 'Simple array (with custom separator)'
+ );
+
+ self::assertSame(
+ '0="Lorem" 1="ipsum" 2="dolor" 3="sit" 4="amet"',
+ Arrays::valuesKeys2string($this->simpleArray, ' ', '=', '"'),
+ 'Simple array (with custom separators)'
+ );
+
+ self::assertSame(
+ '0="Lorem", 1="ipsum", 2="dolor", 3="sit", 4="amet"',
+ Arrays::valuesKeys2string($this->simpleArray, ', ', '=', '"'),
+ 'Simple array (with custom separators)'
+ );
}
/**
* {@inheritdoc}
*/
- protected function setUp()
+ protected function setUp(): void
{
parent::setUp();
@@ -2698,7 +3916,7 @@ letsTest[2] = value_2;';
$this->simpleArrayWithKeys = [
'Lorem' => 'ipsum',
'dolor' => 'sit',
- 'amet' => 'consectetur',
+ 'amet' => 'consectetur',
];
$this->twoDimensionsArray = [
@@ -2723,19 +3941,19 @@ letsTest[2] = value_2;';
];
$this->complexArray = [
- 'lorem' => [
+ 'lorem' => [
'ipsum' => [
'dolor' => 'sit',
- 'diam' => [
+ 'diam' => [
'non' => 'egestas',
],
],
],
'consectetur' => 'adipiscing',
- 'mollis' => 1234,
- 2 => [],
- 'sit' => [
- 'nullam' => 'donec',
+ 'mollis' => 1234,
+ 2 => [],
+ 'sit' => [
+ 'nullam' => 'donec',
'aliquet' => [
'vitae' => [
'ligula' => 'quis',
@@ -2743,14 +3961,14 @@ letsTest[2] = value_2;';
],
'elit',
],
- 'amet' => [
+ 'amet' => [
'iaculis',
'primis',
],
];
$this->superComplexArray = [
- 'ipsum' => [
+ 'ipsum' => [
'quis' => [
'vestibulum' => [
'porta-1' => [
@@ -2793,7 +4011,7 @@ letsTest[2] = value_2;';
/**
* {@inheritdoc}
*/
- protected function tearDown()
+ protected function tearDown(): void
{
parent::tearDown();
diff --git a/tests/Utilities/Bootstrap4CssSelectorTest.php b/tests/Utilities/Bootstrap4CssSelectorTest.php
index ee6787d..98fe708 100644
--- a/tests/Utilities/Bootstrap4CssSelectorTest.php
+++ b/tests/Utilities/Bootstrap4CssSelectorTest.php
@@ -8,6 +8,7 @@
namespace Meritoo\Test\Common\Utilities;
+use Generator;
use Meritoo\Common\Test\Base\BaseTestCase;
use Meritoo\Common\Utilities\Bootstrap4CssSelector;
@@ -16,27 +17,147 @@ use Meritoo\Common\Utilities\Bootstrap4CssSelector;
*
* @author Meritoo
* @copyright Meritoo
+ *
+ * @internal
+ * @covers \Meritoo\Common\Utilities\Bootstrap4CssSelector
*/
class Bootstrap4CssSelectorTest extends BaseTestCase
{
+ /**
+ * Provides name of form and expected selector
+ *
+ * @return Generator
+ */
+ public function provideFormNameAndSelector()
+ {
+ yield [
+ 'test',
+ 'form[name="test"] .form-group',
+ ];
+
+ yield [
+ 'test-123-test-456',
+ 'form[name="test-123-test-456"] .form-group',
+ ];
+
+ yield [
+ 'test_something_098_different',
+ 'form[name="test_something_098_different"] .form-group',
+ ];
+ }
+
+ /**
+ * Provides name of form, name of field and expected selector
+ *
+ * @return Generator
+ */
+ public function provideFormNameFieldNameAndSelector()
+ {
+ yield [
+ 'test',
+ 'test',
+ 'form[name="test"] label[for="test"] .invalid-feedback .form-error-message',
+ ];
+
+ yield [
+ 'test-123-test-456',
+ 'great-000-field',
+ 'form[name="test-123-test-456"] label[for="great-000-field"] .invalid-feedback .form-error-message',
+ ];
+
+ yield [
+ 'test_something_098_different',
+ 'this-is-the-123789-field',
+ 'form[name="test_something_098_different"] label[for="this-is-the-123789-field"] .invalid-feedback .form-error-message',
+ ];
+ }
+
+ /**
+ * Provides name of form, index/position of the field-set and expected selector
+ *
+ * @return Generator
+ */
+ public function provideFormNameFieldSetIndexAndSelector()
+ {
+ yield [
+ 'test',
+ 0,
+ 'form[name="test"] fieldset:nth-of-type(0) legend.col-form-label .invalid-feedback .form-error-message',
+ ];
+
+ yield [
+ 'test-123-test-456',
+ 1,
+ 'form[name="test-123-test-456"] fieldset:nth-of-type(1) legend.col-form-label .invalid-feedback .form-error-message',
+ ];
+
+ yield [
+ 'test_something_098_different',
+ 1245,
+ 'form[name="test_something_098_different"] fieldset:nth-of-type(1245) legend.col-form-label .invalid-feedback .form-error-message',
+ ];
+ }
+
public function testConstructor()
{
static::assertHasNoConstructor(Bootstrap4CssSelector::class);
}
+ public function testGetFieldErrorContainerSelector()
+ {
+ static::assertSame('.invalid-feedback .form-error-message', Bootstrap4CssSelector::getFieldErrorContainerSelector());
+ }
+
+ /**
+ * @param string $formName Name of form (value of the "name" attribute)
+ * @param string $fieldName Name of field (value of the "name" attribute)
+ * @param string $expected Expected selector
+ *
+ * @dataProvider provideFormNameFieldNameAndSelector
+ */
+ public function testGetFieldErrorSelector($formName, $fieldName, $expected)
+ {
+ static::assertSame($expected, Bootstrap4CssSelector::getFieldErrorSelector($formName, $fieldName));
+ }
+
+ /**
+ * @param string $emptyValue Name of field (value of the "name" attribute)
+ * @dataProvider provideEmptyScalarValue
+ */
+ public function testGetFieldErrorSelectorUsingEmptyFieldName($emptyValue)
+ {
+ $formName = 'test';
+ static::assertSame('', Bootstrap4CssSelector::getFieldErrorSelector($formName, $emptyValue));
+ }
+
/**
* @param string $emptyValue Name of form (value of the "name" attribute)
* @dataProvider provideEmptyScalarValue
*/
- public function testGetRadioButtonErrorSelectorUsingEmptyFormName($emptyValue)
+ public function testGetFieldErrorSelectorUsingEmptyFormName($emptyValue)
{
- $fieldSetIndex = 1;
- static::assertSame('', Bootstrap4CssSelector::getRadioButtonErrorSelector($emptyValue, $fieldSetIndex));
+ $fieldName = 'test';
+ static::assertSame('', Bootstrap4CssSelector::getFieldErrorSelector($emptyValue, $fieldName));
}
- public function testGetRadioButtonErrorSelectorUsingNegativeFieldSetIndex()
+ /**
+ * @param string $formName Name of form (value of the "name" attribute)
+ * @param string $expected Expected selector
+ *
+ * @dataProvider provideFormNameAndSelector
+ */
+ public function testGetFieldGroupSelector($formName, $expected)
{
- static::assertSame('', Bootstrap4CssSelector::getRadioButtonErrorSelector('test-test', -1));
+ static::assertSame($expected, Bootstrap4CssSelector::getFieldGroupSelector($formName));
+ }
+
+ /**
+ * @param string $emptyValue Name of form (value of the "name" attribute)
+ * @dataProvider provideEmptyScalarValue
+ */
+ public function testGetFieldGroupSelectorUsingEmptyFormName($emptyValue)
+ {
+ static::assertSame('', Bootstrap4CssSelector::getFieldGroupSelector($emptyValue));
}
/**
@@ -55,131 +176,14 @@ class Bootstrap4CssSelectorTest extends BaseTestCase
* @param string $emptyValue Name of form (value of the "name" attribute)
* @dataProvider provideEmptyScalarValue
*/
- public function testGetFieldErrorSelectorUsingEmptyFormName($emptyValue)
+ public function testGetRadioButtonErrorSelectorUsingEmptyFormName($emptyValue)
{
- $fieldName = 'test';
- static::assertSame('', Bootstrap4CssSelector::getFieldErrorSelector($emptyValue, $fieldName));
+ $fieldSetIndex = 1;
+ static::assertSame('', Bootstrap4CssSelector::getRadioButtonErrorSelector($emptyValue, $fieldSetIndex));
}
- /**
- * @param string $emptyValue Name of field (value of the "name" attribute)
- * @dataProvider provideEmptyScalarValue
- */
- public function testGetFieldErrorSelectorUsingEmptyFieldName($emptyValue)
+ public function testGetRadioButtonErrorSelectorUsingNegativeFieldSetIndex()
{
- $formName = 'test';
- static::assertSame('', Bootstrap4CssSelector::getFieldErrorSelector($formName, $emptyValue));
- }
-
- /**
- * @param string $formName Name of form (value of the "name" attribute)
- * @param string $fieldName Name of field (value of the "name" attribute)
- * @param string $expected Expected selector
- *
- * @dataProvider provideFormNameFieldNameAndSelector
- */
- public function testGetFieldErrorSelector($formName, $fieldName, $expected)
- {
- static::assertSame($expected, Bootstrap4CssSelector::getFieldErrorSelector($formName, $fieldName));
- }
-
- /**
- * @param string $emptyValue Name of form (value of the "name" attribute)
- * @dataProvider provideEmptyScalarValue
- */
- public function testGetFieldGroupSelectorUsingEmptyFormName($emptyValue)
- {
- static::assertSame('', Bootstrap4CssSelector::getFieldGroupSelector($emptyValue));
- }
-
- /**
- * @param string $formName Name of form (value of the "name" attribute)
- * @param string $expected Expected selector
- *
- * @dataProvider provideFormNameAndSelector
- */
- public function testGetFieldGroupSelector($formName, $expected)
- {
- static::assertSame($expected, Bootstrap4CssSelector::getFieldGroupSelector($formName));
- }
-
- public function testGetFieldErrorContainerSelector()
- {
- static::assertSame('.invalid-feedback .form-error-message', Bootstrap4CssSelector::getFieldErrorContainerSelector());
- }
-
- /**
- * Provides name of form, index/position of the field-set and expected selector
- *
- * @return \Generator
- */
- public function provideFormNameFieldSetIndexAndSelector()
- {
- yield[
- 'test',
- 0,
- 'form[name="test"] fieldset:nth-of-type(0) legend.col-form-label .invalid-feedback .form-error-message',
- ];
-
- yield[
- 'test-123-test-456',
- 1,
- 'form[name="test-123-test-456"] fieldset:nth-of-type(1) legend.col-form-label .invalid-feedback .form-error-message',
- ];
-
- yield[
- 'test_something_098_different',
- 1245,
- 'form[name="test_something_098_different"] fieldset:nth-of-type(1245) legend.col-form-label .invalid-feedback .form-error-message',
- ];
- }
-
- /**
- * Provides name of form, name of field and expected selector
- *
- * @return \Generator
- */
- public function provideFormNameFieldNameAndSelector()
- {
- yield[
- 'test',
- 'test',
- 'form[name="test"] label[for="test"] .invalid-feedback .form-error-message',
- ];
-
- yield[
- 'test-123-test-456',
- 'great-000-field',
- 'form[name="test-123-test-456"] label[for="great-000-field"] .invalid-feedback .form-error-message',
- ];
-
- yield[
- 'test_something_098_different',
- 'this-is-the-123789-field',
- 'form[name="test_something_098_different"] label[for="this-is-the-123789-field"] .invalid-feedback .form-error-message',
- ];
- }
-
- /**
- * Provides name of form and expected selector
- *
- * @return \Generator
- */
- public function provideFormNameAndSelector()
- {
- yield[
- 'test',
- 'form[name="test"] .form-group',
- ];
-
- yield[
- 'test-123-test-456',
- 'form[name="test-123-test-456"] .form-group',
- ];
-
- yield[
- 'test_something_098_different',
- 'form[name="test_something_098_different"] .form-group',
- ];
+ static::assertSame('', Bootstrap4CssSelector::getRadioButtonErrorSelector('test-test', -1));
}
}
diff --git a/tests/Utilities/BundleTest.php b/tests/Utilities/BundleTest.php
index 92dd655..13a74ac 100644
--- a/tests/Utilities/BundleTest.php
+++ b/tests/Utilities/BundleTest.php
@@ -18,14 +18,176 @@ use Meritoo\Common\Utilities\Bundle;
*
* @author Meritoo
* @copyright Meritoo
+ *
+ * @internal
+ * @covers \Meritoo\Common\Utilities\Bundle
*/
class BundleTest extends BaseTestCase
{
+ /**
+ * Provides empty path of the view / template and/or name of bundle
+ *
+ * @return Generator
+ */
+ public function provideEmptyViewPathAndBundle()
+ {
+ yield [
+ '',
+ '',
+ ];
+
+ yield [
+ 'test',
+ '',
+ ];
+
+ yield [
+ '',
+ 'test',
+ ];
+ }
+
+ /**
+ * Provides full and short name of bundle
+ *
+ * @return Generator
+ */
+ public function provideFullAndShortBundleName()
+ {
+ yield [
+ 'MyExtraBundle',
+ 'MyExtra',
+ ];
+
+ yield [
+ 'MySuperExtraGorgeousBundle',
+ 'MySuperExtraGorgeous',
+ ];
+ }
+
+ /**
+ * Provides incorrect name of bundle
+ *
+ * @return Generator
+ */
+ public function provideIncorrectBundleName()
+ {
+ yield [
+ 'myExtra',
+ ];
+
+ yield [
+ 'MyExtra',
+ ];
+
+ yield [
+ 'MySuperExtraGorgeous',
+ ];
+ }
+
+ /**
+ * Provides path of the view / template and name of bundle
+ *
+ * @return Generator
+ */
+ public function provideViewPathAndBundle()
+ {
+ yield [
+ 'User',
+ 'MyExtraBundle',
+ '@MyExtra/User.html.twig',
+ ];
+
+ yield [
+ 'User:Active',
+ 'MyExtraBundle',
+ '@MyExtra/User/Active.html.twig',
+ ];
+
+ yield [
+ 'User:Active',
+ 'MySuperExtraGorgeousBundle',
+ '@MySuperExtraGorgeous/User/Active.html.twig',
+ ];
+ }
+
+ /**
+ * Provides path of the view / template, name of bundle and extension of the view / template
+ *
+ * @return Generator
+ */
+ public function provideViewPathAndBundleAndExtension()
+ {
+ yield [
+ 'User:Active',
+ 'MyExtraBundle',
+ '',
+ null,
+ ];
+
+ yield [
+ 'User:Active',
+ 'MyExtraBundle',
+ 'js.twig',
+ '@MyExtra/User/Active.js.twig',
+ ];
+ }
+
+ /**
+ * Provides path of the view / template and incorrect name of bundle
+ *
+ * @return Generator
+ */
+ public function provideViewPathAndIncorrectBundleName()
+ {
+ yield [
+ 'User:Active',
+ 'myExtra',
+ ];
+
+ yield [
+ 'User:Active',
+ 'MyExtra',
+ ];
+
+ yield [
+ 'User:Active',
+ 'MySuperExtraGorgeous',
+ ];
+ }
+
public function testConstructor()
{
static::assertHasNoConstructor(Bundle::class);
}
+ /**
+ * @param string $viewPath Path of the view / template, e.g. "MyDirectory/my-template"
+ * @param string $bundleName Full name of the bundle, e.g. "MyExtraBundle"
+ * @param string $extension (optional) Extension of the view / template
+ * @param string $expected Expected path to view / template
+ *
+ * @throws IncorrectBundleNameException
+ * @dataProvider provideViewPathAndBundleAndExtension
+ */
+ public function testGetBundleViewPathUsingCustomExtension($viewPath, $bundleName, $extension, $expected)
+ {
+ self::assertEquals($expected, Bundle::getBundleViewPath($viewPath, $bundleName, $extension));
+ }
+
+ /**
+ * @param string $viewPath Path of the view / template, e.g. "MyDirectory/my-template"
+ * @param string $bundleName Full name of the bundle, e.g. "MyExtraBundle"
+ * @param string $expected Expected path to view / template
+ *
+ * @throws IncorrectBundleNameException
+ * @dataProvider provideViewPathAndBundle
+ */
+ public function testGetBundleViewPathUsingDefaultExtension($viewPath, $bundleName, $expected)
+ {
+ self::assertEquals($expected, Bundle::getBundleViewPath($viewPath, $bundleName));
+ }
+
/**
* @param string $viewPath Path of the view / template, e.g. "MyDirectory/my-template"
* @param string $bundleName Full name of the bundle, e.g. "MyExtraBundle"
@@ -47,65 +209,14 @@ class BundleTest extends BaseTestCase
public function testGetBundleViewPathUsingIncorrectBundleName($viewPath, $bundleName)
{
$template = 'Name of bundle \'%s\' is incorrect. It should start with big letter and end with "Bundle". Is'
- . ' there everything ok?';
+ .' there everything ok?';
- $message = sprintf($template, $bundleName);
- $this->setExpectedException(IncorrectBundleNameException::class, $message);
+ $this->expectException(IncorrectBundleNameException::class);
+ $this->expectExceptionMessage(sprintf($template, $bundleName));
Bundle::getBundleViewPath($viewPath, $bundleName);
}
- /**
- * @param string $viewPath Path of the view / template, e.g. "MyDirectory/my-template"
- * @param string $bundleName Full name of the bundle, e.g. "MyExtraBundle"
- * @param string $expected Expected path to view / template
- *
- * @throws IncorrectBundleNameException
- * @dataProvider provideViewPathAndBundle
- */
- public function testGetBundleViewPathUsingDefaultExtension($viewPath, $bundleName, $expected)
- {
- self::assertEquals($expected, Bundle::getBundleViewPath($viewPath, $bundleName));
- }
-
- /**
- * @param string $viewPath Path of the view / template, e.g. "MyDirectory/my-template"
- * @param string $bundleName Full name of the bundle, e.g. "MyExtraBundle"
- * @param string $extension (optional) Extension of the view / template
- * @param string $expected Expected path to view / template
- *
- * @throws IncorrectBundleNameException
- * @dataProvider provideViewPathAndBundleAndExtension
- */
- public function testGetBundleViewPathUsingCustomExtension($viewPath, $bundleName, $extension, $expected)
- {
- self::assertEquals($expected, Bundle::getBundleViewPath($viewPath, $bundleName, $extension));
- }
-
- /**
- * @param mixed $emptyValue Empty value, e.g. ""
- *
- * @throws IncorrectBundleNameException
- * @dataProvider provideEmptyValue
- */
- public function testGetShortBundleNameUsingEmptyValue($emptyValue)
- {
- $this->setExpectedException(IncorrectBundleNameException::class);
- Bundle::getShortBundleName($emptyValue);
- }
-
- /**
- * @param string $bundleName Full name of the bundle, e.g. "MyExtraBundle"
- *
- * @throws IncorrectBundleNameException
- * @dataProvider provideIncorrectBundleName
- */
- public function testGetShortBundleNameUsingIncorrectBundleName($bundleName)
- {
- $this->setExpectedException(IncorrectBundleNameException::class);
- Bundle::getShortBundleName($bundleName);
- }
-
/**
* @param string $fullBundleName Full name of the bundle, e.g. "MyExtraBundle"
* @param string $shortBundleName Short name of bundle (without "Bundle")
@@ -118,135 +229,21 @@ class BundleTest extends BaseTestCase
self::assertEquals($shortBundleName, Bundle::getShortBundleName($fullBundleName));
}
- /**
- * Provides empty path of the view / template and/or name of bundle
- *
- * @return Generator
- */
- public function provideEmptyViewPathAndBundle()
+ public function testGetShortBundleNameUsingEmptyValue(): void
{
- yield[
- '',
- '',
- ];
-
- yield[
- 'test',
- '',
- ];
-
- yield[
- '',
- 'test',
- ];
+ $this->expectException(IncorrectBundleNameException::class);
+ Bundle::getShortBundleName('');
}
/**
- * Provides path of the view / template and incorrect name of bundle
+ * @param string $bundleName Full name of the bundle, e.g. "MyExtraBundle"
*
- * @return Generator
+ * @throws IncorrectBundleNameException
+ * @dataProvider provideIncorrectBundleName
*/
- public function provideViewPathAndIncorrectBundleName()
+ public function testGetShortBundleNameUsingIncorrectBundleName($bundleName)
{
- yield[
- 'User:Active',
- 'myExtra',
- ];
-
- yield[
- 'User:Active',
- 'MyExtra',
- ];
-
- yield[
- 'User:Active',
- 'MySuperExtraGorgeous',
- ];
- }
-
- /**
- * Provides path of the view / template and name of bundle
- *
- * @return Generator
- */
- public function provideViewPathAndBundle()
- {
- yield[
- 'User',
- 'MyExtraBundle',
- '@MyExtra/User.html.twig',
- ];
-
- yield[
- 'User:Active',
- 'MyExtraBundle',
- '@MyExtra/User/Active.html.twig',
- ];
-
- yield[
- 'User:Active',
- 'MySuperExtraGorgeousBundle',
- '@MySuperExtraGorgeous/User/Active.html.twig',
- ];
- }
-
- /**
- * Provides path of the view / template, name of bundle and extension of the view / template
- *
- * @return Generator
- */
- public function provideViewPathAndBundleAndExtension()
- {
- yield[
- 'User:Active',
- 'MyExtraBundle',
- '',
- null,
- ];
-
- yield[
- 'User:Active',
- 'MyExtraBundle',
- 'js.twig',
- '@MyExtra/User/Active.js.twig',
- ];
- }
-
- /**
- * Provides incorrect name of bundle
- *
- * @return Generator
- */
- public function provideIncorrectBundleName()
- {
- yield[
- 'myExtra',
- ];
-
- yield[
- 'MyExtra',
- ];
-
- yield[
- 'MySuperExtraGorgeous',
- ];
- }
-
- /**
- * Provides full and short name of bundle
- *
- * @return Generator
- */
- public function provideFullAndShortBundleName()
- {
- yield[
- 'MyExtraBundle',
- 'MyExtra',
- ];
-
- yield[
- 'MySuperExtraGorgeousBundle',
- 'MySuperExtraGorgeous',
- ];
+ $this->expectException(IncorrectBundleNameException::class);
+ Bundle::getShortBundleName($bundleName);
}
}
diff --git a/tests/Utilities/ComposerTest.php b/tests/Utilities/ComposerTest.php
index 10e4177..e1bc69f 100644
--- a/tests/Utilities/ComposerTest.php
+++ b/tests/Utilities/ComposerTest.php
@@ -17,6 +17,9 @@ use Meritoo\Common\Utilities\Composer;
*
* @author Meritoo
* @copyright Meritoo
+ *
+ * @internal
+ * @covers \Meritoo\Common\Utilities\Composer
*/
class ComposerTest extends BaseTestCase
{
@@ -27,64 +30,56 @@ class ComposerTest extends BaseTestCase
*/
private $composerJsonPath;
+ /**
+ * Provides names and values of existing nodes
+ *
+ * @return Generator
+ */
+ public function getExistingNode(): Generator
+ {
+ yield [
+ 'name',
+ 'test/test',
+ ];
+
+ yield [
+ 'version',
+ '1.0.2',
+ ];
+ }
+
public function testConstructor()
{
static::assertHasNoConstructor(Composer::class);
}
- /**
- * @param string $composerJsonPath Empty value, e.g. ""
- * @dataProvider provideEmptyValue
- */
- public function testGetValueNotExistingComposerJson($composerJsonPath)
- {
- self::assertNull(Composer::getValue($composerJsonPath, ''));
- self::assertNull(Composer::getValue('not/existing/composer.json', ''));
- }
-
- /**
- * @param string $nodeName Empty value, e.g. ""
- * @dataProvider provideEmptyValue
- */
- public function testGetValueNotExistingNode($nodeName)
- {
- self::assertNull(Composer::getValue($this->composerJsonPath, $nodeName));
- self::assertNull(Composer::getValue($this->composerJsonPath, 'not_existing_node'));
- }
-
/**
* @param string $nodeName Name of existing node
* @param string $nodeValue Value of existing node
*
* @dataProvider getExistingNode
*/
- public function testGetValueExistingNode($nodeName, $nodeValue)
+ public function testGetValueExistingNode(string $nodeName, string $nodeValue): void
{
self::assertEquals($nodeValue, Composer::getValue($this->composerJsonPath, $nodeName));
}
- /**
- * Provides names and values of existing nodes
- *
- * @return Generator
- */
- public function getExistingNode()
+ public function testGetValueNotExistingComposerJson(): void
{
- yield[
- 'name',
- 'test/test',
- ];
+ self::assertNull(Composer::getValue('', ''));
+ self::assertNull(Composer::getValue('not/existing/composer.json', ''));
+ }
- yield[
- 'version',
- '1.0.2',
- ];
+ public function testGetValueNotExistingNode(): void
+ {
+ self::assertNull(Composer::getValue($this->composerJsonPath, ''));
+ self::assertNull(Composer::getValue($this->composerJsonPath, 'not_existing_node'));
}
/**
* {@inheritdoc}
*/
- protected function setUp()
+ protected function setUp(): void
{
parent::setUp();
diff --git a/tests/Utilities/CssSelectorTest.php b/tests/Utilities/CssSelectorTest.php
index 0ab9535..6f4e3f3 100644
--- a/tests/Utilities/CssSelectorTest.php
+++ b/tests/Utilities/CssSelectorTest.php
@@ -8,6 +8,7 @@
namespace Meritoo\Test\Common\Utilities;
+use Generator;
use Meritoo\Common\Test\Base\BaseTestCase;
use Meritoo\Common\Utilities\CssSelector;
@@ -16,128 +17,154 @@ use Meritoo\Common\Utilities\CssSelector;
*
* @author Meritoo
* @copyright Meritoo
+ *
+ * @internal
+ * @covers \Meritoo\Common\Utilities\CssSelector
*/
class CssSelectorTest extends BaseTestCase
{
+ /**
+ * Provides name of form and selector of the form
+ *
+ * @return Generator
+ */
+ public function provideFormNameAndSelector()
+ {
+ yield [
+ 'test',
+ 'form[name="test"]',
+ ];
+
+ yield [
+ 'test-123-test-456',
+ 'form[name="test-123-test-456"]',
+ ];
+
+ yield [
+ 'test_something_098_different',
+ 'form[name="test_something_098_different"]',
+ ];
+ }
+
+ /**
+ * Provides name of form, ID of field and expected selector of label
+ *
+ * @return Generator
+ */
+ public function provideFormNameFieldIdAndLabelSelector()
+ {
+ yield [
+ 'test',
+ 'test',
+ 'form[name="test"] label[for="test"]',
+ ];
+
+ yield [
+ 'test-123-test-456',
+ 'great-000-field',
+ 'form[name="test-123-test-456"] label[for="great-000-field"]',
+ ];
+
+ yield [
+ 'test_something_098_different',
+ 'this-is-the-123789-field',
+ 'form[name="test_something_098_different"] label[for="this-is-the-123789-field"]',
+ ];
+ }
+
+ /**
+ * Provides name of form, ID of field and expected selector
+ *
+ * @return Generator
+ */
+ public function provideFormNameFieldIdAndSelector()
+ {
+ yield [
+ 'test',
+ 'test',
+ 'form[name="test"] input#test',
+ ];
+
+ yield [
+ 'test-123-test-456',
+ 'great-000-field',
+ 'form[name="test-123-test-456"] input#great-000-field',
+ ];
+
+ yield [
+ 'test_something_098_different',
+ 'this-is-the-123789-field',
+ 'form[name="test_something_098_different"] input#this-is-the-123789-field',
+ ];
+ }
+
+ /**
+ * Provides name of form, name of field and expected selector
+ *
+ * @return Generator
+ */
+ public function provideFormNameFieldNameAndSelector()
+ {
+ yield [
+ 'test',
+ 'test',
+ 'form[name="test"] input[name="test"]',
+ ];
+
+ yield [
+ 'test-123-test-456',
+ 'great-000-field',
+ 'form[name="test-123-test-456"] input[name="great-000-field"]',
+ ];
+
+ yield [
+ 'test_something_098_different',
+ 'this-is-the-123789-field',
+ 'form[name="test_something_098_different"] input[name="this-is-the-123789-field"]',
+ ];
+ }
+
+ /**
+ * Provides name of form, index/position of the field-set and expected selector
+ *
+ * @return Generator
+ */
+ public function provideFormNameFieldSetIndexAndSelector()
+ {
+ yield [
+ 'test',
+ 0,
+ 'form[name="test"] fieldset:nth-of-type(0)',
+ ];
+
+ yield [
+ 'test-123-test-456',
+ 1,
+ 'form[name="test-123-test-456"] fieldset:nth-of-type(1)',
+ ];
+
+ yield [
+ 'test_something_098_different',
+ 1245,
+ 'form[name="test_something_098_different"] fieldset:nth-of-type(1245)',
+ ];
+ }
+
public function testConstructor()
{
static::assertHasNoConstructor(CssSelector::class);
}
/**
- * @param string $emptyValue Name of form (value of the "name" attribute)
- * @dataProvider provideEmptyScalarValue
- */
- public function testGetFormByNameSelectorUsingEmptyName($emptyValue)
- {
- static::assertSame('', CssSelector::getFormByNameSelector($emptyValue));
- }
-
- /**
- * @param string $formName Name of form (value of the "name" attribute)
- * @param string $expected Expected selector
+ * @param string $formName Name of form (value of the "name" attribute)
+ * @param int $fieldSetIndex Index/Position of the field-set
+ * @param string $expected Expected selector
*
- * @dataProvider provideFormNameAndSelector
+ * @dataProvider provideFormNameFieldSetIndexAndSelector
*/
- public function testGetFormByNameSelector($formName, $expected)
+ public function testGetFieldSetByIndexSelector($formName, $fieldSetIndex, $expected)
{
- static::assertSame($expected, CssSelector::getFormByNameSelector($formName));
- }
-
- /**
- * @param string $emptyValue Name of form (value of the "name" attribute)
- * @dataProvider provideEmptyScalarValue
- */
- public function testGetInputByNameSelectorUsingEmptyFormName($emptyValue)
- {
- $fieldName = 'test-test';
- static::assertSame('', CssSelector::getInputByNameSelector($emptyValue, $fieldName));
- }
-
- /**
- * @param string $emptyValue Name of field (value of the "name" attribute)
- * @dataProvider provideEmptyScalarValue
- */
- public function testGetInputByNameSelectorUsingEmptyFieldName($emptyValue)
- {
- $formName = 'test-test';
- static::assertSame('', CssSelector::getInputByNameSelector($formName, $emptyValue));
- }
-
- /**
- * @param string $formName Name of form (value of the "name" attribute)
- * @param string $fieldName Name of field (value of the "name" attribute)
- * @param string $expected Expected selector
- *
- * @dataProvider provideFormNameFieldNameAndSelector
- */
- public function testGetInputByNameSelector($formName, $fieldName, $expected)
- {
- static::assertSame($expected, CssSelector::getInputByNameSelector($formName, $fieldName));
- }
-
- /**
- * @param string $emptyValue Name of form (value of the "name" attribute)
- * @dataProvider provideEmptyScalarValue
- */
- public function testGetInputByIdSelectorUsingEmptyFormName($emptyValue)
- {
- $fieldId = 'test-test';
- static::assertSame('', CssSelector::getInputByIdSelector($emptyValue, $fieldId));
- }
-
- /**
- * @param string $emptyValue ID of field (value of the "id" attribute)
- * @dataProvider provideEmptyScalarValue
- */
- public function testGetInputByIdSelectorUsingEmptyFieldName($emptyValue)
- {
- $formName = 'test-test';
- static::assertSame('', CssSelector::getInputByIdSelector($formName, $emptyValue));
- }
-
- /**
- * @param string $formName Name of form (value of the "name" attribute)
- * @param string $fieldId ID of field (value of the "id" attribute)
- * @param string $expected Expected selector
- *
- * @dataProvider provideFormNameFieldIdAndSelector
- */
- public function testGetInputByIdSelector($formName, $fieldId, $expected)
- {
- static::assertSame($expected, CssSelector::getInputByIdSelector($formName, $fieldId));
- }
-
- /**
- * @param string $emptyValue Name of form (value of the "name" attribute)
- * @dataProvider provideEmptyScalarValue
- */
- public function testGetLabelSelectorUsingEmptyFormName($emptyValue)
- {
- $fieldId = 'test-test';
- static::assertSame('', CssSelector::getLabelSelector($emptyValue, $fieldId));
- }
-
- /**
- * @param string $emptyValue ID of field (value of the "id" attribute)
- * @dataProvider provideEmptyScalarValue
- */
- public function testGetLabelSelectorUsingEmptyFieldId($emptyValue)
- {
- $formName = 'test-test';
- static::assertSame('', CssSelector::getLabelSelector($formName, $emptyValue));
- }
-
- /**
- * @param string $formName Name of form (value of the "name" attribute)
- * @param string $fieldId ID of field (value of the "id" attribute)
- * @param string $expected Expected selector
- *
- * @dataProvider provideFormNameFieldIdAndLabelSelector
- */
- public function testGetLabelSelector($formName, $fieldId, $expected)
- {
- static::assertSame($expected, CssSelector::getLabelSelector($formName, $fieldId));
+ static::assertSame($expected, CssSelector::getFieldSetByIndexSelector($formName, $fieldSetIndex));
}
/**
@@ -156,141 +183,118 @@ class CssSelectorTest extends BaseTestCase
}
/**
- * @param string $formName Name of form (value of the "name" attribute)
- * @param int $fieldSetIndex Index/Position of the field-set
- * @param string $expected Expected selector
+ * @param string $formName Name of form (value of the "name" attribute)
+ * @param string $expected Expected selector
*
- * @dataProvider provideFormNameFieldSetIndexAndSelector
+ * @dataProvider provideFormNameAndSelector
*/
- public function testGetFieldSetByIndexSelector($formName, $fieldSetIndex, $expected)
+ public function testGetFormByNameSelector($formName, $expected)
{
- static::assertSame($expected, CssSelector::getFieldSetByIndexSelector($formName, $fieldSetIndex));
+ static::assertSame($expected, CssSelector::getFormByNameSelector($formName));
}
/**
- * Provides name of form and selector of the form
- *
- * @return \Generator
+ * @param string $emptyValue Name of form (value of the "name" attribute)
+ * @dataProvider provideEmptyScalarValue
*/
- public function provideFormNameAndSelector()
+ public function testGetFormByNameSelectorUsingEmptyName($emptyValue)
{
- yield[
- 'test',
- 'form[name="test"]',
- ];
-
- yield[
- 'test-123-test-456',
- 'form[name="test-123-test-456"]',
- ];
-
- yield[
- 'test_something_098_different',
- 'form[name="test_something_098_different"]',
- ];
+ static::assertSame('', CssSelector::getFormByNameSelector($emptyValue));
}
/**
- * Provides name of form, name of field and expected selector
+ * @param string $formName Name of form (value of the "name" attribute)
+ * @param string $fieldId ID of field (value of the "id" attribute)
+ * @param string $expected Expected selector
*
- * @return \Generator
+ * @dataProvider provideFormNameFieldIdAndSelector
*/
- public function provideFormNameFieldNameAndSelector()
+ public function testGetInputByIdSelector($formName, $fieldId, $expected)
{
- yield[
- 'test',
- 'test',
- 'form[name="test"] input[name="test"]',
- ];
-
- yield[
- 'test-123-test-456',
- 'great-000-field',
- 'form[name="test-123-test-456"] input[name="great-000-field"]',
- ];
-
- yield[
- 'test_something_098_different',
- 'this-is-the-123789-field',
- 'form[name="test_something_098_different"] input[name="this-is-the-123789-field"]',
- ];
+ static::assertSame($expected, CssSelector::getInputByIdSelector($formName, $fieldId));
}
/**
- * Provides name of form, ID of field and expected selector of label
- *
- * @return \Generator
+ * @param string $emptyValue ID of field (value of the "id" attribute)
+ * @dataProvider provideEmptyScalarValue
*/
- public function provideFormNameFieldIdAndLabelSelector()
+ public function testGetInputByIdSelectorUsingEmptyFieldName($emptyValue)
{
- yield[
- 'test',
- 'test',
- 'form[name="test"] label[for="test"]',
- ];
-
- yield[
- 'test-123-test-456',
- 'great-000-field',
- 'form[name="test-123-test-456"] label[for="great-000-field"]',
- ];
-
- yield[
- 'test_something_098_different',
- 'this-is-the-123789-field',
- 'form[name="test_something_098_different"] label[for="this-is-the-123789-field"]',
- ];
+ $formName = 'test-test';
+ static::assertSame('', CssSelector::getInputByIdSelector($formName, $emptyValue));
}
/**
- * Provides name of form, index/position of the field-set and expected selector
- *
- * @return \Generator
+ * @param string $emptyValue Name of form (value of the "name" attribute)
+ * @dataProvider provideEmptyScalarValue
*/
- public function provideFormNameFieldSetIndexAndSelector()
+ public function testGetInputByIdSelectorUsingEmptyFormName($emptyValue)
{
- yield[
- 'test',
- 0,
- 'form[name="test"] fieldset:nth-of-type(0)',
- ];
-
- yield[
- 'test-123-test-456',
- 1,
- 'form[name="test-123-test-456"] fieldset:nth-of-type(1)',
- ];
-
- yield[
- 'test_something_098_different',
- 1245,
- 'form[name="test_something_098_different"] fieldset:nth-of-type(1245)',
- ];
+ $fieldId = 'test-test';
+ static::assertSame('', CssSelector::getInputByIdSelector($emptyValue, $fieldId));
}
/**
- * Provides name of form, ID of field and expected selector
+ * @param string $formName Name of form (value of the "name" attribute)
+ * @param string $fieldName Name of field (value of the "name" attribute)
+ * @param string $expected Expected selector
*
- * @return \Generator
+ * @dataProvider provideFormNameFieldNameAndSelector
*/
- public function provideFormNameFieldIdAndSelector()
+ public function testGetInputByNameSelector($formName, $fieldName, $expected)
{
- yield[
- 'test',
- 'test',
- 'form[name="test"] input#test',
- ];
+ static::assertSame($expected, CssSelector::getInputByNameSelector($formName, $fieldName));
+ }
- yield[
- 'test-123-test-456',
- 'great-000-field',
- 'form[name="test-123-test-456"] input#great-000-field',
- ];
+ /**
+ * @param string $emptyValue Name of field (value of the "name" attribute)
+ * @dataProvider provideEmptyScalarValue
+ */
+ public function testGetInputByNameSelectorUsingEmptyFieldName($emptyValue)
+ {
+ $formName = 'test-test';
+ static::assertSame('', CssSelector::getInputByNameSelector($formName, $emptyValue));
+ }
- yield[
- 'test_something_098_different',
- 'this-is-the-123789-field',
- 'form[name="test_something_098_different"] input#this-is-the-123789-field',
- ];
+ /**
+ * @param string $emptyValue Name of form (value of the "name" attribute)
+ * @dataProvider provideEmptyScalarValue
+ */
+ public function testGetInputByNameSelectorUsingEmptyFormName($emptyValue)
+ {
+ $fieldName = 'test-test';
+ static::assertSame('', CssSelector::getInputByNameSelector($emptyValue, $fieldName));
+ }
+
+ /**
+ * @param string $formName Name of form (value of the "name" attribute)
+ * @param string $fieldId ID of field (value of the "id" attribute)
+ * @param string $expected Expected selector
+ *
+ * @dataProvider provideFormNameFieldIdAndLabelSelector
+ */
+ public function testGetLabelSelector($formName, $fieldId, $expected)
+ {
+ static::assertSame($expected, CssSelector::getLabelSelector($formName, $fieldId));
+ }
+
+ /**
+ * @param string $emptyValue ID of field (value of the "id" attribute)
+ * @dataProvider provideEmptyScalarValue
+ */
+ public function testGetLabelSelectorUsingEmptyFieldId($emptyValue)
+ {
+ $formName = 'test-test';
+ static::assertSame('', CssSelector::getLabelSelector($formName, $emptyValue));
+ }
+
+ /**
+ * @param string $emptyValue Name of form (value of the "name" attribute)
+ * @dataProvider provideEmptyScalarValue
+ */
+ public function testGetLabelSelectorUsingEmptyFormName($emptyValue)
+ {
+ $fieldId = 'test-test';
+ static::assertSame('', CssSelector::getLabelSelector($emptyValue, $fieldId));
}
}
diff --git a/tests/Utilities/DateTest.php b/tests/Utilities/DateTest.php
index 5fca3fe..5821e88 100644
--- a/tests/Utilities/DateTest.php
+++ b/tests/Utilities/DateTest.php
@@ -15,162 +15,390 @@ use Meritoo\Common\Exception\Type\UnknownDatePartTypeException;
use Meritoo\Common\Test\Base\BaseTestCase;
use Meritoo\Common\Type\DatePeriod;
use Meritoo\Common\Utilities\Date;
+use Meritoo\Common\Utilities\Locale;
/**
* Test case of the Date methods (only static functions)
*
* @author Meritoo
* @copyright Meritoo
+ *
+ * @internal
+ * @covers \Meritoo\Common\Utilities\Date
*/
class DateTest extends BaseTestCase
{
- public function testConstructor()
+ /**
+ * Provides correct period
+ *
+ * @return Generator
+ */
+ public function provideCorrectPeriod()
+ {
+ yield [
+ DatePeriod::LAST_WEEK,
+ new DatePeriod(
+ (new DateTime('this week'))->sub(new DateInterval('P7D'))->setTime(0, 0, 0),
+ (new DateTime('this week'))->sub(new DateInterval('P1D'))->setTime(23, 59, 59)
+ ),
+ ];
+
+ yield [
+ DatePeriod::THIS_WEEK,
+ new DatePeriod(
+ (new DateTime('this week'))->setTime(0, 0, 0),
+ (new DateTime('this week'))->add(new DateInterval('P6D'))->setTime(23, 59, 59)
+ ),
+ ];
+
+ yield [
+ DatePeriod::NEXT_WEEK,
+ new DatePeriod(
+ (new DateTime('this week'))->add(new DateInterval('P7D'))->setTime(0, 0, 0),
+ (new DateTime('this week'))->add(new DateInterval('P7D'))
+ ->add(new DateInterval('P6D'))
+ ->setTime(23, 59, 59)
+ ),
+ ];
+
+ yield [
+ DatePeriod::LAST_MONTH,
+ new DatePeriod(
+ (new DateTime('first day of last month'))->setTime(0, 0, 0),
+ (new DateTime('last day of last month'))->setTime(23, 59, 59)
+ ),
+ ];
+
+ yield [
+ DatePeriod::THIS_MONTH,
+ new DatePeriod(
+ Date::getDatesForPeriod(DatePeriod::LAST_MONTH)
+ ->getEndDate()
+ ->add(new DateInterval('P1D'))
+ ->setTime(0, 0, 0),
+ Date::getDatesForPeriod(DatePeriod::NEXT_MONTH)
+ ->getStartDate()
+ ->sub(new DateInterval('P1D'))
+ ->setTime(23, 59, 59)
+ ),
+ ];
+
+ yield [
+ DatePeriod::NEXT_MONTH,
+ new DatePeriod(
+ (new DateTime('first day of next month'))->setTime(0, 0, 0),
+ (new DateTime('last day of next month'))->setTime(23, 59, 59)
+ ),
+ ];
+
+ $lastYearStart = (new DateTime())->modify('-1 year');
+ $lastYearEnd = (new DateTime())->modify('-1 year');
+ $year = $lastYearStart->format('Y');
+
+ yield [
+ DatePeriod::LAST_YEAR,
+ new DatePeriod(
+ $lastYearStart->setDate($year, 1, 1)->setTime(0, 0, 0),
+ $lastYearEnd->setDate($year, 12, 31)->setTime(23, 59, 59)
+ ),
+ ];
+
+ $year = (new DateTime())->format('Y');
+
+ yield [
+ DatePeriod::THIS_YEAR,
+ new DatePeriod(
+ (new DateTime())->setDate($year, 1, 1)->setTime(0, 0, 0),
+ (new DateTime())->setDate($year, 12, 31)->setTime(23, 59, 59)
+ ),
+ ];
+
+ $nextYearStart = (new DateTime())->modify('1 year');
+ $nextYearEnd = (new DateTime())->modify('1 year');
+ $year = $nextYearStart->format('Y');
+
+ yield [
+ DatePeriod::NEXT_YEAR,
+ new DatePeriod(
+ $nextYearStart->setDate($year, 1, 1)->setTime(0, 0, 0),
+ $nextYearEnd->setDate($year, 12, 31)->setTime(23, 59, 59)
+ ),
+ ];
+ }
+
+ /**
+ * Provides data for the random date
+ *
+ * @return Generator
+ */
+ public function provideDataOfRandomDate()
+ {
+ yield [
+ new DateTime('2000-01-01'),
+ 1,
+ 100,
+ ];
+
+ yield [
+ new DateTime('2000-12-01'),
+ 1,
+ 100,
+ ];
+ yield [
+ new DateTime('2000-01-01'),
+ '1',
+ '100',
+ ];
+
+ yield [
+ new DateTime('2000-12-01'),
+ '1',
+ '100',
+ ];
+
+ yield [
+ new DateTime('2000-01-01'),
+ 10,
+ 50,
+ ];
+
+ yield [
+ new DateTime('2000-12-01'),
+ 10,
+ 50,
+ ];
+ }
+
+ /**
+ * Provides data for the random date with incorrect end of random partition
+ *
+ * @return Generator
+ */
+ public function provideDataOfRandomDateIncorrectEnd()
+ {
+ yield [
+ new DateTime('2000-01-01'),
+ 100,
+ 1,
+ ];
+ }
+
+ /**
+ * Provide empty dates for date difference
+ *
+ * @return Generator
+ */
+ public function provideEmptyDatesForDateDifference()
+ {
+ yield [
+ null,
+ null,
+ ];
+
+ yield [
+ '',
+ '',
+ ];
+
+ yield [
+ null,
+ new DateTime(),
+ ];
+
+ yield [
+ new DateTime(),
+ null,
+ ];
+ }
+
+ /**
+ * Provides incorrect invalidCount of DateTime
+ *
+ * @return Generator
+ */
+ public function provideIncorrectDateTimeValue()
+ {
+ // Incorrect one-character values
+ yield ['a'];
+ yield ['m'];
+
+ // Incorrect strings
+ yield ['ss'];
+ yield ['sss'];
+ yield ['mm'];
+ yield ['yy'];
+ yield ['yyyy'];
+
+ // Incorrect integer values
+ yield [1];
+ yield [10];
+ yield [15];
+ yield [100];
+ yield [1000];
+
+ // Incorrect string / numeric values
+ yield ['1'];
+ yield ['10'];
+ yield ['15'];
+ yield ['100'];
+ yield ['1000'];
+
+ // Incorrect dates
+ yield ['0-0-0'];
+ yield ['20-01-01'];
+ yield ['2015-0-0'];
+ yield ['2015-00-00'];
+ yield ['2015-16-01'];
+ }
+
+ /**
+ * Provides incorrect period
+ *
+ * @return Generator
+ */
+ public function provideIncorrectPeriod()
+ {
+ yield [-1];
+ yield [0];
+ yield [10];
+ }
+
+ /**
+ * Provides incorrect values of year, month and day
+ *
+ * @return Generator
+ */
+ public function provideIncorrectYearMonthDay(): Generator
+ {
+ yield [
+ 0,
+ 0,
+ 0,
+ ];
+
+ yield [
+ -1,
+ -1,
+ -1,
+ ];
+
+ yield [
+ 5000,
+ 50,
+ 50,
+ ];
+
+ yield [
+ 2000,
+ 13,
+ 01,
+ ];
+
+ yield [
+ 2000,
+ 01,
+ 40,
+ ];
+ }
+
+ /**
+ * Provides invalid format of date
+ *
+ * @return Generator
+ */
+ public function provideInvalidDateFormats()
+ {
+ yield [0];
+ yield [9];
+ yield ['[]'];
+ yield ['invalid'];
+ yield ['Q'];
+ yield [','];
+ yield ['.'];
+ yield ['aa###'];
+ yield ['Y/m/d H:i:invalid'];
+ }
+
+ /**
+ * Provides values of year, month and day
+ *
+ * @return Generator
+ */
+ public function provideYearMonthDay()
+ {
+ yield [
+ 2000,
+ 01,
+ 01,
+ ];
+
+ yield [
+ 2000,
+ 1,
+ 1,
+ ];
+
+ yield [
+ 2000,
+ 2,
+ 2,
+ ];
+
+ yield [
+ 2000,
+ 6,
+ 1,
+ ];
+
+ yield [
+ 2000,
+ 12,
+ 01,
+ ];
+
+ yield [
+ 2000,
+ 12,
+ 1,
+ ];
+
+ yield [
+ 2000,
+ 12,
+ 31,
+ ];
+ }
+
+ public function testConstructor(): void
{
static::assertHasNoConstructor(Date::class);
}
- /**
- * @param mixed $value Empty value, e.g. ""
- * @dataProvider provideEmptyValue
- */
- public function testGetDateTimeEmptyValue($value)
+ public function testGenerateRandomTimeCustomFormat(): void
{
- self::assertFalse(Date::getDateTime($value));
+ self::assertMatchesRegularExpression('/^0[1-9]{1}|1[0-2]{1}$/', Date::generateRandomTime('h')); // 01 through 12
+ self::assertMatchesRegularExpression('/^[0-5]?[0-9]$/', Date::generateRandomTime('i')); // 00 through 59
+ self::assertMatchesRegularExpression('/^[0-5]?[0-9]$/', Date::generateRandomTime('s')); // 00 through 59
+
+ self::assertMatchesRegularExpression('/^\d{2}:\d{2}$/', Date::generateRandomTime('H:i'));
+ self::assertMatchesRegularExpression('/^[1-9]|1[0-2]:\d{2}$/', Date::generateRandomTime('g:i'));
}
- /**
- * @param mixed $value Incorrect source of DateTime
- * @dataProvider provideIncorrectDateTimeValue
- */
- public function testGetDateTimeIncorrectValue($value)
+ public function testGenerateRandomTimeDefaultFormat(): void
{
- self::assertFalse(Date::getDateTime($value));
- }
-
- /**
- * @param bool $value The value which maybe is a date
- * @dataProvider provideBooleanValue
- */
- public function testGetDateTimeBoolean($value)
- {
- self::assertFalse(Date::getDateTime($value));
- }
-
- /**
- * @param string $relativeFormat Relative / compound format of DateTime
- * @dataProvider provideDateTimeRelativeFormat
- */
- public function testGetDateTimeRelativeFormats($relativeFormat)
- {
- /*
- * Values based on relative / compound formats, but... without explicitly declaring them as compound
- * (2nd argument set to false by default)
- *
- * http://php.net/manual/en/datetime.formats.compound.php
- */
- self::assertFalse(Date::getDateTime($relativeFormat));
-
- /*
- * Values based on relative / compound formats
- * http://php.net/manual/en/datetime.formats.compound.php
- */
- self::assertInstanceOf(DateTime::class, Date::getDateTime($relativeFormat, true));
- }
-
- /**
- * @param DateTime $dateTime Instance of DateTime class
- * @dataProvider provideDateTimeInstance
- */
- public function testGetDateTimeInstanceDateTime(DateTime $dateTime)
- {
- self::assertInstanceOf(DateTime::class, Date::getDateTime($dateTime));
- }
-
- public function testGetDateTimeConcreteDates()
- {
- /*
- * Using the standard date format provided by the tested method
- */
- self::assertInstanceOf(DateTime::class, Date::getDateTime('2015-03-20'));
-
- /*
- * Using custom date format
- */
- self::assertInstanceOf(DateTime::class, Date::getDateTime('2015-03-20 11:30', false, 'Y-m-d H:i'));
- self::assertInstanceOf(DateTime::class, Date::getDateTime('20.03.2015', false, 'd.m.Y'));
+ self::assertMatchesRegularExpression('/\d{2}:\d{2}:\d{2}/', Date::generateRandomTime());
}
/**
* @param mixed $value Empty value, e.g. ""
* @dataProvider provideEmptyValue
*/
- public function testIsValidDateEmptyDates($value)
- {
- self::assertFalse(Date::isValidDate($value));
- }
-
- /**
- * @param mixed $value Incorrect source of DateTime
- * @dataProvider provideIncorrectDateTimeValue
- */
- public function testIsValidDateIncorrectDates($value)
- {
- self::assertFalse(Date::isValidDate($value));
- }
-
- public function testIsValidDateValidDates()
- {
- self::assertTrue(Date::isValidDate('2017-01-01'));
- self::assertTrue(Date::isValidDate('2017-01-01 10:30', true));
- self::assertTrue(Date::isValidDate('2017-01-01 14:00', true));
-
- self::assertTrue(Date::isValidDate(new DateTime()));
- self::assertTrue(Date::isValidDate(new DateTime('now')));
- self::assertTrue(Date::isValidDate(new DateTime('tomorrow')));
- self::assertTrue(Date::isValidDate(new DateTime('m')));
- }
-
- /**
- * @param mixed $value Empty source of date format
- * @dataProvider provideEmptyValue
- */
- public function testIsValidDateFormatEmptyFormats($value)
- {
- self::assertFalse(Date::isValidDateFormat($value));
- }
-
- /**
- * @param mixed $format Invalid format of date
- * @dataProvider provideInvalidDateFormats
- */
- public function testIsValidDateFormatInvalidFormats($format)
- {
- self::assertFalse(Date::isValidDateFormat($format));
- }
-
- public function testIsValidDateFormatValidFormats()
- {
- self::assertTrue(Date::isValidDateFormat('Y'));
- self::assertTrue(Date::isValidDateFormat('yy'));
- self::assertTrue(Date::isValidDateFormat('M'));
- self::assertTrue(Date::isValidDateFormat('i'));
- self::assertTrue(Date::isValidDateFormat('l'));
- self::assertTrue(Date::isValidDateFormat('l, d F'));
- self::assertTrue(Date::isValidDateFormat('Y-m-d'));
- self::assertTrue(Date::isValidDateFormat('H:i:s'));
- self::assertTrue(Date::isValidDateFormat('Y/m/d H:i:s'));
- }
-
- /**
- * @param mixed $value Empty value, e.g. ""
- * @dataProvider provideEmptyValue
- */
- public function testGenerateRandomTimeEmptyFormat($value)
+ public function testGenerateRandomTimeEmptyFormat($value): void
{
self::assertNull(Date::generateRandomTime($value));
}
- public function testGenerateRandomTimeIncorrectFormat()
+ public function testGenerateRandomTimeIncorrectFormat(): void
{
self::assertNull(Date::generateRandomTime(','));
self::assertNull(Date::generateRandomTime(';'));
@@ -178,28 +406,19 @@ class DateTest extends BaseTestCase
self::assertNull(Date::generateRandomTime('?'));
}
- public function testGenerateRandomTimeDefaultFormat()
+ public function testGetCurrentDayOfWeek(): void
{
- self::assertRegExp('/\d{2}:\d{2}:\d{2}/', Date::generateRandomTime());
+ self::assertMatchesRegularExpression('/^[0-6]{1}$/', (string) Date::getCurrentDayOfWeek());
}
- public function testGenerateRandomTimeCustomFormat()
+ public function testGetCurrentDayOfWeekName(): void
{
- self::assertRegExp('/^0[1-9]{1}|1[0-2]{1}$/', Date::generateRandomTime('h')); // 01 through 12
- self::assertRegExp('/^[0-5]?[0-9]$/', Date::generateRandomTime('i')); // 00 through 59
- self::assertRegExp('/^[0-5]?[0-9]$/', Date::generateRandomTime('s')); // 00 through 59
+ // Required to avoid failure:
+ //
+ // Failed asserting that 'giovedì' matches PCRE pattern
+ // "/^Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday$/"
+ Locale::setLocale(LC_ALL, 'en', 'US');
- self::assertRegExp('/^\d{2}:\d{2}$/', Date::generateRandomTime('H:i'));
- self::assertRegExp('/^[1-9]|1[0-2]:\d{2}$/', Date::generateRandomTime('g:i'));
- }
-
- public function testGetCurrentDayOfWeek()
- {
- self::assertRegExp('/^[0-6]{1}$/', (string)Date::getCurrentDayOfWeek());
- }
-
- public function testGetCurrentDayOfWeekName()
- {
$days = [
'Monday',
'Tuesday',
@@ -212,247 +431,30 @@ class DateTest extends BaseTestCase
$pattern = sprintf('/^%s$/', implode('|', $days));
- self::assertRegExp($pattern, Date::getCurrentDayOfWeekName());
+ self::assertMatchesRegularExpression($pattern, Date::getCurrentDayOfWeekName());
}
/**
- * @param int $year The year value
- * @param int $month The month value
- * @param int $day The day value
- *
- * @dataProvider provideIncorrectYearMonthDay
- */
- public function testGetDayOfWeekIncorrectValues($year, $month, $day)
- {
- $this->setExpectedException(UnknownDatePartTypeException::class);
- self::assertEmpty(Date::getDayOfWeek($year, $month, $day));
- }
-
- /**
- * @param int $year The year value
- * @param int $month The month value
- * @param int $day The day value
- *
- * @dataProvider provideYearMonthDay
- */
- public function testGetDayOfWeek($year, $month, $day)
- {
- self::assertRegExp('/^[0-6]{1}$/', (string)Date::getDayOfWeek($year, $month, $day));
- }
-
- /**
- * @param string|DateTime $dateStart The start date
- * @param string|DateTime $dateEnd The end date
+ * @param DateTime|string $dateStart The start date
+ * @param DateTime|string $dateEnd The end date
*
* @dataProvider provideEmptyDatesForDateDifference
*/
- public function testGetDateDifferenceEmptyDates($dateStart, $dateEnd)
+ public function testGetDateDifferenceEmptyDates($dateStart, $dateEnd): void
{
self::assertNull(Date::getDateDifference($dateStart, $dateEnd));
}
- public function testGetDateDifferenceInvalidDates()
- {
- self::assertNull(Date::getDateDifference('2017-01-40', '2017-13-01'));
- self::assertNull(Date::getDateDifference('xyz', 'lorem'));
- }
-
- public function testGetDateDifferenceOneDay()
- {
- /*
- * Difference of 1 day
- */
- $dateStart = '2017-01-01';
- $dateEnd = '2017-01-02';
-
- $effect = [
- Date::DATE_DIFFERENCE_UNIT_YEARS => 0,
- Date::DATE_DIFFERENCE_UNIT_MONTHS => 0,
- Date::DATE_DIFFERENCE_UNIT_DAYS => 1,
- Date::DATE_DIFFERENCE_UNIT_HOURS => 0,
- Date::DATE_DIFFERENCE_UNIT_MINUTES => 0,
- ];
-
- self::assertEquals($effect, Date::getDateDifference($dateStart, $dateEnd));
- self::assertEquals($effect, Date::getDateDifference(new DateTime($dateStart), new DateTime($dateEnd)));
-
- self::assertEquals(0, Date::getDateDifference($dateStart, $dateEnd, Date::DATE_DIFFERENCE_UNIT_YEARS));
- self::assertEquals(0, Date::getDateDifference(new DateTime($dateStart), new DateTime($dateEnd), Date::DATE_DIFFERENCE_UNIT_YEARS));
-
- self::assertEquals(0, Date::getDateDifference($dateStart, $dateEnd, Date::DATE_DIFFERENCE_UNIT_MONTHS));
- self::assertEquals(0, Date::getDateDifference(new DateTime($dateStart), new DateTime($dateEnd), Date::DATE_DIFFERENCE_UNIT_MONTHS));
-
- self::assertEquals(1, Date::getDateDifference($dateStart, $dateEnd, Date::DATE_DIFFERENCE_UNIT_DAYS));
- self::assertEquals(1, Date::getDateDifference(new DateTime($dateStart), new DateTime($dateEnd), Date::DATE_DIFFERENCE_UNIT_DAYS));
-
- self::assertEquals(0, Date::getDateDifference($dateStart, $dateEnd, Date::DATE_DIFFERENCE_UNIT_HOURS));
- self::assertEquals(0, Date::getDateDifference(new DateTime($dateStart), new DateTime($dateEnd), Date::DATE_DIFFERENCE_UNIT_HOURS));
-
- self::assertEquals(0, Date::getDateDifference($dateStart, $dateEnd, Date::DATE_DIFFERENCE_UNIT_MINUTES));
- self::assertEquals(0, Date::getDateDifference(new DateTime($dateStart), new DateTime($dateEnd), Date::DATE_DIFFERENCE_UNIT_MINUTES));
-
- /*
- * Difference of 1 day (using the relative date format)
- */
- $effect = [
- Date::DATE_DIFFERENCE_UNIT_YEARS => 0,
- Date::DATE_DIFFERENCE_UNIT_MONTHS => 0,
- Date::DATE_DIFFERENCE_UNIT_DAYS => 1,
- Date::DATE_DIFFERENCE_UNIT_HOURS => 0,
- Date::DATE_DIFFERENCE_UNIT_MINUTES => 0,
- ];
-
- self::assertEquals($effect, Date::getDateDifference(new DateTime('yesterday'), new DateTime('midnight')));
- self::assertEquals(0, Date::getDateDifference(new DateTime('yesterday'), new DateTime('midnight'), Date::DATE_DIFFERENCE_UNIT_MONTHS));
- self::assertEquals(1, Date::getDateDifference(new DateTime('yesterday'), new DateTime('midnight'), Date::DATE_DIFFERENCE_UNIT_DAYS));
- self::assertEquals(0, Date::getDateDifference(new DateTime('yesterday'), new DateTime('midnight'), Date::DATE_DIFFERENCE_UNIT_HOURS));
- self::assertEquals(0, Date::getDateDifference(new DateTime('yesterday'), new DateTime('midnight'), Date::DATE_DIFFERENCE_UNIT_MINUTES));
- }
-
- public function testGetDateDifferenceOneDayTwoHours()
- {
- /*
- * Difference of 1 day, 2 hours and 15 minutes
- */
- $dateStart = '2017-01-01 12:00';
- $dateEnd = '2017-01-02 14:15';
-
- $effect = [
- Date::DATE_DIFFERENCE_UNIT_YEARS => 0,
- Date::DATE_DIFFERENCE_UNIT_MONTHS => 0,
- Date::DATE_DIFFERENCE_UNIT_DAYS => 1,
- Date::DATE_DIFFERENCE_UNIT_HOURS => 2,
- Date::DATE_DIFFERENCE_UNIT_MINUTES => 15,
- ];
-
- self::assertEquals($effect, Date::getDateDifference($dateStart, $dateEnd));
- self::assertEquals($effect, Date::getDateDifference(new DateTime($dateStart), new DateTime($dateEnd)));
-
- self::assertEquals(0, Date::getDateDifference($dateStart, $dateEnd, Date::DATE_DIFFERENCE_UNIT_YEARS));
- self::assertEquals(0, Date::getDateDifference(new DateTime($dateStart), new DateTime($dateEnd), Date::DATE_DIFFERENCE_UNIT_YEARS));
-
- self::assertEquals(0, Date::getDateDifference($dateStart, $dateEnd, Date::DATE_DIFFERENCE_UNIT_MONTHS));
- self::assertEquals(0, Date::getDateDifference(new DateTime($dateStart), new DateTime($dateEnd), Date::DATE_DIFFERENCE_UNIT_MONTHS));
-
- self::assertEquals(1, Date::getDateDifference($dateStart, $dateEnd, Date::DATE_DIFFERENCE_UNIT_DAYS));
- self::assertEquals(1, Date::getDateDifference(new DateTime($dateStart), new DateTime($dateEnd), Date::DATE_DIFFERENCE_UNIT_DAYS));
-
- self::assertEquals(2, Date::getDateDifference($dateStart, $dateEnd, Date::DATE_DIFFERENCE_UNIT_HOURS));
- self::assertEquals(2, Date::getDateDifference(new DateTime($dateStart), new DateTime($dateEnd), Date::DATE_DIFFERENCE_UNIT_HOURS));
-
- self::assertEquals(15, Date::getDateDifference($dateStart, $dateEnd, Date::DATE_DIFFERENCE_UNIT_MINUTES));
- self::assertEquals(15, Date::getDateDifference(new DateTime($dateStart), new DateTime($dateEnd), Date::DATE_DIFFERENCE_UNIT_MINUTES));
- }
-
- public function testGetDateDifferenceOneMonthFortyOneDays()
- {
- /*
- * Difference of 1 month, 41 days, 4 hours and 30 minutes
- */
- $dateStart = '2017-01-01 12:00';
- $dateEnd = '2017-02-11 16:30';
-
- $effect = [
- Date::DATE_DIFFERENCE_UNIT_YEARS => 0,
- Date::DATE_DIFFERENCE_UNIT_MONTHS => 1,
- Date::DATE_DIFFERENCE_UNIT_DAYS => 41,
- Date::DATE_DIFFERENCE_UNIT_HOURS => 4,
- Date::DATE_DIFFERENCE_UNIT_MINUTES => 30,
- ];
-
- self::assertEquals($effect, Date::getDateDifference($dateStart, $dateEnd));
- self::assertEquals($effect, Date::getDateDifference(new DateTime($dateStart), new DateTime($dateEnd)));
-
- self::assertEquals(0, Date::getDateDifference($dateStart, $dateEnd, Date::DATE_DIFFERENCE_UNIT_YEARS));
- self::assertEquals(0, Date::getDateDifference(new DateTime($dateStart), new DateTime($dateEnd), Date::DATE_DIFFERENCE_UNIT_YEARS));
-
- self::assertEquals(1, Date::getDateDifference($dateStart, $dateEnd, Date::DATE_DIFFERENCE_UNIT_MONTHS));
- self::assertEquals(1, Date::getDateDifference(new DateTime($dateStart), new DateTime($dateEnd), Date::DATE_DIFFERENCE_UNIT_MONTHS));
-
- self::assertEquals(41, Date::getDateDifference($dateStart, $dateEnd, Date::DATE_DIFFERENCE_UNIT_DAYS));
- self::assertEquals(41, Date::getDateDifference(new DateTime($dateStart), new DateTime($dateEnd), Date::DATE_DIFFERENCE_UNIT_DAYS));
-
- self::assertEquals(4, Date::getDateDifference($dateStart, $dateEnd, Date::DATE_DIFFERENCE_UNIT_HOURS));
- self::assertEquals(4, Date::getDateDifference(new DateTime($dateStart), new DateTime($dateEnd), Date::DATE_DIFFERENCE_UNIT_HOURS));
-
- self::assertEquals(30, Date::getDateDifference($dateStart, $dateEnd, Date::DATE_DIFFERENCE_UNIT_MINUTES));
- self::assertEquals(30, Date::getDateDifference(new DateTime($dateStart), new DateTime($dateEnd), Date::DATE_DIFFERENCE_UNIT_MINUTES));
- }
-
- public function testGetDateDifferenceNewYear()
- {
- $dateStart = '2017-12-31 23:59';
- $dateEnd = '2018-01-01 00:00';
-
- $effect = [
- Date::DATE_DIFFERENCE_UNIT_YEARS => 0,
- Date::DATE_DIFFERENCE_UNIT_MONTHS => 0,
- Date::DATE_DIFFERENCE_UNIT_DAYS => 0,
- Date::DATE_DIFFERENCE_UNIT_HOURS => 0,
- Date::DATE_DIFFERENCE_UNIT_MINUTES => 1,
- ];
-
- self::assertEquals($effect, Date::getDateDifference($dateStart, $dateEnd));
- self::assertEquals($effect, Date::getDateDifference(new DateTime($dateStart), new DateTime($dateEnd)));
-
- self::assertEquals(0, Date::getDateDifference($dateStart, $dateEnd, Date::DATE_DIFFERENCE_UNIT_YEARS));
- self::assertEquals(0, Date::getDateDifference(new DateTime($dateStart), new DateTime($dateEnd), Date::DATE_DIFFERENCE_UNIT_YEARS));
-
- self::assertEquals(0, Date::getDateDifference($dateStart, $dateEnd, Date::DATE_DIFFERENCE_UNIT_MONTHS));
- self::assertEquals(0, Date::getDateDifference(new DateTime($dateStart), new DateTime($dateEnd), Date::DATE_DIFFERENCE_UNIT_MONTHS));
-
- self::assertEquals(0, Date::getDateDifference($dateStart, $dateEnd, Date::DATE_DIFFERENCE_UNIT_DAYS));
- self::assertEquals(0, Date::getDateDifference(new DateTime($dateStart), new DateTime($dateEnd), Date::DATE_DIFFERENCE_UNIT_DAYS));
-
- self::assertEquals(0, Date::getDateDifference($dateStart, $dateEnd, Date::DATE_DIFFERENCE_UNIT_HOURS));
- self::assertEquals(0, Date::getDateDifference(new DateTime($dateStart), new DateTime($dateEnd), Date::DATE_DIFFERENCE_UNIT_HOURS));
-
- self::assertEquals(1, Date::getDateDifference($dateStart, $dateEnd, Date::DATE_DIFFERENCE_UNIT_MINUTES));
- self::assertEquals(1, Date::getDateDifference(new DateTime($dateStart), new DateTime($dateEnd), Date::DATE_DIFFERENCE_UNIT_MINUTES));
- }
-
- public function testGetDateDifferenceLessThan24Hours()
- {
- $dateStart = '2017-01-01 16:00';
- $dateEnd = '2017-01-02 10:00';
-
- $effect = [
- Date::DATE_DIFFERENCE_UNIT_YEARS => 0,
- Date::DATE_DIFFERENCE_UNIT_MONTHS => 0,
- Date::DATE_DIFFERENCE_UNIT_DAYS => 0,
- Date::DATE_DIFFERENCE_UNIT_HOURS => 18,
- Date::DATE_DIFFERENCE_UNIT_MINUTES => 0,
- ];
-
- self::assertEquals($effect, Date::getDateDifference($dateStart, $dateEnd));
- self::assertEquals($effect, Date::getDateDifference(new DateTime($dateStart), new DateTime($dateEnd)));
-
- self::assertEquals(0, Date::getDateDifference($dateStart, $dateEnd, Date::DATE_DIFFERENCE_UNIT_YEARS));
- self::assertEquals(0, Date::getDateDifference(new DateTime($dateStart), new DateTime($dateEnd), Date::DATE_DIFFERENCE_UNIT_YEARS));
-
- self::assertEquals(0, Date::getDateDifference($dateStart, $dateEnd, Date::DATE_DIFFERENCE_UNIT_MONTHS));
- self::assertEquals(0, Date::getDateDifference(new DateTime($dateStart), new DateTime($dateEnd), Date::DATE_DIFFERENCE_UNIT_MONTHS));
-
- self::assertEquals(0, Date::getDateDifference($dateStart, $dateEnd, Date::DATE_DIFFERENCE_UNIT_DAYS));
- self::assertEquals(0, Date::getDateDifference(new DateTime($dateStart), new DateTime($dateEnd), Date::DATE_DIFFERENCE_UNIT_DAYS));
-
- self::assertEquals(18, Date::getDateDifference($dateStart, $dateEnd, Date::DATE_DIFFERENCE_UNIT_HOURS));
- self::assertEquals(18, Date::getDateDifference(new DateTime($dateStart), new DateTime($dateEnd), Date::DATE_DIFFERENCE_UNIT_HOURS));
-
- self::assertEquals(0, Date::getDateDifference($dateStart, $dateEnd, Date::DATE_DIFFERENCE_UNIT_MINUTES));
- self::assertEquals(0, Date::getDateDifference(new DateTime($dateStart), new DateTime($dateEnd), Date::DATE_DIFFERENCE_UNIT_MINUTES));
- }
-
- public function testGetDateDifferenceEqual24Hours()
+ public function testGetDateDifferenceEqual24Hours(): void
{
$dateStart = '2017-01-01 00:00';
$dateEnd = '2017-01-02 00:00';
$effect = [
- Date::DATE_DIFFERENCE_UNIT_YEARS => 0,
- Date::DATE_DIFFERENCE_UNIT_MONTHS => 0,
- Date::DATE_DIFFERENCE_UNIT_DAYS => 1,
- Date::DATE_DIFFERENCE_UNIT_HOURS => 0,
+ Date::DATE_DIFFERENCE_UNIT_YEARS => 0,
+ Date::DATE_DIFFERENCE_UNIT_MONTHS => 0,
+ Date::DATE_DIFFERENCE_UNIT_DAYS => 1,
+ Date::DATE_DIFFERENCE_UNIT_HOURS => 0,
Date::DATE_DIFFERENCE_UNIT_MINUTES => 0,
];
@@ -475,16 +477,22 @@ class DateTest extends BaseTestCase
self::assertEquals(0, Date::getDateDifference(new DateTime($dateStart), new DateTime($dateEnd), Date::DATE_DIFFERENCE_UNIT_MINUTES));
}
- public function testGetDateDifferenceInvertedDates()
+ public function testGetDateDifferenceInvalidDates(): void
+ {
+ self::assertNull(Date::getDateDifference('2017-01-40', '2017-13-01'));
+ self::assertNull(Date::getDateDifference('xyz', 'lorem'));
+ }
+
+ public function testGetDateDifferenceInvertedDates(): void
{
$dateStart = '2017-01-02 10:00';
$dateEnd = '2017-01-01 16:00';
$effect = [
- Date::DATE_DIFFERENCE_UNIT_YEARS => 0,
- Date::DATE_DIFFERENCE_UNIT_MONTHS => 0,
- Date::DATE_DIFFERENCE_UNIT_DAYS => -1,
- Date::DATE_DIFFERENCE_UNIT_HOURS => 6,
+ Date::DATE_DIFFERENCE_UNIT_YEARS => 0,
+ Date::DATE_DIFFERENCE_UNIT_MONTHS => 0,
+ Date::DATE_DIFFERENCE_UNIT_DAYS => -1,
+ Date::DATE_DIFFERENCE_UNIT_HOURS => 6,
Date::DATE_DIFFERENCE_UNIT_MINUTES => 0,
];
@@ -507,19 +515,81 @@ class DateTest extends BaseTestCase
self::assertEquals(0, Date::getDateDifference(new DateTime($dateStart), new DateTime($dateEnd), Date::DATE_DIFFERENCE_UNIT_MINUTES));
}
- public function testGetDateDifferenceNoDifference()
+ public function testGetDateDifferenceLessThan24Hours(): void
{
- /*
- * No difference
- */
+ $dateStart = '2017-01-01 16:00';
+ $dateEnd = '2017-01-02 10:00';
+
+ $effect = [
+ Date::DATE_DIFFERENCE_UNIT_YEARS => 0,
+ Date::DATE_DIFFERENCE_UNIT_MONTHS => 0,
+ Date::DATE_DIFFERENCE_UNIT_DAYS => 0,
+ Date::DATE_DIFFERENCE_UNIT_HOURS => 18,
+ Date::DATE_DIFFERENCE_UNIT_MINUTES => 0,
+ ];
+
+ self::assertEquals($effect, Date::getDateDifference($dateStart, $dateEnd));
+ self::assertEquals($effect, Date::getDateDifference(new DateTime($dateStart), new DateTime($dateEnd)));
+
+ self::assertEquals(0, Date::getDateDifference($dateStart, $dateEnd, Date::DATE_DIFFERENCE_UNIT_YEARS));
+ self::assertEquals(0, Date::getDateDifference(new DateTime($dateStart), new DateTime($dateEnd), Date::DATE_DIFFERENCE_UNIT_YEARS));
+
+ self::assertEquals(0, Date::getDateDifference($dateStart, $dateEnd, Date::DATE_DIFFERENCE_UNIT_MONTHS));
+ self::assertEquals(0, Date::getDateDifference(new DateTime($dateStart), new DateTime($dateEnd), Date::DATE_DIFFERENCE_UNIT_MONTHS));
+
+ self::assertEquals(0, Date::getDateDifference($dateStart, $dateEnd, Date::DATE_DIFFERENCE_UNIT_DAYS));
+ self::assertEquals(0, Date::getDateDifference(new DateTime($dateStart), new DateTime($dateEnd), Date::DATE_DIFFERENCE_UNIT_DAYS));
+
+ self::assertEquals(18, Date::getDateDifference($dateStart, $dateEnd, Date::DATE_DIFFERENCE_UNIT_HOURS));
+ self::assertEquals(18, Date::getDateDifference(new DateTime($dateStart), new DateTime($dateEnd), Date::DATE_DIFFERENCE_UNIT_HOURS));
+
+ self::assertEquals(0, Date::getDateDifference($dateStart, $dateEnd, Date::DATE_DIFFERENCE_UNIT_MINUTES));
+ self::assertEquals(0, Date::getDateDifference(new DateTime($dateStart), new DateTime($dateEnd), Date::DATE_DIFFERENCE_UNIT_MINUTES));
+ }
+
+ public function testGetDateDifferenceNewYear(): void
+ {
+ $dateStart = '2017-12-31 23:59';
+ $dateEnd = '2018-01-01 00:00';
+
+ $effect = [
+ Date::DATE_DIFFERENCE_UNIT_YEARS => 0,
+ Date::DATE_DIFFERENCE_UNIT_MONTHS => 0,
+ Date::DATE_DIFFERENCE_UNIT_DAYS => 0,
+ Date::DATE_DIFFERENCE_UNIT_HOURS => 0,
+ Date::DATE_DIFFERENCE_UNIT_MINUTES => 1,
+ ];
+
+ self::assertEquals($effect, Date::getDateDifference($dateStart, $dateEnd));
+ self::assertEquals($effect, Date::getDateDifference(new DateTime($dateStart), new DateTime($dateEnd)));
+
+ self::assertEquals(0, Date::getDateDifference($dateStart, $dateEnd, Date::DATE_DIFFERENCE_UNIT_YEARS));
+ self::assertEquals(0, Date::getDateDifference(new DateTime($dateStart), new DateTime($dateEnd), Date::DATE_DIFFERENCE_UNIT_YEARS));
+
+ self::assertEquals(0, Date::getDateDifference($dateStart, $dateEnd, Date::DATE_DIFFERENCE_UNIT_MONTHS));
+ self::assertEquals(0, Date::getDateDifference(new DateTime($dateStart), new DateTime($dateEnd), Date::DATE_DIFFERENCE_UNIT_MONTHS));
+
+ self::assertEquals(0, Date::getDateDifference($dateStart, $dateEnd, Date::DATE_DIFFERENCE_UNIT_DAYS));
+ self::assertEquals(0, Date::getDateDifference(new DateTime($dateStart), new DateTime($dateEnd), Date::DATE_DIFFERENCE_UNIT_DAYS));
+
+ self::assertEquals(0, Date::getDateDifference($dateStart, $dateEnd, Date::DATE_DIFFERENCE_UNIT_HOURS));
+ self::assertEquals(0, Date::getDateDifference(new DateTime($dateStart), new DateTime($dateEnd), Date::DATE_DIFFERENCE_UNIT_HOURS));
+
+ self::assertEquals(1, Date::getDateDifference($dateStart, $dateEnd, Date::DATE_DIFFERENCE_UNIT_MINUTES));
+ self::assertEquals(1, Date::getDateDifference(new DateTime($dateStart), new DateTime($dateEnd), Date::DATE_DIFFERENCE_UNIT_MINUTES));
+ }
+
+ public function testGetDateDifferenceNoDifference(): void
+ {
+ // No difference
$dateStart = '2017-01-01 12:00';
$dateEnd = $dateStart;
$effect = [
- Date::DATE_DIFFERENCE_UNIT_YEARS => 0,
- Date::DATE_DIFFERENCE_UNIT_MONTHS => 0,
- Date::DATE_DIFFERENCE_UNIT_DAYS => 0,
- Date::DATE_DIFFERENCE_UNIT_HOURS => 0,
+ Date::DATE_DIFFERENCE_UNIT_YEARS => 0,
+ Date::DATE_DIFFERENCE_UNIT_MONTHS => 0,
+ Date::DATE_DIFFERENCE_UNIT_DAYS => 0,
+ Date::DATE_DIFFERENCE_UNIT_HOURS => 0,
Date::DATE_DIFFERENCE_UNIT_MINUTES => 0,
];
@@ -542,41 +612,197 @@ class DateTest extends BaseTestCase
self::assertEquals(0, Date::getDateDifference(new DateTime(), new DateTime(), Date::DATE_DIFFERENCE_UNIT_MINUTES));
}
- /**
- * @param mixed $invalidCount Empty value, e.g. ""
- * @dataProvider provideEmptyValue
- */
- public function testGetDatesCollectionInvalidCount($invalidCount)
+ public function testGetDateDifferenceOneDay(): void
{
- self::assertEquals([], Date::getDatesCollection(new DateTime(), $invalidCount));
- self::assertEquals([], Date::getDatesCollection(new DateTime(), -1));
+ // Difference of 1 day
+ $dateStart = '2017-01-01';
+ $dateEnd = '2017-01-02';
+
+ $effect = [
+ Date::DATE_DIFFERENCE_UNIT_YEARS => 0,
+ Date::DATE_DIFFERENCE_UNIT_MONTHS => 0,
+ Date::DATE_DIFFERENCE_UNIT_DAYS => 1,
+ Date::DATE_DIFFERENCE_UNIT_HOURS => 0,
+ Date::DATE_DIFFERENCE_UNIT_MINUTES => 0,
+ ];
+
+ self::assertEquals($effect, Date::getDateDifference($dateStart, $dateEnd));
+ self::assertEquals($effect, Date::getDateDifference(new DateTime($dateStart), new DateTime($dateEnd)));
+
+ self::assertEquals(0, Date::getDateDifference($dateStart, $dateEnd, Date::DATE_DIFFERENCE_UNIT_YEARS));
+ self::assertEquals(0, Date::getDateDifference(new DateTime($dateStart), new DateTime($dateEnd), Date::DATE_DIFFERENCE_UNIT_YEARS));
+
+ self::assertEquals(0, Date::getDateDifference($dateStart, $dateEnd, Date::DATE_DIFFERENCE_UNIT_MONTHS));
+ self::assertEquals(0, Date::getDateDifference(new DateTime($dateStart), new DateTime($dateEnd), Date::DATE_DIFFERENCE_UNIT_MONTHS));
+
+ self::assertEquals(1, Date::getDateDifference($dateStart, $dateEnd, Date::DATE_DIFFERENCE_UNIT_DAYS));
+ self::assertEquals(1, Date::getDateDifference(new DateTime($dateStart), new DateTime($dateEnd), Date::DATE_DIFFERENCE_UNIT_DAYS));
+
+ self::assertEquals(0, Date::getDateDifference($dateStart, $dateEnd, Date::DATE_DIFFERENCE_UNIT_HOURS));
+ self::assertEquals(0, Date::getDateDifference(new DateTime($dateStart), new DateTime($dateEnd), Date::DATE_DIFFERENCE_UNIT_HOURS));
+
+ self::assertEquals(0, Date::getDateDifference($dateStart, $dateEnd, Date::DATE_DIFFERENCE_UNIT_MINUTES));
+ self::assertEquals(0, Date::getDateDifference(new DateTime($dateStart), new DateTime($dateEnd), Date::DATE_DIFFERENCE_UNIT_MINUTES));
+
+ // Difference of 1 day (using the relative date format)
+ $effect = [
+ Date::DATE_DIFFERENCE_UNIT_YEARS => 0,
+ Date::DATE_DIFFERENCE_UNIT_MONTHS => 0,
+ Date::DATE_DIFFERENCE_UNIT_DAYS => 1,
+ Date::DATE_DIFFERENCE_UNIT_HOURS => 0,
+ Date::DATE_DIFFERENCE_UNIT_MINUTES => 0,
+ ];
+
+ self::assertEquals($effect, Date::getDateDifference(new DateTime('yesterday'), new DateTime('midnight')));
+ self::assertEquals(0, Date::getDateDifference(new DateTime('yesterday'), new DateTime('midnight'), Date::DATE_DIFFERENCE_UNIT_MONTHS));
+ self::assertEquals(1, Date::getDateDifference(new DateTime('yesterday'), new DateTime('midnight'), Date::DATE_DIFFERENCE_UNIT_DAYS));
+ self::assertEquals(0, Date::getDateDifference(new DateTime('yesterday'), new DateTime('midnight'), Date::DATE_DIFFERENCE_UNIT_HOURS));
+ self::assertEquals(0, Date::getDateDifference(new DateTime('yesterday'), new DateTime('midnight'), Date::DATE_DIFFERENCE_UNIT_MINUTES));
+ }
+
+ public function testGetDateDifferenceOneDayTwoHours(): void
+ {
+ // Difference of 1 day, 2 hours and 15 minutes
+ $dateStart = '2017-01-01 12:00';
+ $dateEnd = '2017-01-02 14:15';
+
+ $effect = [
+ Date::DATE_DIFFERENCE_UNIT_YEARS => 0,
+ Date::DATE_DIFFERENCE_UNIT_MONTHS => 0,
+ Date::DATE_DIFFERENCE_UNIT_DAYS => 1,
+ Date::DATE_DIFFERENCE_UNIT_HOURS => 2,
+ Date::DATE_DIFFERENCE_UNIT_MINUTES => 15,
+ ];
+
+ self::assertEquals($effect, Date::getDateDifference($dateStart, $dateEnd));
+ self::assertEquals($effect, Date::getDateDifference(new DateTime($dateStart), new DateTime($dateEnd)));
+
+ self::assertEquals(0, Date::getDateDifference($dateStart, $dateEnd, Date::DATE_DIFFERENCE_UNIT_YEARS));
+ self::assertEquals(0, Date::getDateDifference(new DateTime($dateStart), new DateTime($dateEnd), Date::DATE_DIFFERENCE_UNIT_YEARS));
+
+ self::assertEquals(0, Date::getDateDifference($dateStart, $dateEnd, Date::DATE_DIFFERENCE_UNIT_MONTHS));
+ self::assertEquals(0, Date::getDateDifference(new DateTime($dateStart), new DateTime($dateEnd), Date::DATE_DIFFERENCE_UNIT_MONTHS));
+
+ self::assertEquals(1, Date::getDateDifference($dateStart, $dateEnd, Date::DATE_DIFFERENCE_UNIT_DAYS));
+ self::assertEquals(1, Date::getDateDifference(new DateTime($dateStart), new DateTime($dateEnd), Date::DATE_DIFFERENCE_UNIT_DAYS));
+
+ self::assertEquals(2, Date::getDateDifference($dateStart, $dateEnd, Date::DATE_DIFFERENCE_UNIT_HOURS));
+ self::assertEquals(2, Date::getDateDifference(new DateTime($dateStart), new DateTime($dateEnd), Date::DATE_DIFFERENCE_UNIT_HOURS));
+
+ self::assertEquals(15, Date::getDateDifference($dateStart, $dateEnd, Date::DATE_DIFFERENCE_UNIT_MINUTES));
+ self::assertEquals(15, Date::getDateDifference(new DateTime($dateStart), new DateTime($dateEnd), Date::DATE_DIFFERENCE_UNIT_MINUTES));
+ }
+
+ public function testGetDateDifferenceOneMonthFortyOneDays(): void
+ {
+ // Difference of 1 month, 41 days, 4 hours and 30 minutes
+ $dateStart = '2017-01-01 12:00';
+ $dateEnd = '2017-02-11 16:30';
+
+ $effect = [
+ Date::DATE_DIFFERENCE_UNIT_YEARS => 0,
+ Date::DATE_DIFFERENCE_UNIT_MONTHS => 1,
+ Date::DATE_DIFFERENCE_UNIT_DAYS => 41,
+ Date::DATE_DIFFERENCE_UNIT_HOURS => 4,
+ Date::DATE_DIFFERENCE_UNIT_MINUTES => 30,
+ ];
+
+ self::assertEquals($effect, Date::getDateDifference($dateStart, $dateEnd));
+ self::assertEquals($effect, Date::getDateDifference(new DateTime($dateStart), new DateTime($dateEnd)));
+
+ self::assertEquals(0, Date::getDateDifference($dateStart, $dateEnd, Date::DATE_DIFFERENCE_UNIT_YEARS));
+ self::assertEquals(0, Date::getDateDifference(new DateTime($dateStart), new DateTime($dateEnd), Date::DATE_DIFFERENCE_UNIT_YEARS));
+
+ self::assertEquals(1, Date::getDateDifference($dateStart, $dateEnd, Date::DATE_DIFFERENCE_UNIT_MONTHS));
+ self::assertEquals(1, Date::getDateDifference(new DateTime($dateStart), new DateTime($dateEnd), Date::DATE_DIFFERENCE_UNIT_MONTHS));
+
+ self::assertEquals(41, Date::getDateDifference($dateStart, $dateEnd, Date::DATE_DIFFERENCE_UNIT_DAYS));
+ self::assertEquals(41, Date::getDateDifference(new DateTime($dateStart), new DateTime($dateEnd), Date::DATE_DIFFERENCE_UNIT_DAYS));
+
+ self::assertEquals(4, Date::getDateDifference($dateStart, $dateEnd, Date::DATE_DIFFERENCE_UNIT_HOURS));
+ self::assertEquals(4, Date::getDateDifference(new DateTime($dateStart), new DateTime($dateEnd), Date::DATE_DIFFERENCE_UNIT_HOURS));
+
+ self::assertEquals(30, Date::getDateDifference($dateStart, $dateEnd, Date::DATE_DIFFERENCE_UNIT_MINUTES));
+ self::assertEquals(30, Date::getDateDifference(new DateTime($dateStart), new DateTime($dateEnd), Date::DATE_DIFFERENCE_UNIT_MINUTES));
}
/**
- * @param mixed $invalidInterval Empty value, e.g. ""
- * @dataProvider provideEmptyValue
+ * @param bool $value The value which maybe is a date
+ * @dataProvider provideBooleanValue
*/
- public function testGetDatesCollectionInvalidInterval($invalidInterval)
+ public function testGetDateTimeBoolean($value): void
{
- self::assertEquals([], Date::getDatesCollection(new DateTime(), 2, $invalidInterval));
- self::assertEquals([], Date::getDatesCollection(new DateTime(), 2, 'lorem'));
- self::assertEquals([], Date::getDatesCollection(new DateTime(), 2, '%d'));
+ self::assertFalse(Date::getDateTime($value));
}
- public function testGetDatesCollection()
+ public function testGetDateTimeConcreteDates(): void
+ {
+ // Using the standard date format provided by the tested method
+ self::assertInstanceOf(DateTime::class, Date::getDateTime('2015-03-20'));
+
+ // Using custom date format
+ self::assertInstanceOf(DateTime::class, Date::getDateTime('2015-03-20 11:30', false, 'Y-m-d H:i'));
+ self::assertInstanceOf(DateTime::class, Date::getDateTime('20.03.2015', false, 'd.m.Y'));
+ }
+
+ /**
+ * @param mixed $value Empty value, e.g. ""
+ * @dataProvider provideEmptyValue
+ */
+ public function testGetDateTimeEmptyValue($value): void
+ {
+ self::assertFalse(Date::getDateTime($value));
+ }
+
+ /**
+ * @param mixed $value Incorrect source of DateTime
+ * @dataProvider provideIncorrectDateTimeValue
+ */
+ public function testGetDateTimeIncorrectValue($value): void
+ {
+ self::assertFalse(Date::getDateTime($value));
+ }
+
+ /**
+ * @param DateTime $dateTime Instance of DateTime class
+ * @dataProvider provideDateTimeInstance
+ */
+ public function testGetDateTimeInstanceDateTime(DateTime $dateTime): void
+ {
+ self::assertInstanceOf(DateTime::class, Date::getDateTime($dateTime));
+ }
+
+ /**
+ * @param string $relativeFormat Relative / compound format of DateTime
+ * @dataProvider provideDateTimeRelativeFormat
+ */
+ public function testGetDateTimeRelativeFormats($relativeFormat): void
{
/*
- * 1 date only
+ * Values based on relative / compound formats, but... without explicitly declaring them as compound
+ * (2nd argument set to false by default)
+ *
+ * http://php.net/manual/en/datetime.formats.compound.php
*/
+ self::assertFalse(Date::getDateTime($relativeFormat));
+
+ /*
+ * Values based on relative / compound formats
+ * http://php.net/manual/en/datetime.formats.compound.php
+ */
+ self::assertInstanceOf(DateTime::class, Date::getDateTime($relativeFormat, true));
+ }
+
+ public function testGetDatesCollection(): void
+ {
+ // 1 date only
$effect = [
1 => new DateTime('2017-01-02'),
];
self::assertEquals($effect, Date::getDatesCollection(new DateTime('2017-01-01'), 1));
- /*
- * 3 dates with default date interval (days)
- */
+ // 3 dates with default date interval (days)
$effect = [
1 => new DateTime('2017-01-02'),
2 => new DateTime('2017-01-03'),
@@ -585,9 +811,7 @@ class DateTest extends BaseTestCase
self::assertEquals($effect, Date::getDatesCollection(new DateTime('2017-01-01'), 3));
- /*
- * 3 dates with custom date interval (hours)
- */
+ // 3 dates with custom date interval (hours)
$effect = [
1 => new DateTime('2017-01-01 10:30'),
2 => new DateTime('2017-01-01 11:30'),
@@ -596,9 +820,7 @@ class DateTest extends BaseTestCase
self::assertEquals($effect, Date::getDatesCollection(new DateTime('2017-01-01 09:30'), 3, 'PT%dH'));
- /*
- * 3 dates with custom date interval (months)
- */
+ // 3 dates with custom date interval (months)
$effect = [
1 => new DateTime('2017-02-01'),
2 => new DateTime('2017-03-01'),
@@ -608,7 +830,116 @@ class DateTest extends BaseTestCase
self::assertEquals($effect, Date::getDatesCollection(new DateTime('2017-01-01'), 3, 'P%dM'));
}
- public function testGetRandomDateUsingDefaults()
+ /**
+ * @param mixed $invalidCount Empty value, e.g. ""
+ * @dataProvider provideEmptyValue
+ */
+ public function testGetDatesCollectionInvalidCount($invalidCount): void
+ {
+ self::assertEquals([], Date::getDatesCollection(new DateTime(), $invalidCount));
+ self::assertEquals([], Date::getDatesCollection(new DateTime(), -1));
+ }
+
+ /**
+ * @param mixed $invalidInterval Empty value, e.g. ""
+ * @dataProvider provideEmptyValue
+ */
+ public function testGetDatesCollectionInvalidInterval($invalidInterval): void
+ {
+ self::assertEquals([], Date::getDatesCollection(new DateTime(), 2, $invalidInterval));
+ self::assertEquals([], Date::getDatesCollection(new DateTime(), 2, 'lorem'));
+ self::assertEquals([], Date::getDatesCollection(new DateTime(), 2, '%d'));
+ }
+
+ /**
+ * @param int $period The period, type of period. One of DatePeriod class constants, e.g.
+ * DatePeriod::LAST_WEEK.
+ * @param DatePeriod $expected Expected start and end date for given period
+ *
+ * @dataProvider provideCorrectPeriod
+ */
+ public function testGetDatesForPeriod($period, DatePeriod $expected): void
+ {
+ self::assertEquals($expected, Date::getDatesForPeriod($period));
+ }
+
+ public function testGetDatesForPeriodUsingEmptyString(): void
+ {
+ self::assertNull(Date::getDatesForPeriod(''));
+ }
+
+ /**
+ * @param int $period Incorrect period to verify
+ * @dataProvider provideIncorrectPeriod
+ */
+ public function testGetDatesForPeriodUsingIncorrectPeriod($period): void
+ {
+ self::assertNull(Date::getDatesForPeriod($period));
+ }
+
+ /**
+ * @param int $year The year value
+ * @param int $month The month value
+ * @param int $day The day value
+ *
+ * @dataProvider provideYearMonthDay
+ */
+ public function testGetDayOfWeek(int $year, int $month, int $day): void
+ {
+ self::assertMatchesRegularExpression('/^[0-6]{1}$/', (string) Date::getDayOfWeek($year, $month, $day));
+ }
+
+ /**
+ * @param int $year The year value
+ * @param int $month The month value
+ * @param int $day The day value
+ *
+ * @dataProvider provideIncorrectYearMonthDay
+ */
+ public function testGetDayOfWeekIncorrectValues(int $year, int $month, int $day): void
+ {
+ $this->expectException(UnknownDatePartTypeException::class);
+ self::assertEmpty(Date::getDayOfWeek($year, $month, $day));
+ }
+
+ /**
+ * @param DateTime $startDate The start date. Start of the random date.
+ * @param int $start Start of random partition
+ * @param int $end End of random partition
+ *
+ * @dataProvider provideDataOfRandomDate
+ */
+ public function testGetRandomDate(DateTime $startDate, $start, $end): void
+ {
+ $randomDate = Date::getRandomDate($startDate, $start, $end);
+
+ $minDate = clone $startDate;
+ $maxDate = clone $startDate;
+
+ $intervalMinDate = $minDate->add(new DateInterval(sprintf('P%dD', $start)));
+ $intervalMaxDate = $maxDate->add(new DateInterval(sprintf('P%dD', $end)));
+
+ self::assertTrue($randomDate >= $intervalMinDate && $randomDate <= $intervalMaxDate);
+ }
+
+ /**
+ * @param DateTime $startDate The start date. Start of the random date.
+ * @param int $start Start of random partition
+ * @param int $end End of random partition
+ *
+ * @dataProvider provideDataOfRandomDateIncorrectEnd
+ */
+ public function testGetRandomDateIncorrectEnd(DateTime $startDate, $start, $end): void
+ {
+ $randomDate = Date::getRandomDate($startDate, $start, $end);
+
+ $cloned = clone $startDate;
+ $intervalDate = $cloned->add(new DateInterval(sprintf('P%dD', $start)));
+
+ self::assertTrue($randomDate >= $intervalDate && $randomDate <= $intervalDate);
+ }
+
+ public function testGetRandomDateUsingDefaults(): void
{
$startDate = new DateTime();
$start = 1;
@@ -625,432 +956,63 @@ class DateTest extends BaseTestCase
}
/**
- * @param DateTime $startDate The start date. Start of the random date.
- * @param int $start Start of random partition
- * @param int $end End of random partition
- *
- * @dataProvider provideDataOfRandomDateIncorrectEnd
- */
- public function testGetRandomDateIncorrectEnd(DateTime $startDate, $start, $end)
- {
- $randomDate = Date::getRandomDate($startDate, $start, $end);
-
- $cloned = clone $startDate;
- $intervalDate = $cloned->add(new DateInterval(sprintf('P%dD', $start)));
-
- self::assertTrue($randomDate >= $intervalDate && $randomDate <= $intervalDate);
- }
-
- /**
- * @param DateTime $startDate The start date. Start of the random date.
- * @param int $start Start of random partition
- * @param int $end End of random partition
- *
- * @dataProvider provideDataOfRandomDate
- */
- public function testGetRandomDate(DateTime $startDate, $start, $end)
- {
- $randomDate = Date::getRandomDate($startDate, $start, $end);
-
- $minDate = clone $startDate;
- $maxDate = clone $startDate;
-
- $intervalMinDate = $minDate->add(new DateInterval(sprintf('P%dD', $start)));
- $intervalMaxDate = $maxDate->add(new DateInterval(sprintf('P%dD', $end)));
-
- self::assertTrue($randomDate >= $intervalMinDate && $randomDate <= $intervalMaxDate);
- }
-
- /**
- * @param mixed $period Empty value, e.g. ""
+ * @param mixed $value Empty value, e.g. ""
* @dataProvider provideEmptyValue
*/
- public function testGetDatesForPeriodUsingEmptyPeriod($period)
+ public function testIsValidDateEmptyDates($value): void
{
- self::assertNull(Date::getDatesForPeriod($period));
+ self::assertFalse(Date::isValidDate($value));
}
/**
- * @param int $period Incorrect period to verify
- * @dataProvider provideIncorrectPeriod
+ * @param mixed $value Empty source of date format
+ * @dataProvider provideEmptyValue
*/
- public function testGetDatesForPeriodUsingIncorrectPeriod($period)
+ public function testIsValidDateFormatEmptyFormats($value): void
{
- self::assertNull(Date::getDatesForPeriod($period));
+ self::assertFalse(Date::isValidDateFormat($value));
}
/**
- * @param int $period The period, type of period. One of DatePeriod class constants, e.g.
- * DatePeriod::LAST_WEEK.
- * @param DatePeriod $expected Expected start and end date for given period
- *
- * @dataProvider provideCorrectPeriod
+ * @param mixed $format Invalid format of date
+ * @dataProvider provideInvalidDateFormats
*/
- public function testGetDatesForPeriod($period, DatePeriod $expected)
+ public function testIsValidDateFormatInvalidFormats($format): void
{
- self::assertEquals($expected, Date::getDatesForPeriod($period));
+ self::assertFalse(Date::isValidDateFormat($format));
+ }
+
+ public function testIsValidDateFormatValidFormats(): void
+ {
+ self::assertTrue(Date::isValidDateFormat('Y'));
+ self::assertTrue(Date::isValidDateFormat('yy'));
+ self::assertTrue(Date::isValidDateFormat('M'));
+ self::assertTrue(Date::isValidDateFormat('i'));
+ self::assertTrue(Date::isValidDateFormat('l'));
+ self::assertTrue(Date::isValidDateFormat('l, d F'));
+ self::assertTrue(Date::isValidDateFormat('Y-m-d'));
+ self::assertTrue(Date::isValidDateFormat('H:i:s'));
+ self::assertTrue(Date::isValidDateFormat('Y/m/d H:i:s'));
}
/**
- * Provides incorrect invalidCount of DateTime
- *
- * @return Generator
+ * @param mixed $value Incorrect source of DateTime
+ * @dataProvider provideIncorrectDateTimeValue
*/
- public function provideIncorrectDateTimeValue()
+ public function testIsValidDateIncorrectDates($value): void
{
- /*
- * Incorrect one-character values
- */
- yield['a'];
- yield['m'];
-
- /*
- * Incorrect strings
- */
- yield['ss'];
- yield['sss'];
- yield['mm'];
- yield['yy'];
- yield['yyyy'];
-
- /*
- * Incorrect integer values
- */
- yield[1];
- yield[10];
- yield[15];
- yield[100];
- yield[1000];
-
- /*
- * Incorrect string / numeric values
- */
- yield['1'];
- yield['10'];
- yield['15'];
- yield['100'];
- yield['1000'];
-
- /*
- * Incorrect dates
- */
- yield['0-0-0'];
- yield['20-01-01'];
- yield['2015-0-0'];
- yield['2015-00-00'];
- yield['2015-16-01'];
+ self::assertFalse(Date::isValidDate($value));
}
- /**
- * Provides invalid format of date
- *
- * @return Generator
- */
- public function provideInvalidDateFormats()
+ public function testIsValidDateValidDates(): void
{
- yield[0];
- yield[9];
- yield['[]'];
- yield['invalid'];
- yield['Q'];
- yield[','];
- yield['.'];
- yield['aa###'];
- yield['Y/m/d H:i:invalid'];
- }
+ self::assertTrue(Date::isValidDate('2017-01-01'));
+ self::assertTrue(Date::isValidDate('2017-01-01 10:30', true));
+ self::assertTrue(Date::isValidDate('2017-01-01 14:00', true));
- /**
- * Provide empty dates for date difference
- *
- * @return Generator
- */
- public function provideEmptyDatesForDateDifference()
- {
- yield[
- null,
- null,
- ];
-
- yield[
- '',
- '',
- ];
-
- yield[
- null,
- new DateTime(),
- ];
-
- yield[
- new DateTime(),
- null,
- ];
- }
-
- /**
- * Provides incorrect values of year, month and day
- *
- * @return Generator
- */
- public function provideIncorrectYearMonthDay()
- {
- yield[
- null,
- null,
- null,
- ];
-
- yield[
- '',
- '',
- '',
- ];
-
- yield[
- 0,
- 0,
- 0,
- ];
-
- yield[
- -1,
- -1,
- -1,
- ];
-
- yield[
- 5000,
- 50,
- 50,
- ];
-
- yield[
- 2000,
- 13,
- 01,
- ];
-
- yield[
- 2000,
- 01,
- 40,
- ];
- }
-
- /**
- * Provides values of year, month and day
- *
- * @return Generator
- */
- public function provideYearMonthDay()
- {
- yield[
- 2000,
- 01,
- 01,
- ];
-
- yield[
- 2000,
- 1,
- 1,
- ];
-
- yield[
- 2000,
- 2,
- 2,
- ];
-
- yield[
- 2000,
- 6,
- 1,
- ];
-
- yield[
- 2000,
- 12,
- 01,
- ];
-
- yield[
- 2000,
- 12,
- 1,
- ];
-
- yield[
- 2000,
- 12,
- 31,
- ];
- }
-
- /**
- * Provides data for the random date with incorrect end of random partition
- *
- * @return Generator
- */
- public function provideDataOfRandomDateIncorrectEnd()
- {
- yield[
- new DateTime('2000-01-01'),
- 100,
- 1,
- ];
- }
-
- /**
- * Provides data for the random date
- *
- * @return Generator
- */
- public function provideDataOfRandomDate()
- {
- yield[
- new DateTime('2000-01-01'),
- 1,
- 100,
- ];
-
- yield[
- new DateTime('2000-12-01'),
- 1,
- 100,
- ];
- yield[
- new DateTime('2000-01-01'),
- '1',
- '100',
- ];
-
- yield[
- new DateTime('2000-12-01'),
- '1',
- '100',
- ];
-
- yield[
- new DateTime('2000-01-01'),
- 10,
- 50,
- ];
-
- yield[
- new DateTime('2000-12-01'),
- 10,
- 50,
- ];
- }
-
- /**
- * Provides incorrect period
- *
- * @return Generator
- */
- public function provideIncorrectPeriod()
- {
- yield[-1];
- yield[0];
- yield[10];
- }
-
- /**
- * Provides correct period
- *
- * @return Generator
- */
- public function provideCorrectPeriod()
- {
- yield[
- DatePeriod::LAST_WEEK,
- new DatePeriod(
- (new DateTime('this week'))->sub(new DateInterval('P7D'))->setTime(0, 0, 0),
- (new DateTime('this week'))->sub(new DateInterval('P1D'))->setTime(23, 59, 59)
- ),
- ];
-
- yield[
- DatePeriod::THIS_WEEK,
- new DatePeriod(
- (new DateTime('this week'))->setTime(0, 0, 0),
- (new DateTime('this week'))->add(new DateInterval('P6D'))->setTime(23, 59, 59)
- ),
- ];
-
- yield[
- DatePeriod::NEXT_WEEK,
- new DatePeriod(
- (new DateTime('this week'))->add(new DateInterval('P7D'))->setTime(0, 0, 0),
- (new DateTime('this week'))->add(new DateInterval('P7D'))
- ->add(new DateInterval('P6D'))
- ->setTime(23, 59, 59)
- ),
- ];
-
- yield[
- DatePeriod::LAST_MONTH,
- new DatePeriod(
- (new DateTime('first day of last month'))->setTime(0, 0, 0),
- (new DateTime('last day of last month'))->setTime(23, 59, 59)
- ),
- ];
-
- yield[
- DatePeriod::THIS_MONTH,
- new DatePeriod(
- Date::getDatesForPeriod(DatePeriod::LAST_MONTH)
- ->getEndDate()
- ->add(new DateInterval('P1D'))
- ->setTime(0, 0, 0),
- Date::getDatesForPeriod(DatePeriod::NEXT_MONTH)
- ->getStartDate()
- ->sub(new DateInterval('P1D'))
- ->setTime(23, 59, 59)
- ),
- ];
-
- yield[
- DatePeriod::NEXT_MONTH,
- new DatePeriod(
- (new DateTime('first day of next month'))->setTime(0, 0, 0),
- (new DateTime('last day of next month'))->setTime(23, 59, 59)
- ),
- ];
-
- $lastYearStart = (new DateTime())->modify('-1 year');
- $lastYearEnd = (new DateTime())->modify('-1 year');
- $year = $lastYearStart->format('Y');
-
- yield[
- DatePeriod::LAST_YEAR,
- new DatePeriod(
- $lastYearStart->setDate($year, 1, 1)->setTime(0, 0, 0),
- $lastYearEnd->setDate($year, 12, 31)->setTime(23, 59, 59)
- ),
- ];
-
- $year = (new DateTime())->format('Y');
-
- yield[
- DatePeriod::THIS_YEAR,
- new DatePeriod(
- (new DateTime())->setDate($year, 1, 1)->setTime(0, 0, 0),
- (new DateTime())->setDate($year, 12, 31)->setTime(23, 59, 59)
- ),
- ];
-
- $nextYearStart = (new DateTime())->modify('1 year');
- $nextYearEnd = (new DateTime())->modify('1 year');
- $year = $nextYearStart->format('Y');
-
- yield[
- DatePeriod::NEXT_YEAR,
- new DatePeriod(
- $nextYearStart->setDate($year, 1, 1)->setTime(0, 0, 0),
- $nextYearEnd->setDate($year, 12, 31)->setTime(23, 59, 59)
- ),
- ];
+ self::assertTrue(Date::isValidDate(new DateTime()));
+ self::assertTrue(Date::isValidDate(new DateTime('now')));
+ self::assertTrue(Date::isValidDate(new DateTime('tomorrow')));
+ self::assertTrue(Date::isValidDate(new DateTime('m')));
}
}
diff --git a/tests/Utilities/GeneratorUtilityTest.php b/tests/Utilities/GeneratorUtilityTest.php
index 7642c87..18eb8a0 100644
--- a/tests/Utilities/GeneratorUtilityTest.php
+++ b/tests/Utilities/GeneratorUtilityTest.php
@@ -16,6 +16,9 @@ use Meritoo\Common\Utilities\GeneratorUtility;
*
* @author Meritoo
* @copyright Meritoo
+ *
+ * @internal
+ * @covers \Meritoo\Common\Utilities\GeneratorUtility
*/
class GeneratorUtilityTest extends BaseTestCase
{
@@ -26,9 +29,7 @@ class GeneratorUtilityTest extends BaseTestCase
public function testGetGeneratorElements()
{
- /*
- * Generator that provides boolean value
- */
+ // Generator that provides boolean value
$elements = [
[false],
[true],
@@ -46,15 +47,11 @@ class GeneratorUtilityTest extends BaseTestCase
[[]],
];
- /*
- * Generator that provides an empty value
- */
+ // Generator that provides an empty value
$generator = $this->provideEmptyValue();
self::assertEquals($elements, GeneratorUtility::getGeneratorElements($generator));
- /*
- * Generator that provides instance of DateTime class
- */
+ // Generator that provides instance of DateTime class
$generator = $this->provideDateTimeInstance();
self::assertCount(4, GeneratorUtility::getGeneratorElements($generator));
}
diff --git a/tests/Utilities/LocaleTest.php b/tests/Utilities/LocaleTest.php
index 6a2c9ea..0f0d16e 100644
--- a/tests/Utilities/LocaleTest.php
+++ b/tests/Utilities/LocaleTest.php
@@ -18,9 +18,140 @@ use ReflectionException;
*
* @author Meritoo
* @copyright Meritoo
+ *
+ * @internal
+ * @covers \Meritoo\Common\Utilities\Locale
*/
class LocaleTest extends BaseTestCase
{
+ /**
+ * Provides category
+ *
+ * @return Generator
+ */
+ public function provideCategoryLanguageCodeAndExpectedLocale()
+ {
+ yield [
+ LC_ALL,
+ 'fr',
+ '',
+ 'fr_FR.UTF-8',
+ ];
+
+ yield [
+ LC_COLLATE,
+ 'fr',
+ 'FR',
+ 'fr_FR.UTF-8',
+ ];
+
+ yield [
+ LC_CTYPE,
+ 'en',
+ 'US',
+ 'en_US.UTF-8',
+ ];
+
+ yield [
+ LC_NUMERIC,
+ 'en',
+ 'GB',
+ 'en_GB.UTF-8',
+ ];
+
+ yield [
+ LC_MONETARY,
+ 'es',
+ '',
+ 'es_ES.UTF-8',
+ ];
+
+ yield [
+ LC_MONETARY,
+ 'es',
+ 'ES',
+ 'es_ES.UTF-8',
+ ];
+
+ yield [
+ LC_TIME,
+ 'it',
+ '',
+ 'it_IT.UTF-8',
+ ];
+
+ yield [
+ LC_TIME,
+ 'it',
+ 'IT',
+ 'it_IT.UTF-8',
+ ];
+
+ yield [
+ LC_TIME,
+ 'it',
+ 'it',
+ 'it_IT.UTF-8',
+ ];
+ }
+
+ /**
+ * Provides language, encoding and country code
+ *
+ * @return Generator
+ */
+ public function provideLanguageEncodingAndCountryCode()
+ {
+ yield [
+ 'fr',
+ '',
+ '',
+ 'fr_FR',
+ ];
+
+ yield [
+ 'fr',
+ '',
+ 'UTF-8',
+ 'fr_FR.UTF-8',
+ ];
+
+ yield [
+ 'fr',
+ 'FR',
+ '',
+ 'fr_FR',
+ ];
+
+ yield [
+ 'fr',
+ 'FR',
+ 'UTF-8',
+ 'fr_FR.UTF-8',
+ ];
+
+ yield [
+ 'en',
+ 'US',
+ '',
+ 'en_US',
+ ];
+
+ yield [
+ 'en',
+ 'US',
+ 'UTF-8',
+ 'en_US.UTF-8',
+ ];
+
+ yield [
+ 'en',
+ 'US',
+ 'ISO-8859-1',
+ 'en_US.ISO-8859-1',
+ ];
+ }
+
/**
* @throws ReflectionException
*/
@@ -29,56 +160,6 @@ class LocaleTest extends BaseTestCase
static::assertHasNoConstructor(Locale::class);
}
- /**
- * @param mixed $languageCode Empty value, e.g. ""
- * @dataProvider provideEmptyValue
- */
- public function testGetLongFormEmptyLanguageCode($languageCode)
- {
- self::assertEquals('', Locale::getLongForm($languageCode));
- }
-
- /**
- * @param string $languageCode Language code, in ISO 639-1 format. Short form of the locale, e.g. "fr".
- * @param string $countryCode Country code, in ISO 3166-1 alpha-2 format, e.g. "FR"
- * @param string $encoding Encoding of the final locale
- * @param string $expected Expected long form of the locale
- *
- * @dataProvider provideLanguageEncodingAndCountryCode
- */
- public function testGetLongForm($languageCode, $countryCode, $encoding, $expected)
- {
- self::assertEquals($expected, Locale::getLongForm($languageCode, $countryCode, $encoding));
- }
-
- /**
- * @param mixed $emptyValue Empty value, e.g. ""
- * @dataProvider provideEmptyValue
- */
- public function testSetLocaleEmptyCategoryAndLanguageCode($emptyValue)
- {
- self::assertFalse(Locale::setLocale($emptyValue, $emptyValue));
- }
-
- public function testSetLocaleIncorrectCategory()
- {
- self::assertFalse(Locale::setLocale(-1, 'en'));
- }
-
- /**
- * @param int $category Named constant specifying the category of the functions affected by the locale
- * setting. It's the same constant as required by setlocale() function.
- * @param string $languageCode Language code, in ISO 639-1 format. Short form of the locale, e.g. "fr".
- * @param string $countryCode Country code, in ISO 3166-1 alpha-2 format, e.g. "FR"
- * @param string $expectedLocale Expected locale
- *
- * @dataProvider provideCategoryLanguageCodeAndExpectedLocale
- */
- public function testSetLocale($category, $languageCode, $countryCode, $expectedLocale)
- {
- self::assertEquals($expectedLocale, Locale::setLocale($category, $languageCode, $countryCode));
- }
-
/**
* @param int $category Named constant specifying the category of the functions affected by the locale
* setting. It's the same constant as required by setlocale() function.
@@ -95,130 +176,52 @@ class LocaleTest extends BaseTestCase
}
/**
- * Provides language, encoding and country code
+ * @param string $languageCode Language code, in ISO 639-1 format. Short form of the locale, e.g. "fr".
+ * @param string $countryCode Country code, in ISO 3166-1 alpha-2 format, e.g. "FR"
+ * @param string $encoding Encoding of the final locale
+ * @param string $expected Expected long form of the locale
*
- * @return Generator
+ * @dataProvider provideLanguageEncodingAndCountryCode
*/
- public function provideLanguageEncodingAndCountryCode()
+ public function testGetLongForm($languageCode, $countryCode, $encoding, $expected)
{
- yield[
- 'fr',
- '',
- '',
- 'fr_FR',
- ];
-
- yield[
- 'fr',
- '',
- 'UTF-8',
- 'fr_FR.UTF-8',
- ];
-
- yield[
- 'fr',
- 'FR',
- '',
- 'fr_FR',
- ];
-
- yield[
- 'fr',
- 'FR',
- 'UTF-8',
- 'fr_FR.UTF-8',
- ];
-
- yield[
- 'en',
- 'US',
- '',
- 'en_US',
- ];
-
- yield[
- 'en',
- 'US',
- 'UTF-8',
- 'en_US.UTF-8',
- ];
-
- yield[
- 'en',
- 'US',
- 'ISO-8859-1',
- 'en_US.ISO-8859-1',
- ];
+ self::assertEquals($expected, Locale::getLongForm($languageCode, $countryCode, $encoding));
}
/**
- * Provides category
- *
- * @return Generator
+ * @param mixed $languageCode Empty value, e.g. ""
+ * @dataProvider provideEmptyValue
*/
- public function provideCategoryLanguageCodeAndExpectedLocale()
+ public function testGetLongFormEmptyLanguageCode($languageCode)
{
- yield[
- LC_ALL,
- 'fr',
- '',
- 'fr_FR.UTF-8',
- ];
+ self::assertEquals('', Locale::getLongForm($languageCode));
+ }
- yield[
- LC_COLLATE,
- 'fr',
- 'FR',
- 'fr_FR.UTF-8',
- ];
+ /**
+ * @param int $category Named constant specifying the category of the functions affected by the locale
+ * setting. It's the same constant as required by setlocale() function.
+ * @param string $languageCode Language code, in ISO 639-1 format. Short form of the locale, e.g. "fr".
+ * @param string $countryCode Country code, in ISO 3166-1 alpha-2 format, e.g. "FR"
+ * @param string $expectedLocale Expected locale
+ *
+ * @dataProvider provideCategoryLanguageCodeAndExpectedLocale
+ */
+ public function testSetLocale($category, $languageCode, $countryCode, $expectedLocale)
+ {
+ self::assertEquals($expectedLocale, Locale::setLocale($category, $languageCode, $countryCode));
+ }
- yield[
- LC_CTYPE,
- 'en',
- 'US',
- 'en_US.UTF-8',
- ];
+ /**
+ * @param mixed $emptyValue Empty value, e.g. ""
+ * @dataProvider provideEmptyValue
+ */
+ public function testSetLocaleEmptyCategoryAndLanguageCode($emptyValue)
+ {
+ self::assertFalse(Locale::setLocale($emptyValue, $emptyValue));
+ }
- yield[
- LC_NUMERIC,
- 'en',
- 'GB',
- 'en_GB.UTF-8',
- ];
-
- yield[
- LC_MONETARY,
- 'es',
- '',
- 'es_ES.UTF-8',
- ];
-
- yield[
- LC_MONETARY,
- 'es',
- 'ES',
- 'es_ES.UTF-8',
- ];
-
- yield[
- LC_TIME,
- 'it',
- '',
- 'it_IT.UTF-8',
- ];
-
- yield[
- LC_TIME,
- 'it',
- 'IT',
- 'it_IT.UTF-8',
- ];
-
- yield[
- LC_TIME,
- 'it',
- 'it',
- 'it_IT.UTF-8',
- ];
+ public function testSetLocaleIncorrectCategory()
+ {
+ self::assertFalse(Locale::setLocale(-1, 'en'));
}
}
diff --git a/tests/Utilities/MimeTypesTest.php b/tests/Utilities/MimeTypesTest.php
index ee0e85e..829495f 100644
--- a/tests/Utilities/MimeTypesTest.php
+++ b/tests/Utilities/MimeTypesTest.php
@@ -17,14 +17,311 @@ use Meritoo\Common\Utilities\MimeTypes;
*
* @author Meritoo
* @copyright Meritoo
+ *
+ * @internal
+ * @covers \Meritoo\Common\Utilities\MimeTypes
*/
class MimeTypesTest extends BaseTestCase
{
+ /**
+ * Provides real file path to get information if the file is an image
+ *
+ * @return Generator
+ */
+ public function provideExistingFilePathToCheckIsImagePath()
+ {
+ yield [
+ $this->getFilePathForTesting('minion.jpg'),
+ true,
+ ];
+
+ yield [
+ $this->getFilePathForTesting('lorem-ipsum.txt'),
+ false,
+ ];
+ }
+
+ /**
+ * Provides real file path to get mime type
+ *
+ * @return Generator
+ */
+ public function provideFilePathToGetMimeTypeOfRealFile()
+ {
+ yield [
+ $this->getFilePathForTesting('minion.jpg'),
+ 'image/jpeg',
+ ];
+
+ yield [
+ $this->getFilePathForTesting('lorem-ipsum.txt'),
+ 'text/plain',
+ ];
+ }
+
+ /**
+ * Provides mime type of image
+ *
+ * @return Generator
+ */
+ public function provideImageMimeType()
+ {
+ yield ['image/bmp'];
+ yield ['image/jpeg'];
+ yield ['image/png'];
+ yield ['image/tiff'];
+ yield ['image/vnd.microsoft.icon'];
+ yield ['image/x-rgb'];
+ }
+
+ /**
+ * Provides existing mime type used to get multiple, more than one extension
+ *
+ * @return Generator
+ */
+ public function provideMimeTypeToGetMultipleExtension()
+ {
+ yield [
+ 'application/postscript',
+ [
+ 'ai',
+ 'eps',
+ 'ps',
+ ],
+ ];
+
+ yield [
+ 'audio/midi',
+ [
+ 'mid',
+ 'midi',
+ 'kar',
+ 'rmi',
+ ],
+ ];
+
+ yield [
+ 'image/jpeg',
+ [
+ 'jpeg',
+ 'jpe',
+ 'jpg',
+ ],
+ ];
+
+ yield [
+ 'text/html',
+ [
+ 'html',
+ 'htm',
+ ],
+ ];
+
+ yield [
+ 'text/plain',
+ [
+ 'txt',
+ 'text',
+ 'conf',
+ 'def',
+ 'list',
+ 'log',
+ 'in',
+ ],
+ ];
+
+ yield [
+ 'video/mp4',
+ [
+ 'mp4',
+ 'mp4v',
+ 'mpg4',
+ 'm4v',
+ ],
+ ];
+ }
+
+ /**
+ * Provides existing mime type used to get single, one extension
+ *
+ * @return Generator
+ */
+ public function provideMimeTypeToGetSingleExtension()
+ {
+ yield [
+ 'application/x-7z-compressed',
+ '7z',
+ ];
+
+ yield [
+ 'application/json',
+ 'json',
+ ];
+
+ yield [
+ 'application/zip',
+ 'zip',
+ ];
+ }
+
+ /**
+ * Provides mime types used to get extensions
+ *
+ * @return Generator
+ */
+ public function provideMimesTypesToGetExtensions()
+ {
+ yield [
+ [
+ 'application/x-7z-compressed',
+ 'application/json',
+ ],
+ [
+ 'application/x-7z-compressed' => '7z',
+ 'application/json' => 'json',
+ ],
+ ];
+
+ yield [
+ [
+ 'application/mathematica',
+ 'application/xml',
+ 'audio/mp4',
+ 'video/mp4',
+ ],
+ [
+ 'application/mathematica' => [
+ 'ma',
+ 'nb',
+ 'mb',
+ ],
+ 'application/xml' => [
+ 'xml',
+ 'xsl',
+ ],
+ 'audio/mp4' => 'mp4a',
+ 'video/mp4' => [
+ 'mp4',
+ 'mp4v',
+ 'mpg4',
+ 'm4v',
+ ],
+ ],
+ ];
+ }
+
+ /**
+ * Provides mime types used to get extensions as upper case
+ *
+ * @return Generator
+ */
+ public function provideMimesTypesToGetExtensionsUpperCase()
+ {
+ yield [
+ [
+ 'application/x-7z-compressed',
+ 'application/json',
+ ],
+ [
+ 'application/x-7z-compressed' => '7Z',
+ 'application/json' => 'JSON',
+ ],
+ ];
+
+ yield [
+ [
+ 'application/xml',
+ 'audio/mp4',
+ 'text/html',
+ 'video/mp4',
+ ],
+ [
+ 'application/xml' => [
+ 'XML',
+ 'XSL',
+ ],
+ 'audio/mp4' => 'MP4A',
+ 'text/html' => [
+ 'HTML',
+ 'HTM',
+ ],
+ 'video/mp4' => [
+ 'MP4',
+ 'MP4V',
+ 'MPG4',
+ 'M4V',
+ ],
+ ],
+ ];
+ }
+
+ /**
+ * Provides mime type of non-image
+ *
+ * @return Generator
+ */
+ public function provideNonImageMimeType()
+ {
+ yield ['application/rtf'];
+ yield ['audio/mp4'];
+ yield ['text/plain'];
+ yield ['text/html'];
+ }
+
+ /**
+ * Provides not existing mime type
+ *
+ * @return Generator
+ */
+ public function provideNotExistingMimeType()
+ {
+ yield ['lorem/ipsum'];
+ yield ['dolor'];
+ yield ['x/y/z'];
+ }
+
+ /**
+ * Provides not existing mime types
+ *
+ * @return Generator
+ */
+ public function provideNotExistingMimeTypes()
+ {
+ yield [
+ [],
+ ];
+
+ yield [
+ [
+ '',
+ null,
+ false,
+ 0,
+ ],
+ ];
+
+ yield [
+ [
+ 'lorem/ipsum',
+ 'dolor/sit',
+ ],
+ ];
+ }
+
public function testConstructor()
{
static::assertHasNoConstructor(MimeTypes::class);
}
+ /**
+ * @param bool $mimeType The mime type, e.g. "video/mpeg"
+ * @dataProvider provideBooleanValue
+ */
+ public function testGetExtensionBooleanMimeType($mimeType)
+ {
+ self::assertEquals('', MimeTypes::getExtension($mimeType));
+ }
+
/**
* @param mixed $mimeType Empty value, e.g. ""
* @dataProvider provideEmptyValue
@@ -35,12 +332,14 @@ class MimeTypesTest extends BaseTestCase
}
/**
- * @param bool $mimeType The mime type, e.g. "video/mpeg"
- * @dataProvider provideBooleanValue
+ * @param string $mimeType The mime type, e.g. "video/mpeg"
+ * @param array $extensions Expected extensions
+ *
+ * @dataProvider provideMimeTypeToGetMultipleExtension
*/
- public function testGetExtensionBooleanMimeType($mimeType)
+ public function testGetExtensionMultiple($mimeType, $extensions)
{
- self::assertEquals('', MimeTypes::getExtension($mimeType));
+ self::assertEquals($extensions, MimeTypes::getExtension($mimeType));
}
/**
@@ -64,14 +363,14 @@ class MimeTypesTest extends BaseTestCase
}
/**
- * @param string $mimeType The mime type, e.g. "video/mpeg"
- * @param array $extensions Expected extensions
+ * @param array $mimesTypes The mimes types, e.g. ['video/mpeg', 'image/jpeg']
+ * @param array $extensions Expected extensions
*
- * @dataProvider provideMimeTypeToGetMultipleExtension
+ * @dataProvider provideMimesTypesToGetExtensions
*/
- public function testGetExtensionMultiple($mimeType, $extensions)
+ public function testGetExtensions($mimesTypes, $extensions)
{
- self::assertEquals($extensions, MimeTypes::getExtension($mimeType));
+ self::assertEquals($extensions, MimeTypes::getExtensions($mimesTypes));
}
/**
@@ -83,17 +382,6 @@ class MimeTypesTest extends BaseTestCase
self::assertEquals([], MimeTypes::getExtensions($mimesTypes));
}
- /**
- * @param array $mimesTypes The mimes types, e.g. ['video/mpeg', 'image/jpeg']
- * @param array $extensions Expected extensions
- *
- * @dataProvider provideMimesTypesToGetExtensions
- */
- public function testGetExtensions($mimesTypes, $extensions)
- {
- self::assertEquals($extensions, MimeTypes::getExtensions($mimesTypes));
- }
-
/**
* @param array $mimesTypes The mimes types, e.g. ['video/mpeg', 'image/jpeg']
* @param array $extensions Expected extensions
@@ -135,12 +423,12 @@ class MimeTypesTest extends BaseTestCase
}
/**
- * @param string $mimeType Not existing mime type, e.g. "lorem/ipsum"
- * @dataProvider provideNotExistingMimeType
+ * @param string $mimeType Mime type of image, e.g. "image/jpeg"
+ * @dataProvider provideImageMimeType
*/
- public function testIsImageNotExistingMimeType($mimeType)
+ public function testIsImageImageMimeType($mimeType)
{
- self::assertFalse(MimeTypes::isImage($mimeType));
+ self::assertTrue(MimeTypes::isImage($mimeType));
}
/**
@@ -152,6 +440,15 @@ class MimeTypesTest extends BaseTestCase
self::assertFalse(MimeTypes::isImage($mimeType));
}
+ /**
+ * @param string $mimeType Not existing mime type, e.g. "lorem/ipsum"
+ * @dataProvider provideNotExistingMimeType
+ */
+ public function testIsImageNotExistingMimeType($mimeType)
+ {
+ self::assertFalse(MimeTypes::isImage($mimeType));
+ }
+
/**
* @param mixed $path Empty value, e.g. ""
* @dataProvider provideEmptyValue
@@ -161,15 +458,6 @@ class MimeTypesTest extends BaseTestCase
self::assertFalse(MimeTypes::isImagePath($path));
}
- /**
- * @param mixed $path Path of not existing file, e.g. "lorem/ipsum.jpg"
- * @dataProvider provideNotExistingFilePath
- */
- public function testIsImagePathNotExistingPath($path)
- {
- self::assertFalse(MimeTypes::isImagePath($path));
- }
-
/**
* @param string $path Path of the file to check
* @param bool $isImage Expected information if the file is an image
@@ -182,296 +470,11 @@ class MimeTypesTest extends BaseTestCase
}
/**
- * @param string $mimeType Mime type of image, e.g. "image/jpeg"
- * @dataProvider provideImageMimeType
+ * @param mixed $path Path of not existing file, e.g. "lorem/ipsum.jpg"
+ * @dataProvider provideNotExistingFilePath
*/
- public function testIsImageImageMimeType($mimeType)
+ public function testIsImagePathNotExistingPath($path)
{
- self::assertTrue(MimeTypes::isImage($mimeType));
- }
-
- /**
- * Provides not existing mime type
- *
- * @return Generator
- */
- public function provideNotExistingMimeType()
- {
- yield['lorem/ipsum'];
- yield['dolor'];
- yield['x/y/z'];
- }
-
- /**
- * Provides mime type of non-image
- *
- * @return Generator
- */
- public function provideNonImageMimeType()
- {
- yield['application/rtf'];
- yield['audio/mp4'];
- yield['text/plain'];
- yield['text/html'];
- }
-
- /**
- * Provides mime type of image
- *
- * @return Generator
- */
- public function provideImageMimeType()
- {
- yield['image/bmp'];
- yield['image/jpeg'];
- yield['image/png'];
- yield['image/tiff'];
- yield['image/vnd.microsoft.icon'];
- yield['image/x-rgb'];
- }
-
- /**
- * Provides existing mime type used to get single, one extension
- *
- * @return Generator
- */
- public function provideMimeTypeToGetSingleExtension()
- {
- yield[
- 'application/x-7z-compressed',
- '7z',
- ];
-
- yield[
- 'application/json',
- 'json',
- ];
-
- yield[
- 'application/zip',
- 'zip',
- ];
- }
-
- /**
- * Provides existing mime type used to get multiple, more than one extension
- *
- * @return Generator
- */
- public function provideMimeTypeToGetMultipleExtension()
- {
- yield[
- 'application/postscript',
- [
- 'ai',
- 'eps',
- 'ps',
- ],
- ];
-
- yield[
- 'audio/midi',
- [
- 'mid',
- 'midi',
- 'kar',
- 'rmi',
- ],
- ];
-
- yield[
- 'image/jpeg',
- [
- 'jpeg',
- 'jpe',
- 'jpg',
- ],
- ];
-
- yield[
- 'text/html',
- [
- 'html',
- 'htm',
- ],
- ];
-
- yield[
- 'text/plain',
- [
- 'txt',
- 'text',
- 'conf',
- 'def',
- 'list',
- 'log',
- 'in',
- ],
- ];
-
- yield[
- 'video/mp4',
- [
- 'mp4',
- 'mp4v',
- 'mpg4',
- 'm4v',
- ],
- ];
- }
-
- /**
- * Provides not existing mime types
- *
- * @return Generator
- */
- public function provideNotExistingMimeTypes()
- {
- yield[
- [],
- ];
-
- yield[
- [
- '',
- null,
- false,
- 0,
- ],
- ];
-
- yield[
- [
- 'lorem/ipsum',
- 'dolor/sit',
- ],
- ];
- }
-
- /**
- * Provides mime types used to get extensions
- *
- * @return Generator
- */
- public function provideMimesTypesToGetExtensions()
- {
- yield[
- [
- 'application/x-7z-compressed',
- 'application/json',
- ],
- [
- 'application/x-7z-compressed' => '7z',
- 'application/json' => 'json',
- ],
- ];
-
- yield[
- [
- 'application/mathematica',
- 'application/xml',
- 'audio/mp4',
- 'video/mp4',
- ],
- [
- 'application/mathematica' => [
- 'ma',
- 'nb',
- 'mb',
- ],
- 'application/xml' => [
- 'xml',
- 'xsl',
- ],
- 'audio/mp4' => 'mp4a',
- 'video/mp4' => [
- 'mp4',
- 'mp4v',
- 'mpg4',
- 'm4v',
- ],
- ],
- ];
- }
-
- /**
- * Provides mime types used to get extensions as upper case
- *
- * @return Generator
- */
- public function provideMimesTypesToGetExtensionsUpperCase()
- {
- yield[
- [
- 'application/x-7z-compressed',
- 'application/json',
- ],
- [
- 'application/x-7z-compressed' => '7Z',
- 'application/json' => 'JSON',
- ],
- ];
-
- yield[
- [
- 'application/xml',
- 'audio/mp4',
- 'text/html',
- 'video/mp4',
- ],
- [
- 'application/xml' => [
- 'XML',
- 'XSL',
- ],
- 'audio/mp4' => 'MP4A',
- 'text/html' => [
- 'HTML',
- 'HTM',
- ],
- 'video/mp4' => [
- 'MP4',
- 'MP4V',
- 'MPG4',
- 'M4V',
- ],
- ],
- ];
- }
-
- /**
- * Provides real file path to get mime type
- *
- * @return Generator
- */
- public function provideFilePathToGetMimeTypeOfRealFile()
- {
- yield[
- $this->getFilePathForTesting('minion.jpg'),
- 'image/jpeg',
- ];
-
- yield[
- $this->getFilePathForTesting('lorem-ipsum.txt'),
- 'text/plain',
- ];
- }
-
- /**
- * Provides real file path to get information if the file is an image
- *
- * @return Generator
- */
- public function provideExistingFilePathToCheckIsImagePath()
- {
- yield[
- $this->getFilePathForTesting('minion.jpg'),
- true,
- ];
-
- yield[
- $this->getFilePathForTesting('lorem-ipsum.txt'),
- false,
- ];
+ self::assertFalse(MimeTypes::isImagePath($path));
}
}
diff --git a/tests/Utilities/MiscellaneousTest.php b/tests/Utilities/MiscellaneousTest.php
index 70c36c7..7705cb0 100644
--- a/tests/Utilities/MiscellaneousTest.php
+++ b/tests/Utilities/MiscellaneousTest.php
@@ -21,6 +21,9 @@ use stdClass;
*
* @author Meritoo
* @copyright Meritoo
+ *
+ * @internal
+ * @covers \Meritoo\Common\Utilities\Miscellaneous
*/
class MiscellaneousTest extends BaseTestCase
{
@@ -29,25 +32,978 @@ class MiscellaneousTest extends BaseTestCase
private $stringDotSeparated;
private $stringWithoutSpaces;
- public function testConstructor()
+ public function provideDataToReplaceWithQuoteStrings()
{
- static::assertHasNoConstructor(Miscellaneous::class);
+ yield [
+ 'An empty string as subject',
+ '',
+ 'test',
+ 'another test',
+ '',
+ ];
+
+ yield [
+ 'An empty string to search',
+ 'test',
+ '',
+ 'another test',
+ 'test',
+ ];
+
+ yield [
+ 'An empty string as replacement',
+ 'test',
+ 'another test',
+ '',
+ 'test',
+ ];
+
+ yield [
+ 'Replace 1 not existing word in 1 sentence (nothing to replace)',
+ 'Lorem ipsum dolor sit amet',
+ 'plum',
+ 'commodo',
+ 'Lorem ipsum dolor sit amet',
+ ];
+
+ yield [
+ 'Replace 1 word in 1 sentence',
+ 'Lorem ipsum dolor sit amet',
+ 'ipsum',
+ 'commodo',
+ 'Lorem \'commodo\' dolor sit amet',
+ ];
+
+ yield [
+ 'Replace 1 word in 2 sentences',
+ [
+ 'Lorem ipsum dolor sit amet',
+ 'Maecenas sed diam eget risus varius blandit sit amet',
+ ],
+ 'amet',
+ 'commodo',
+ [
+ 'Lorem ipsum dolor sit \'commodo\'',
+ 'Maecenas sed diam eget risus varius blandit sit \'commodo\'',
+ ],
+ ];
+
+ yield [
+ '1 pattern (word -> "")',
+ 'Lorem ipsum dolor sit amet',
+ '|ipsum|',
+ '',
+ 'Lorem \'\' dolor sit amet',
+ ];
+
+ yield [
+ '1 pattern (word -> word)',
+ 'Lorem ipsum dolor sit amet',
+ '|ipsum|',
+ 'commodo',
+ 'Lorem \'commodo\' dolor sit amet',
+ ];
+
+ yield [
+ '2 patterns (word -> word)',
+ 'Lorem ipsum dolor sit amet',
+ [
+ '|ipsum|',
+ '|amet|',
+ ],
+ [
+ 'commodo',
+ 'egestas',
+ ],
+ 'Lorem \'commodo\' dolor sit \'egestas\'',
+ ];
}
- public function testGetDirectoryContent()
+ /**
+ * Provides empty value used to fill missing zeros
+ *
+ * @return Generator
+ */
+ public function provideEmptyValueToFillMissingZeros()
{
- $directoryPath = __DIR__ . '/../';
- $filePath = __FILE__;
+ yield [''];
+ yield [' '];
+ yield [null];
+ yield [false];
+ yield [[]];
+ }
- self::assertNull(Miscellaneous::getDirectoryContent(null));
- self::assertNull(Miscellaneous::getDirectoryContent(''));
+ public function provideEmptyValuesToReplace()
+ {
+ yield [
+ 'An empty string as subject',
+ '',
+ 'test',
+ 'another test',
+ '',
+ ];
- self::assertGreaterThanOrEqual(0, count(Miscellaneous::getDirectoryContent($directoryPath)));
- self::assertGreaterThanOrEqual(0, count(Miscellaneous::getDirectoryContent($directoryPath, true)));
- self::assertGreaterThanOrEqual(0, count(Miscellaneous::getDirectoryContent($directoryPath, true, 5)));
+ yield [
+ 'An empty array as subject',
+ [],
+ 'test',
+ 'another test',
+ [],
+ ];
- self::assertGreaterThanOrEqual(0, count(Miscellaneous::getDirectoryContent($filePath)));
- self::assertGreaterThanOrEqual(0, count(Miscellaneous::getDirectoryContent($filePath, true)));
+ yield [
+ 'Null as subject',
+ null,
+ 'test',
+ 'another test',
+ null,
+ ];
+
+ yield [
+ 'An empty string to search',
+ 'test',
+ '',
+ 'another test',
+ 'test',
+ ];
+
+ yield [
+ 'An empty array to search',
+ 'test',
+ [],
+ 'another test',
+ 'test',
+ ];
+
+ yield [
+ 'Null to search',
+ 'test',
+ null,
+ 'another test',
+ 'test',
+ ];
+
+ yield [
+ 'An empty string as replacement',
+ 'test',
+ 'another test',
+ '',
+ 'test',
+ ];
+
+ yield [
+ 'An empty array as replacement',
+ 'test',
+ 'another test',
+ [],
+ 'test',
+ ];
+
+ yield [
+ 'Null as replacement',
+ 'test',
+ 'another test',
+ null,
+ 'test',
+ ];
+ }
+
+ /**
+ * Provides names of files
+ *
+ * @return Generator
+ */
+ public function provideFileNames()
+ {
+ yield [
+ 'Lorem.ipsum-dolor.sit.JPG',
+ 'Lorem.ipsum-dolor.sit',
+ ];
+
+ yield [
+ 'lets-test.doc',
+ 'lets-test',
+ ];
+
+ yield [
+ 'something/else.txt',
+ 'something/else',
+ ];
+
+ yield [
+ 'public/js/user.js',
+ 'public/js/user',
+ ];
+ }
+
+ public function provideFilePath(): ?Generator
+ {
+ yield [
+ 'Path with file',
+ 'lorem/ipsum-dolor/sit.amet.JPG',
+ 'sit.amet.JPG',
+ ];
+
+ yield [
+ 'Path with complicated name of file',
+ 'lorem/ipsum-dolor/this-1_2 3 & my! 4+file.jpg',
+ 'this-1_2 3 & my! 4+file.jpg',
+ ];
+
+ yield [
+ 'Path without file',
+ 'lorem/ipsum-dolor/sit-amet',
+ '',
+ ];
+
+ yield [
+ 'Path with a dot "." in name of directory',
+ 'lorem/ipsum.dolor/sit.amet.JPG',
+ 'sit.amet.JPG',
+ ];
+
+ yield [
+ 'Relative path',
+ 'lorem/ipsum/../dolor/sit.amet.JPG',
+ 'sit.amet.JPG',
+ ];
+ }
+
+ public function provideGreatestCommonDivisor(): ?Generator
+ {
+ yield [
+ 0,
+ 0,
+ 0,
+ ];
+
+ yield [
+ 1,
+ 1,
+ 1,
+ ];
+
+ yield [
+ 5,
+ 3,
+ 1,
+ ];
+
+ yield [
+ 6,
+ 3,
+ 3,
+ ];
+
+ yield [
+ 12,
+ 9,
+ 3,
+ ];
+
+ yield [
+ 20,
+ 12,
+ 4,
+ ];
+
+ yield [
+ 120,
+ 80,
+ 40,
+ ];
+ }
+
+ public function provideLastElementOfString(): ?Generator
+ {
+ yield [
+ 'An empty string',
+ '',
+ '',
+ null,
+ ];
+
+ yield [
+ 'One-character string',
+ 'a',
+ ',',
+ null,
+ ];
+
+ yield [
+ 'String without given separator',
+ 'abc',
+ ',',
+ null,
+ ];
+
+ yield [
+ 'Simple, short string',
+ 'a, b, c',
+ ',',
+ ' c',
+ ];
+
+ yield [
+ 'A sentence',
+ 'Lorem ipsum - dolor sit - amet, consectetur adipiscing - elit.',
+ '-',
+ ' elit.',
+ ];
+
+ yield [
+ 'A class namespace',
+ 'This\\Is\\My\\Class\\For\\Testing',
+ '\\',
+ 'Testing',
+ ];
+ }
+
+ /**
+ * Provides number used to fill missing zeros
+ *
+ * @return Generator
+ */
+ public function provideNumberToFillMissingZeros()
+ {
+ yield [
+ 0,
+ 0,
+ true,
+ '0',
+ ];
+
+ yield [
+ 0,
+ 0,
+ false,
+ '0',
+ ];
+
+ yield [
+ 1,
+ 0,
+ true,
+ '1',
+ ];
+
+ yield [
+ 1,
+ 0,
+ false,
+ '1',
+ ];
+
+ yield [
+ 1,
+ 1,
+ true,
+ '1',
+ ];
+
+ yield [
+ 1,
+ 1,
+ false,
+ '1',
+ ];
+
+ yield [
+ 123,
+ 5,
+ true,
+ '00123',
+ ];
+
+ yield [
+ 123,
+ 5,
+ false,
+ '12300',
+ ];
+ }
+
+ /**
+ * Provides path used to remove the ending directory's separator
+ *
+ * @return Generator
+ */
+ public function providePathsToRemoveEndingDirectorySeparator()
+ {
+ yield [
+ 'lorem/ipsum/dolor/',
+ '/',
+ 'lorem/ipsum/dolor',
+ ];
+
+ yield [
+ 'lorem/ipsum/dolor',
+ '/',
+ 'lorem/ipsum/dolor',
+ ];
+
+ yield [
+ 'lorem\ipsum\dolor\\',
+ '\\',
+ 'lorem\ipsum\dolor',
+ ];
+
+ yield [
+ 'lorem\ipsum\dolor',
+ '\\',
+ 'lorem\ipsum\dolor',
+ ];
+
+ yield [
+ 'lorem;ipsum;dolor;',
+ ';',
+ 'lorem;ipsum;dolor',
+ ];
+
+ yield [
+ 'lorem;ipsum;dolor',
+ ';',
+ 'lorem;ipsum;dolor',
+ ];
+ }
+
+ /**
+ * Provides path used to remove the starting / beginning directory's separator
+ *
+ * @return Generator
+ */
+ public function providePathsToRemoveStartingDirectorySeparator()
+ {
+ yield [
+ '/lorem/ipsum/dolor',
+ '/',
+ 'lorem/ipsum/dolor',
+ ];
+
+ yield [
+ 'lorem/ipsum/dolor',
+ '/',
+ 'lorem/ipsum/dolor',
+ ];
+
+ yield [
+ '\\lorem\ipsum\dolor',
+ '\\',
+ 'lorem\ipsum\dolor',
+ ];
+
+ yield [
+ 'lorem\ipsum\dolor',
+ '\\',
+ 'lorem\ipsum\dolor',
+ ];
+
+ yield [
+ ';lorem;ipsum;dolor',
+ ';',
+ 'lorem;ipsum;dolor',
+ ];
+
+ yield [
+ 'lorem;ipsum;dolor',
+ ';',
+ 'lorem;ipsum;dolor',
+ ];
+ }
+
+ public function provideRegexToReplace()
+ {
+ yield [
+ 'Different count of strings to search and replace - 1st part',
+ 'Lorem ipsum dolor sit amet',
+ [
+ '|ipsum|',
+ ],
+ 'commodo',
+ 'Lorem ipsum dolor sit amet',
+ ];
+
+ yield [
+ 'Different count of strings to search and replace - 2nd part',
+ 'Lorem ipsum dolor sit amet',
+ '|ipsum|',
+ [
+ 'commodo',
+ ],
+ 'Lorem ipsum dolor sit amet',
+ ];
+
+ yield [
+ '1 pattern (word -> "")',
+ 'Lorem ipsum dolor sit amet',
+ '|ipsum|',
+ '',
+ 'Lorem dolor sit amet',
+ ];
+
+ yield [
+ '1 pattern (word -> word)',
+ 'Lorem ipsum dolor sit amet',
+ '|ipsum|',
+ 'commodo',
+ 'Lorem commodo dolor sit amet',
+ ];
+
+ yield [
+ '2 patterns (word -> word)',
+ 'Lorem ipsum dolor sit amet',
+ [
+ '|ipsum|',
+ '|amet|',
+ ],
+ [
+ 'commodo',
+ 'egestas',
+ ],
+ 'Lorem commodo dolor sit egestas',
+ ];
+
+ yield [
+ '1 word in 2 sentences',
+ [
+ 'Lorem ipsum dolor sit amet',
+ 'Maecenas sed diam eget risus varius blandit sit amet',
+ ],
+ '|amet|',
+ 'commodo',
+ [
+ 'Lorem ipsum dolor sit commodo',
+ 'Maecenas sed diam eget risus varius blandit sit commodo',
+ ],
+ ];
+
+ yield [
+ '2 words in 2 sentences',
+ [
+ 'Lorem ipsum dolor sit amet',
+ 'Maecenas sed diam eget risus varius blandit sit amet',
+ ],
+ [
+ '|ipsum|',
+ '|amet|',
+ ],
+ [
+ 'commodo',
+ 'egestas',
+ ],
+ [
+ 'Lorem commodo dolor sit egestas',
+ 'Maecenas sed diam eget risus varius blandit sit egestas',
+ ],
+ ];
+ }
+
+ public function provideStringElements(): ?Generator
+ {
+ yield [
+ 'An empty string',
+ '',
+ '',
+ [],
+ ];
+
+ yield [
+ 'One-character string',
+ 'a',
+ ',',
+ [],
+ ];
+
+ yield [
+ 'String without given separator',
+ 'abc',
+ ',',
+ [],
+ ];
+
+ yield [
+ 'Simple, short string',
+ 'a, b, c',
+ ',',
+ [
+ 'a',
+ ' b',
+ ' c',
+ ],
+ ];
+
+ yield [
+ 'A sentence',
+ 'Lorem ipsum - dolor sit - amet, consectetur adipiscing - elit.',
+ '-',
+ [
+ 'Lorem ipsum ',
+ ' dolor sit ',
+ ' amet, consectetur adipiscing ',
+ ' elit.',
+ ],
+ ];
+
+ yield [
+ 'A class namespace',
+ 'This\\Is\\My\\Class\\For\\Testing',
+ '\\',
+ [
+ 'This',
+ 'Is',
+ 'My',
+ 'Class',
+ 'For',
+ 'Testing',
+ ],
+ ];
+ }
+
+ /**
+ * Provides string to convert to camel case
+ *
+ * @return Generator
+ */
+ public function provideStringToCamelCase()
+ {
+ yield [
+ 'lorem ipsum',
+ ' ',
+ 'loremIpsum',
+ ];
+
+ yield [
+ 'Lorem ipSum Dolor',
+ ' ',
+ 'loremIpsumDolor',
+ ];
+
+ yield [
+ 'abc;def;ghi',
+ ';',
+ 'abcDefGhi',
+ ];
+ }
+
+ /**
+ * Provides string to convert characters to latin characters and lower cased and human-readable
+ *
+ * @return Generator
+ */
+ public function provideStringToLatinLowerCaseHuman()
+ {
+ yield [
+ 'asuo',
+ 'ąśüö',
+ ];
+
+ yield [
+ 'eoaslzzcn',
+ 'ęóąśłżźćń',
+ ];
+
+ yield [
+ 'loremipsum',
+ 'loremipsum',
+ ];
+
+ yield [
+ 'lorem-ipsum',
+ 'lorem ipsum',
+ ];
+
+ yield [
+ 'lorem-ipsum',
+ 'lorem;ipsum',
+ ];
+
+ yield [
+ 'lorem1ipsum2',
+ 'lorem1ipsum2',
+ ];
+
+ yield [
+ 'lorem_ipsum',
+ 'lorem ipsum',
+ '_',
+ ];
+
+ yield [
+ 'lorem-ipsum',
+ 'lorem-ipsum',
+ ];
+
+ yield [
+ 'lorem ipsum',
+ 'Lorem!Ipsum',
+ ' ',
+ ];
+
+ yield [
+ 'lorem ipsum',
+ 'Lorem.Ipsum',
+ ' ',
+ ];
+
+ yield [
+ 'lorem|ipsum',
+ 'Lorem.Ipsum',
+ '|',
+ ];
+
+ yield [
+ 'lorem-ipsum',
+ 'LoremIpsum',
+ ];
+
+ yield [
+ 'lorem.ipsum',
+ 'Lorem Ipsum',
+ '.',
+ ];
+
+ yield [
+ 'lorem.ipsum',
+ 'Lorem=Ipsum',
+ '.',
+ ];
+
+ yield [
+ 'lorem-ipsum-d',
+ 'LoremIpsumD',
+ ];
+
+ yield [
+ 'lorem.ipsum.d',
+ 'LoremIpsumD',
+ '.',
+ ];
+ }
+
+ /**
+ * Provides string to convert characters to latin characters and not lower cased and not human-readable
+ *
+ * @return Generator
+ */
+ public function provideStringToLatinNotLowerCaseHuman(): ?Generator
+ {
+ yield [
+ 'asuo',
+ 'ąśüö',
+ ];
+
+ yield [
+ 'eoaslzzcn',
+ 'ęóąśłżźćń',
+ ];
+
+ yield [
+ 'loremipsum',
+ 'loremipsum',
+ ];
+
+ yield [
+ 'LoremIpsum',
+ 'LoremIpsum',
+ ];
+
+ yield [
+ 'Lorem.Ipsum',
+ 'Lorem Ipsum',
+ '.',
+ ];
+
+ yield [
+ 'Lorem.Ipsum',
+ 'Lorem=Ipsum',
+ '.',
+ ];
+
+ yield [
+ 'LoremIpsumD',
+ 'LoremIpsumD',
+ ];
+
+ yield [
+ 'LoremIpsumD',
+ 'LoremIpsumD',
+ '.',
+ ];
+
+ yield [
+ 'lorem-ipsum',
+ 'lorem ipsum',
+ ];
+
+ yield [
+ 'lorem-ipsum',
+ 'lorem;ipsum',
+ ];
+
+ yield [
+ 'lorem1ipsum2',
+ 'lorem1ipsum2',
+ ];
+
+ yield [
+ 'lorem_ipsum',
+ 'lorem ipsum',
+ '_',
+ ];
+
+ yield [
+ 'LoremIpsum',
+ 'LoremIpsum',
+ ];
+
+ yield [
+ 'Lorem Ipsum',
+ 'Lorem!Ipsum',
+ ' ',
+ ];
+
+ yield [
+ 'Lorem Ipsum',
+ 'Lorem.Ipsum',
+ ' ',
+ ];
+
+ yield [
+ 'Lorem|Ipsum',
+ 'Lorem.Ipsum',
+ '|',
+ ];
+ }
+
+ public function provideStringToRemoveMarginalCharacter(): ?Generator
+ {
+ yield [
+ 'An empty string - remove last character',
+ '',
+ true,
+ null,
+ ];
+
+ yield [
+ 'An empty string - remove first character',
+ '',
+ false,
+ null,
+ ];
+
+ yield [
+ 'Simple, two words - remove last character',
+ 'Lorem ipsum',
+ true,
+ 'Lorem ipsu',
+ ];
+
+ yield [
+ 'Simple, two words - remove first character',
+ 'Lorem ipsum',
+ false,
+ 'orem ipsum',
+ ];
+
+ yield [
+ 'Two sentences - remove last character',
+ 'Etiam ullamcorper. Suspendisse a pellentesque dui, non felis.',
+ true,
+ 'Etiam ullamcorper. Suspendisse a pellentesque dui, non felis',
+ ];
+
+ yield [
+ 'Two sentences - remove first character',
+ 'Etiam ullamcorper. Suspendisse a pellentesque dui, non felis.',
+ false,
+ 'tiam ullamcorper. Suspendisse a pellentesque dui, non felis.',
+ ];
+ }
+
+ public function provideStringsToReplace()
+ {
+ yield [
+ 'Different count of strings to search and replace - 1st part',
+ 'Lorem ipsum dolor sit amet',
+ [
+ 'ipsum',
+ ],
+ 'commodo',
+ 'Lorem ipsum dolor sit amet',
+ ];
+
+ yield [
+ 'Different count of strings to search and replace - 2nd part',
+ 'Lorem ipsum dolor sit amet',
+ 'ipsum',
+ [
+ 'commodo',
+ ],
+ 'Lorem commodo dolor sit amet',
+ ];
+
+ yield [
+ 'Replace 1 not existing word in 1 sentence (nothing to replace)',
+ 'Lorem ipsum dolor sit amet',
+ 'plum',
+ 'commodo',
+ 'Lorem ipsum dolor sit amet',
+ ];
+
+ yield [
+ 'Replace 1 word in 1 sentence',
+ 'Lorem ipsum dolor sit amet',
+ 'ipsum',
+ 'commodo',
+ 'Lorem commodo dolor sit amet',
+ ];
+
+ yield [
+ 'Replace 1 not existing word in 2 sentences (nothing to replace)',
+ [
+ 'Lorem ipsum dolor sit amet',
+ 'Maecenas sed diam eget risus varius blandit sit amet',
+ ],
+ 'plum',
+ 'commodo',
+ [
+ 'Lorem ipsum dolor sit amet',
+ 'Maecenas sed diam eget risus varius blandit sit amet',
+ ],
+ ];
+
+ yield [
+ 'Replace 1 word in 2 sentences',
+ [
+ 'Lorem ipsum dolor sit amet',
+ 'Maecenas sed diam eget risus varius blandit sit amet',
+ ],
+ 'amet',
+ 'commodo',
+ [
+ 'Lorem ipsum dolor sit commodo',
+ 'Maecenas sed diam eget risus varius blandit sit commodo',
+ ],
+ ];
+ }
+
+ public function testBreakLongText()
+ {
+ self::assertEquals('Lorem ipsum dolor sit
amet, consectetur
adipiscing
elit', Miscellaneous::breakLongText($this->stringCommaSeparated, 20));
+ self::assertEquals('Lorem ipsum dolor sit---amet, consectetur---adipiscing---elit', Miscellaneous::breakLongText($this->stringCommaSeparated, 20, '---'));
+ self::assertEquals('LoremIpsum
DolorSitAm
etConsecte
turAdipisc
ingElit', Miscellaneous::breakLongText($this->stringWithoutSpaces, 10));
+ }
+
+ /**
+ * @param int $first
+ * @param int $second
+ * @param int $expected
+ *
+ * @dataProvider provideGreatestCommonDivisor
+ */
+ public function testCalculateGreatestCommonDivisor(int $first, int $second, int $expected): void
+ {
+ static::assertSame($expected, Miscellaneous::calculateGreatestCommonDivisor($first, $second));
}
public function testCheckboxValue2Boolean()
@@ -64,435 +1020,29 @@ class MiscellaneousTest extends BaseTestCase
self::assertEquals(0, Miscellaneous::checkboxValue2Integer(null));
}
- public function testGetFileExtension()
+ public function testConcatenatePathsInNixOs()
{
- $fileName = 'Lorem.ipsum-dolor.sit.JPG';
- self::assertEquals('JPG', Miscellaneous::getFileExtension($fileName));
- self::assertEquals('jpg', Miscellaneous::getFileExtension($fileName, true));
- }
-
- /**
- * @param string $fileName Empty value, e.g. ""
- * @dataProvider provideEmptyValue
- */
- public function testGetFileNameWithoutExtensionEmptyValue($fileName)
- {
- self::assertEquals('', Miscellaneous::getFileNameWithoutExtension($fileName));
- }
-
- /**
- * @param string $fileName The file name with extension
- * @param string $withoutExtension The file name without extension
- *
- * @dataProvider provideFileNames
- */
- public function testGetFileNameWithoutExtension($fileName, $withoutExtension)
- {
- self::assertEquals($withoutExtension, Miscellaneous::getFileNameWithoutExtension($fileName));
- }
-
- public function testGetFileNameFromPath()
- {
- /*
- * Path with file
- */
- self::assertEquals('sit.amet.JPG', Miscellaneous::getFileNameFromPath('lorem/ipsum-dolor/sit.amet.JPG'));
-
- /*
- * Path without file
- */
- self::assertEquals('', Miscellaneous::getFileNameFromPath('lorem/ipsum-dolor/sit-amet'));
-
- /*
- * Path with a dot "." in name of directory
- */
- self::assertEquals('sit.amet.JPG', Miscellaneous::getFileNameFromPath('lorem/ipsum.dolor/sit.amet.JPG'));
-
- /*
- * Relative path
- */
- self::assertEquals('sit.amet.JPG', Miscellaneous::getFileNameFromPath('lorem/ipsum/../dolor/sit.amet.JPG'));
- }
-
- public function testGetUniqueFileName()
- {
- $originalFileName = 'Lorem.ipsum-dolor.sit.JPG';
- $pattern = '|^lorem\-ipsum\-dolor\-sit\-[a-z0-9.-]+\.jpg$|';
-
- /*
- * With object ID
- */
- $uniqueFileName1 = Miscellaneous::getUniqueFileName($originalFileName, 123);
-
- /*
- * Without object ID
- */
- $uniqueFileName2 = Miscellaneous::getUniqueFileName($originalFileName);
-
- $isCorrect1 = (bool)preg_match($pattern, $uniqueFileName1);
- $isCorrect2 = (bool)preg_match($pattern, $uniqueFileName2);
-
- self::assertTrue($isCorrect1);
- self::assertTrue($isCorrect2);
- }
-
- public function testValue2NonNegativeInteger()
- {
- self::assertEquals(2, Miscellaneous::value2NonNegativeInteger('2'));
- self::assertEquals(0, Miscellaneous::value2NonNegativeInteger('a'));
- self::assertEquals('-', Miscellaneous::value2NonNegativeInteger('-4', '-'));
- }
-
- public function testIsPhpModuleLoaded()
- {
- $loadedExtensions = get_loaded_extensions();
- $firstExtension = $loadedExtensions[0];
-
- self::assertTrue(Miscellaneous::isPhpModuleLoaded($firstExtension));
- self::assertFalse(Miscellaneous::isPhpModuleLoaded('xyz123'));
- }
-
- /**
- * @param mixed $string Empty value, e.g. ""
- * @dataProvider provideEmptyValue
- */
- public function testToLatinEmptyValue($string)
- {
- self::assertEquals('', Miscellaneous::toLatin($string));
- }
-
- /**
- * @param string $expected Expected/converted string
- * @param string $string String to convert
- * @param string $replacementChar (optional) Replacement character for all non-latin characters
- *
- * @dataProvider provideStringToLatinNotLowerCaseHuman
- */
- public function testToLatinNotLowerCaseHuman($expected, $string, $replacementChar = '-')
- {
- self::assertEquals($expected, Miscellaneous::toLatin($string, false, $replacementChar));
- }
-
- /**
- * @param string $expected Expected/converted string
- * @param string $string String to convert
- * @param string $replacementChar (optional) Replacement character for all non-latin characters
- *
- * @dataProvider provideStringToLatinLowerCaseHuman
- */
- public function testToLatinLowerCaseHuman($expected, $string, $replacementChar = '-')
- {
- self::assertEquals($expected, Miscellaneous::toLatin($string, true, $replacementChar));
- }
-
- public function testGetUniqueString()
- {
- $prefix = '';
- $hashed = false;
- self::assertEquals(23, strlen(Miscellaneous::getUniqueString($prefix, $hashed)));
-
- $prefix = 'xyz';
- $hashed = false;
- self::assertEquals(26, strlen(Miscellaneous::getUniqueString($prefix, $hashed)));
-
- $hashed = true;
- self::assertEquals(40, strlen(Miscellaneous::getUniqueString($prefix, $hashed)));
- }
-
- /**
- * @param string|array $search An empty value to find
- * @dataProvider provideEmptyValue
- */
- public function testReplaceEmptyValue($search)
- {
- $replacement1 = '';
- $replacement2 = [];
-
- $replacement3 = [
- 'commodo',
- 'interdum',
+ // For *nix operating system
+ $paths1 = [
+ 'first/directory',
+ 'second/one',
+ 'and/the/third',
];
- self::assertEquals($this->stringSmall, Miscellaneous::replace($this->stringSmall, $search, $replacement1));
- self::assertEquals($this->stringSmall, Miscellaneous::replace($this->stringSmall, $search, $replacement2));
- self::assertEquals($this->stringSmall, Miscellaneous::replace($this->stringSmall, $search, $replacement3));
-
- self::assertEquals($this->stringSmall, Miscellaneous::replace($this->stringSmall, $search, $replacement1, true));
- self::assertEquals($this->stringSmall, Miscellaneous::replace($this->stringSmall, $search, $replacement2, true));
- self::assertEquals($this->stringSmall, Miscellaneous::replace($this->stringSmall, $search, $replacement3, true));
+ self::assertEquals('/'.implode('/', $paths1), Miscellaneous::concatenatePaths($paths1));
+ self::assertEquals('/'.implode('/', $paths1), Miscellaneous::concatenatePaths($paths1[0], $paths1[1], $paths1[2]));
}
- /**
- * @param string $description Description of test
- * @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 mixed $result Result of replacing
- *
- * @dataProvider provideEmptyValuesToReplace
- */
- public function testReplaceUsingEmptyValues($description, $subject, $search, $replacement, $result)
+ public function testConcatenatePathsInWindowsOs()
{
- static::assertSame($result, Miscellaneous::replace($subject, $search, $replacement), $description);
- }
+ // For Windows operating system
+ $paths2 = [
+ 'C:\first\directory',
+ 'second\one',
+ 'and\the\third',
+ ];
- /**
- * @param string $description Description of test
- * @param string $subject The string or an array of strings to search and replace
- * @param string $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 $replacement The string or an array of strings to replace. It may be: string or an array of
- * strings.
- * @param mixed $result Result of replacing
- *
- * @dataProvider provideStringsToReplace
- */
- public function testReplaceUsingStrings($description, $subject, $search, $replacement, $result)
- {
- static::assertSame($result, Miscellaneous::replace($subject, $search, $replacement), $description);
- }
-
- /**
- * @param string $description Description of test
- * @param string $subject The string or an array of strings to search and replace
- * @param string $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 $replacement The string or an array of strings to replace. It may be: string or an array of
- * strings.
- * @param mixed $result Result of replacing
- *
- * @dataProvider provideRegexToReplace
- */
- public function testReplaceUsingRegex($description, $subject, $search, $replacement, $result)
- {
- static::assertSame($result, Miscellaneous::replace($subject, $search, $replacement), $description);
- }
-
- /**
- * @param string $description Description of test
- * @param string $subject The string or an array of strings to search and replace
- * @param string $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 $replacement The string or an array of strings to replace. It may be: string or an array of
- * strings.
- * @param mixed $result Result of replacing
- *
- * @dataProvider provideDataToReplaceWithQuoteStrings
- */
- public function testReplaceWithQuoteStrings($description, $subject, $search, $replacement, $result)
- {
- static::assertSame($result, Miscellaneous::replace($subject, $search, $replacement, true), $description);
- }
-
- public function testUppercaseFirst()
- {
- self::assertEquals('', Miscellaneous::uppercaseFirst(''));
- self::assertEquals('', Miscellaneous::uppercaseFirst(null));
- self::assertEquals('', Miscellaneous::uppercaseFirst(false));
-
- $text = 'lorEM ipsum dolor sit Amet';
- self::assertEquals('LorEM ipsum dolor sit Amet', Miscellaneous::uppercaseFirst($text));
-
- $restLowercase = true;
- self::assertEquals('Lorem ipsum dolor sit amet', Miscellaneous::uppercaseFirst($text, $restLowercase));
-
- $restLowercase = false;
- self::assertEquals('LOREM IPSUM DOLOR SIT AMET', Miscellaneous::uppercaseFirst($text, $restLowercase));
- }
-
- public function testLowercaseFirst()
- {
- self::assertEquals('', Miscellaneous::lowercaseFirst(''));
- self::assertEquals('', Miscellaneous::lowercaseFirst(null));
- self::assertEquals('', Miscellaneous::lowercaseFirst(false));
-
- $text = 'LorEM ipsum dolor sit Amet';
- self::assertEquals('lorEM ipsum dolor sit Amet', Miscellaneous::lowercaseFirst($text));
-
- $restLowercase = true;
- self::assertEquals('lorem ipsum dolor sit amet', Miscellaneous::lowercaseFirst($text, $restLowercase));
-
- $restLowercase = false;
- self::assertEquals('lOREM IPSUM DOLOR SIT AMET', Miscellaneous::lowercaseFirst($text, $restLowercase));
- }
-
- public function testGetNewFileName()
- {
- self::assertEquals('test.jpg', Miscellaneous::getNewFileName('test.jpg', '', ''));
- self::assertEquals('my-test.jpg', Miscellaneous::getNewFileName('test.jpg', 'my-', ''));
- self::assertEquals('test-file.jpg', Miscellaneous::getNewFileName('test.jpg', '', '-file'));
- self::assertEquals('my-test-file.jpg', Miscellaneous::getNewFileName('test.jpg', 'my-', '-file'));
- }
-
- public function testGetOperatingSystemNameServer()
- {
- /*
- * While running Docker OS is a Linux
- */
- self::assertEquals('Linux', Miscellaneous::getOperatingSystemNameServer());
- }
-
- public function testSubstringToWord()
- {
- $suffix = '...';
-
- self::assertEquals('Lorem ipsum' . $suffix, Miscellaneous::substringToWord($this->stringCommaSeparated, 20));
- self::assertEquals('Lorem ipsum dolor sit' . $suffix, Miscellaneous::substringToWord($this->stringCommaSeparated, 25));
-
- self::assertEquals('Lorem ipsum dolor', Miscellaneous::substringToWord($this->stringCommaSeparated, 20, ''));
- self::assertEquals('Lorem ipsum dolor sit amet, consectetur', Miscellaneous::substringToWord($this->stringCommaSeparated, 40, ''));
- }
-
- public function testBreakLongText()
- {
- self::assertEquals('Lorem ipsum dolor sit
amet, consectetur
adipiscing
elit', Miscellaneous::breakLongText($this->stringCommaSeparated, 20));
- self::assertEquals('Lorem ipsum dolor sit---amet, consectetur---adipiscing---elit', Miscellaneous::breakLongText($this->stringCommaSeparated, 20, '---'));
- self::assertEquals('LoremIpsum
DolorSitAm
etConsecte
turAdipisc
ingElit', Miscellaneous::breakLongText($this->stringWithoutSpaces, 10));
- }
-
- public function testRemoveDirectoryUsingNotExistingDirectory()
- {
- self::assertNull(Miscellaneous::removeDirectory('/abc/def/ghi'));
- }
-
- public function testRemoveDirectoryUsingNoDirectory()
- {
- $directoryPath = sys_get_temp_dir() . '/ipsum.txt';
- touch($directoryPath);
- self::assertTrue(Miscellaneous::removeDirectory($directoryPath));
- }
-
- public function testRemoveDirectoryUsingSimpleDirectory()
- {
- $directoryPath = sys_get_temp_dir() . '/lorem/ipsum';
- mkdir($directoryPath, 0777, true);
- self::assertTrue(Miscellaneous::removeDirectory($directoryPath));
- }
-
- public function testRemoveDirectoryUsingComplexDirectory()
- {
- $directory1Path = sys_get_temp_dir() . '/lorem/ipsum';
- $directory2Path = sys_get_temp_dir() . '/lorem/dolor/sit';
-
- mkdir($directory1Path, 0777, true);
- mkdir($directory2Path, 0777, true);
-
- self::assertTrue(Miscellaneous::removeDirectory(sys_get_temp_dir() . '/lorem'));
- }
-
- /**
- * @param string $text Empty value, e.g. ""
- * @dataProvider provideEmptyValue
- */
- public function testRemoveStartingDirectorySeparatorEmptyValue($text)
- {
- self::assertEquals('', Miscellaneous::removeStartingDirectorySeparator($text));
- }
-
- /**
- * @param string $text Text that may contain a directory's separator at the start / beginning
- * @param string $separator The directory's separator, e.g. "/"
- * @param string $expected Text without the starting / beginning directory's separator
- *
- * @dataProvider providePathsToRemoveStartingDirectorySeparator
- */
- public function testRemoveStartingDirectorySeparator($text, $separator, $expected)
- {
- self::assertEquals($expected, Miscellaneous::removeStartingDirectorySeparator($text, $separator));
- }
-
- /**
- * @param string $text Empty value, e.g. ""
- * @dataProvider provideEmptyValue
- */
- public function testRemoveEndingDirectorySeparatorEmptyValue($text)
- {
- self::assertEquals('', Miscellaneous::removeEndingDirectorySeparator($text));
- }
-
- /**
- * @param string $text Text that may contain a directory's separator at the end
- * @param string $separator (optional) The directory's separator, e.g. "/"
- * @param string $expected Text without the ending directory's separator
- *
- * @dataProvider providePathsToRemoveEndingDirectorySeparator
- */
- public function testRemoveEndingDirectorySeparator($text, $separator, $expected)
- {
- self::assertEquals($expected, Miscellaneous::removeEndingDirectorySeparator($text, $separator));
- }
-
- public function testIsDecimal()
- {
- self::assertTrue(Miscellaneous::isDecimal(1.2));
- self::assertTrue(Miscellaneous::isDecimal('1.2'));
- self::assertFalse(Miscellaneous::isDecimal('a'));
- self::assertFalse(Miscellaneous::isDecimal(1));
- }
-
- public function testIsFilePath()
- {
- $filePath = __FILE__;
- $directoryPath = dirname($filePath);
-
- self::assertTrue(Miscellaneous::isFilePath($filePath));
- self::assertFalse(Miscellaneous::isFilePath($directoryPath));
- }
-
- /**
- * @param string $string The string to convert e.g. this-is-eXamplE (return: thisIsExample)
- * @dataProvider provideEmptyValue
- */
- public function testGetCamelCaseEmptyValue($string)
- {
- self::assertEquals('', Miscellaneous::getCamelCase($string));
- }
-
- /**
- * @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 ','
- * @param string $expected String in camel case
- *
- * @dataProvider provideStringToCamelCase
- */
- public function testGetCamelCase($string, $separator, $expected)
- {
- self::assertEquals($expected, Miscellaneous::getCamelCase($string, $separator));
- }
-
- public function testQuoteValue()
- {
- self::assertEquals(123, Miscellaneous::quoteValue(123));
- self::assertEquals('\'lorem ipsum\'', Miscellaneous::quoteValue('lorem ipsum'));
- self::assertEquals('"lorem ipsum"', Miscellaneous::quoteValue('lorem ipsum', false));
- }
-
- public function testGetHumanReadableSize()
- {
- Locale::setLocale(LC_ALL, 'en', 'US');
-
- self::assertEquals('400 B', Miscellaneous::getHumanReadableSize(400));
- self::assertEquals('1 KB', Miscellaneous::getHumanReadableSize(1024));
- self::assertEquals('1 MB', Miscellaneous::getHumanReadableSize(1024 * 1024));
- self::assertEquals('1.75 MB', Miscellaneous::getHumanReadableSize(1024 * 1024 * 1.75));
- }
-
- public function testGetLastElementOfString()
- {
- self::assertEquals('elit', Miscellaneous::getLastElementOfString($this->stringCommaSeparated, ' '));
- self::assertEquals('consectetur adipiscing elit', Miscellaneous::getLastElementOfString($this->stringCommaSeparated, ','));
- self::assertEquals(null, Miscellaneous::getLastElementOfString($this->stringCommaSeparated, ';'));
- self::assertEquals(null, Miscellaneous::getLastElementOfString($this->stringCommaSeparated, '.'));
- }
-
- public function testTrimSmart()
- {
- self::assertNull(Miscellaneous::trimSmart(null));
- self::assertEquals(' ', Miscellaneous::trimSmart(' '));
- self::assertEquals('lorem ipsum', Miscellaneous::trimSmart(' lorem ipsum'));
- self::assertEquals('lorem ipsum', Miscellaneous::trimSmart(' lorem ipsum '));
+ self::assertEquals(implode('\\', $paths2), Miscellaneous::concatenatePaths($paths2));
}
/**
@@ -517,61 +1067,214 @@ class MiscellaneousTest extends BaseTestCase
unset($paths[2]);
$imploded = implode('/', $paths);
- self::assertEquals('/' . $imploded, $concatenated);
+ self::assertEquals('/'.$imploded, $concatenated);
}
- public function testConcatenatePathsInNixOs()
+ public function testConstructor()
{
- /*
- * For *nix operating system
- */
- $paths1 = [
- 'first/directory',
- 'second/one',
- 'and/the/third',
- ];
-
- self::assertEquals('/' . implode('/', $paths1), Miscellaneous::concatenatePaths($paths1));
- self::assertEquals('/' . implode('/', $paths1), Miscellaneous::concatenatePaths($paths1[0], $paths1[1], $paths1[2]));
+ static::assertHasNoConstructor(Miscellaneous::class);
}
- public function testConcatenatePathsInWindowsOs()
+ /**
+ * @param mixed $number Number for who the "0" characters should be inserted
+ * @param int $length Wanted length of final number
+ * @param bool $before If false, 0 characters will be inserted after given number
+ * @param string $expected String with added missing the "0" characters
+ *
+ * @dataProvider provideNumberToFillMissingZeros
+ */
+ public function testFillMissingZeros($number, $length, $before, $expected): void
{
- /*
- * For Windows operating system
- */
- $paths2 = [
- 'C:\first\directory',
- 'second\one',
- 'and\the\third',
- ];
-
- self::assertEquals(implode('\\', $paths2), Miscellaneous::concatenatePaths($paths2));
+ self::assertSame($expected, Miscellaneous::fillMissingZeros($number, $length, $before));
}
- public function testIncludeFileExtension()
+ /**
+ * @param mixed $number Number for who the "0" characters should be inserted
+ * @dataProvider provideEmptyValueToFillMissingZeros
+ */
+ public function testFillMissingZerosEmptyValue($number)
{
- $fileName = 'lorem-ipsum.jpg';
-
- self::assertEquals($fileName, Miscellaneous::includeFileExtension($fileName, 'jpg'));
- self::assertEquals(sprintf('%s.%s', $fileName, 'txt'), Miscellaneous::includeFileExtension($fileName, 'txt'));
+ self::assertEquals('', Miscellaneous::fillMissingZeros($number, 1));
}
- public function testGetStringElements()
+ /**
+ * @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 ','
+ * @param string $expected String in camel case
+ *
+ * @dataProvider provideStringToCamelCase
+ */
+ public function testGetCamelCase($string, $separator, $expected)
{
- $elements = [
- 'Lorem ipsum dolor sit amet',
- ' consectetur adipiscing elit',
- ];
-
- self::assertEquals($elements, Miscellaneous::getStringElements($this->stringCommaSeparated, ','));
- self::assertEquals([], Miscellaneous::getStringElements($this->stringCommaSeparated, ';'));
+ self::assertEquals($expected, Miscellaneous::getCamelCase($string, $separator));
}
- public function testGetStringWithoutLastElement()
+ /**
+ * @param string $string The string to convert e.g. this-is-eXamplE (return: thisIsExample)
+ * @dataProvider provideEmptyValue
+ */
+ public function testGetCamelCaseEmptyValue($string)
{
- self::assertEquals('Lorem ipsum dolor sit', Miscellaneous::getStringWithoutLastElement($this->stringSmall, ' '));
- self::assertEquals('', Miscellaneous::getStringWithoutLastElement($this->stringSmall, ';'));
+ self::assertEquals('', Miscellaneous::getCamelCase($string));
+ }
+
+ public function testGetDirectoryContent()
+ {
+ $directoryPath = __DIR__.'/../';
+ $filePath = __FILE__;
+
+ self::assertNull(Miscellaneous::getDirectoryContent(null));
+ self::assertNull(Miscellaneous::getDirectoryContent(''));
+
+ self::assertGreaterThanOrEqual(0, count(Miscellaneous::getDirectoryContent($directoryPath)));
+ self::assertGreaterThanOrEqual(0, count(Miscellaneous::getDirectoryContent($directoryPath, true)));
+ self::assertGreaterThanOrEqual(0, count(Miscellaneous::getDirectoryContent($directoryPath, true, 5)));
+
+ self::assertGreaterThanOrEqual(0, count(Miscellaneous::getDirectoryContent($filePath)));
+ self::assertGreaterThanOrEqual(0, count(Miscellaneous::getDirectoryContent($filePath, true)));
+ }
+
+ public function testGetFileExtension()
+ {
+ $fileName = 'Lorem.ipsum-dolor.sit.JPG';
+ self::assertEquals('JPG', Miscellaneous::getFileExtension($fileName));
+ self::assertEquals('jpg', Miscellaneous::getFileExtension($fileName, true));
+ }
+
+ /**
+ * @param string $description Description of test
+ * @param string $path A path that contains file name
+ * @param string $expected Expected file name
+ *
+ * @dataProvider provideFilePath
+ */
+ public function testGetFileNameFromPath(string $description, string $path, string $expected): void
+ {
+ static::assertEquals($expected, Miscellaneous::getFileNameFromPath($path), $description);
+ }
+
+ /**
+ * @param string $fileName The file name with extension
+ * @param string $withoutExtension The file name without extension
+ *
+ * @dataProvider provideFileNames
+ */
+ public function testGetFileNameWithoutExtension($fileName, $withoutExtension)
+ {
+ self::assertEquals($withoutExtension, Miscellaneous::getFileNameWithoutExtension($fileName));
+ }
+
+ /**
+ * @param string $fileName Empty value, e.g. ""
+ * @dataProvider provideEmptyValue
+ */
+ public function testGetFileNameWithoutExtensionEmptyValue($fileName)
+ {
+ self::assertEquals('', Miscellaneous::getFileNameWithoutExtension($fileName));
+ }
+
+ public function testGetHumanReadableSize()
+ {
+ Locale::setLocale(LC_ALL, 'en', 'US');
+
+ self::assertEquals('400 B', Miscellaneous::getHumanReadableSize(400));
+ self::assertEquals('1 KB', Miscellaneous::getHumanReadableSize(1024));
+ self::assertEquals('1 MB', Miscellaneous::getHumanReadableSize(1024 * 1024));
+ self::assertEquals('1.75 MB', Miscellaneous::getHumanReadableSize(1024 * 1024 * 1.75));
+ }
+
+ public function testGetInvertedColor()
+ {
+ // Simple cases
+ self::assertEquals('000000', Miscellaneous::getInvertedColor('fff'));
+ self::assertEquals('ffffff', Miscellaneous::getInvertedColor('000'));
+ self::assertEquals('000000', Miscellaneous::getInvertedColor('ffffff'));
+ self::assertEquals('ffffff', Miscellaneous::getInvertedColor('000000'));
+ self::assertEquals('#000000', Miscellaneous::getInvertedColor('#ffffff'));
+ self::assertEquals('#ffffff', Miscellaneous::getInvertedColor('#000000'));
+
+ // Advanced cases - part 1
+ self::assertEquals('ffffee', Miscellaneous::getInvertedColor('001'));
+ self::assertEquals('ffeeff', Miscellaneous::getInvertedColor('010'));
+ self::assertEquals('eeffff', Miscellaneous::getInvertedColor('100'));
+ self::assertEquals('333333', Miscellaneous::getInvertedColor('ccc'));
+ self::assertEquals('333333', Miscellaneous::getInvertedColor('CCC'));
+
+ // Advanced cases - part 2
+ self::assertEquals('3e3e3e', Miscellaneous::getInvertedColor('c1c1c1'));
+ self::assertEquals('3e3e3e', Miscellaneous::getInvertedColor('C1C1C1'));
+ self::assertEquals('#dd5a01', Miscellaneous::getInvertedColor('#22a5fe'));
+ self::assertEquals('#22dbb3', Miscellaneous::getInvertedColor('#dd244c'));
+ self::assertEquals('#464646', Miscellaneous::getInvertedColor('#b9b9b9'));
+ self::assertEquals('#080808', Miscellaneous::getInvertedColor('#f7f7f7'));
+
+ // Advanced cases - verification
+ self::assertEquals('000011', Miscellaneous::getInvertedColor('ffffee'));
+ self::assertEquals('cccccc', Miscellaneous::getInvertedColor('333333'));
+ self::assertEquals('#22a5fe', Miscellaneous::getInvertedColor('#dd5a01'));
+ self::assertEquals('#22a5fe', Miscellaneous::getInvertedColor('#DD5A01'));
+ self::assertEquals('#f7f7f7', Miscellaneous::getInvertedColor('#080808'));
+ }
+
+ public function testGetInvertedColorWithIncorrectLength()
+ {
+ $this->expectException(IncorrectColorHexLengthException::class);
+
+ Miscellaneous::getInvertedColor(null);
+ Miscellaneous::getInvertedColor('');
+ Miscellaneous::getInvertedColor(1);
+ Miscellaneous::getInvertedColor(12);
+ Miscellaneous::getInvertedColor(1234567);
+ Miscellaneous::getInvertedColor('1');
+ Miscellaneous::getInvertedColor('12');
+ Miscellaneous::getInvertedColor('1234567');
+ }
+
+ public function testGetInvertedColorWithInvalidValue()
+ {
+ $this->expectException(InvalidColorHexValueException::class);
+
+ Miscellaneous::getInvertedColor('0011zz');
+ Miscellaneous::getInvertedColor('001#zz');
+ Miscellaneous::getInvertedColor('001!zz');
+ Miscellaneous::getInvertedColor('001-zz');
+ Miscellaneous::getInvertedColor('00ppqq');
+ }
+
+ /**
+ * @param string $description
+ * @param string $string
+ * @param string $separator
+ * @param string|null $expected
+ *
+ * @dataProvider provideLastElementOfString
+ */
+ public function testGetLastElementOfString(
+ string $description,
+ string $string,
+ string $separator,
+ ?string $expected
+ ): void {
+ self::assertEquals($expected, Miscellaneous::getLastElementOfString($string, $separator), $description);
+ }
+
+ public function testGetNewFileName()
+ {
+ self::assertEquals('test.jpg', Miscellaneous::getNewFileName('test.jpg', '', ''));
+ self::assertEquals('my-test.jpg', Miscellaneous::getNewFileName('test.jpg', 'my-', ''));
+ self::assertEquals('test-file.jpg', Miscellaneous::getNewFileName('test.jpg', '', '-file'));
+ self::assertEquals('my-test-file.jpg', Miscellaneous::getNewFileName('test.jpg', 'my-', '-file'));
+ }
+
+ public function testGetOperatingSystemNameServer()
+ {
+ // While running Docker OS is a Linux
+ self::assertEquals('Linux', Miscellaneous::getOperatingSystemNameServer());
+ }
+
+ public function testGetProjectRootPath(): void
+ {
+ self::assertNotEmpty(Miscellaneous::getProjectRootPath());
}
public function testGetSafelyGlobalVariable()
@@ -586,24 +1289,27 @@ class MiscellaneousTest extends BaseTestCase
self::assertEquals(123, Miscellaneous::getSafelyGlobalVariable(INPUT_GET, 'lorem'));
}
- public function testIsBetween()
- {
- /*
- * Negative cases
- */
- self::assertFalse(Miscellaneous::isBetween(0, 0, 0));
- self::assertFalse(Miscellaneous::isBetween('0', '0', '0'));
- self::assertFalse(Miscellaneous::isBetween(0, 0, 1));
- self::assertFalse(Miscellaneous::isBetween(-1, -1, -1));
- self::assertFalse(Miscellaneous::isBetween(1.2, 0.1, 1.1));
+ /**
+ * @param string $description
+ * @param string $string
+ * @param string $separator
+ * @param array $expected
+ *
+ * @dataProvider provideStringElements
+ */
+ public function testGetStringElements(
+ string $description,
+ string $string,
+ string $separator,
+ array $expected
+ ): void {
+ self::assertEquals($expected, Miscellaneous::getStringElements($string, $separator), $description);
+ }
- /*
- * Positive cases
- */
- self::assertTrue(Miscellaneous::isBetween(1, 0, 2));
- self::assertTrue(Miscellaneous::isBetween('1', '0', '2'));
- self::assertTrue(Miscellaneous::isBetween(-1, -2, 2));
- self::assertTrue(Miscellaneous::isBetween(1.1, 0.1, 1.2));
+ public function testGetStringWithoutLastElement()
+ {
+ self::assertEquals('Lorem ipsum dolor sit', Miscellaneous::getStringWithoutLastElement($this->stringSmall, ' '));
+ self::assertEquals('', Miscellaneous::getStringWithoutLastElement($this->stringSmall, ';'));
}
public function testGetType()
@@ -617,11 +1323,41 @@ class MiscellaneousTest extends BaseTestCase
self::assertEquals(__CLASS__, Miscellaneous::getType(new self()));
}
+ public function testGetUniqueFileName()
+ {
+ $originalFileName = 'Lorem.ipsum-dolor.sit.JPG';
+ $pattern = '|^lorem\-ipsum\-dolor\-sit\-[a-z0-9.-]+\.jpg$|';
+
+ // With object ID
+ $uniqueFileName1 = Miscellaneous::getUniqueFileName($originalFileName, 123);
+
+ // Without object ID
+ $uniqueFileName2 = Miscellaneous::getUniqueFileName($originalFileName);
+
+ $isCorrect1 = (bool) preg_match($pattern, $uniqueFileName1);
+ $isCorrect2 = (bool) preg_match($pattern, $uniqueFileName2);
+
+ self::assertTrue($isCorrect1);
+ self::assertTrue($isCorrect2);
+ }
+
+ public function testGetUniqueString()
+ {
+ $prefix = '';
+ $hashed = false;
+ self::assertEquals(23, strlen(Miscellaneous::getUniqueString($prefix, $hashed)));
+
+ $prefix = 'xyz';
+ $hashed = false;
+ self::assertEquals(26, strlen(Miscellaneous::getUniqueString($prefix, $hashed)));
+
+ $hashed = true;
+ self::assertEquals(40, strlen(Miscellaneous::getUniqueString($prefix, $hashed)));
+ }
+
public function testGetValidColorComponent()
{
- /*
- * Negative cases
- */
+ // Negative cases
self::assertEquals(0, Miscellaneous::getValidColorComponent(null));
self::assertEquals(0, Miscellaneous::getValidColorComponent(''));
self::assertEquals(0, Miscellaneous::getValidColorComponent('0'));
@@ -629,18 +1365,14 @@ class MiscellaneousTest extends BaseTestCase
self::assertEquals(0, Miscellaneous::getValidColorComponent(256));
self::assertEquals(0, Miscellaneous::getValidColorComponent(256, false));
- /*
- * Positive cases - part 1
- */
+ // Positive cases - part 1
self::assertEquals(1, Miscellaneous::getValidColorComponent(1));
self::assertEquals('0a', Miscellaneous::getValidColorComponent(10));
self::assertEquals('0f', Miscellaneous::getValidColorComponent(15));
self::assertEquals(64, Miscellaneous::getValidColorComponent(100));
self::assertEquals('ff', Miscellaneous::getValidColorComponent(255));
- /*
- * Positive cases - part 2
- */
+ // Positive cases - part 2
self::assertEquals(1, Miscellaneous::getValidColorComponent(1, false));
self::assertEquals(10, Miscellaneous::getValidColorComponent(10, false));
self::assertEquals(15, Miscellaneous::getValidColorComponent(15, false));
@@ -648,829 +1380,344 @@ class MiscellaneousTest extends BaseTestCase
self::assertEquals(255, Miscellaneous::getValidColorComponent(255, false));
}
- public function testGetInvertedColorWithIncorrectLength()
+ public function testIncludeFileExtension()
{
- $this->setExpectedException(IncorrectColorHexLengthException::class);
+ $fileName = 'lorem-ipsum.jpg';
- Miscellaneous::getInvertedColor(null);
- Miscellaneous::getInvertedColor('');
- Miscellaneous::getInvertedColor(1);
- Miscellaneous::getInvertedColor(12);
- Miscellaneous::getInvertedColor(1234567);
- Miscellaneous::getInvertedColor('1');
- Miscellaneous::getInvertedColor('12');
- Miscellaneous::getInvertedColor('1234567');
+ self::assertEquals($fileName, Miscellaneous::includeFileExtension($fileName, 'jpg'));
+ self::assertEquals(sprintf('%s.%s', $fileName, 'txt'), Miscellaneous::includeFileExtension($fileName, 'txt'));
}
- public function testGetInvertedColorWithInvalidValue()
+ public function testIsBetween()
{
- $this->setExpectedException(InvalidColorHexValueException::class);
+ // Negative cases
+ self::assertFalse(Miscellaneous::isBetween(0, 0, 0));
+ self::assertFalse(Miscellaneous::isBetween('0', '0', '0'));
+ self::assertFalse(Miscellaneous::isBetween(0, 0, 1));
+ self::assertFalse(Miscellaneous::isBetween(-1, -1, -1));
+ self::assertFalse(Miscellaneous::isBetween(1.2, 0.1, 1.1));
- Miscellaneous::getInvertedColor('0011zz');
- Miscellaneous::getInvertedColor('001#zz');
- Miscellaneous::getInvertedColor('001!zz');
- Miscellaneous::getInvertedColor('001-zz');
- Miscellaneous::getInvertedColor('00ppqq');
+ // Positive cases
+ self::assertTrue(Miscellaneous::isBetween(1, 0, 2));
+ self::assertTrue(Miscellaneous::isBetween('1', '0', '2'));
+ self::assertTrue(Miscellaneous::isBetween(-1, -2, 2));
+ self::assertTrue(Miscellaneous::isBetween(1.1, 0.1, 1.2));
}
- public function testGetInvertedColor()
+ public function testIsDecimal()
{
- /*
- * Simple cases
- */
- self::assertEquals('000000', Miscellaneous::getInvertedColor('fff'));
- self::assertEquals('ffffff', Miscellaneous::getInvertedColor('000'));
- self::assertEquals('000000', Miscellaneous::getInvertedColor('ffffff'));
- self::assertEquals('ffffff', Miscellaneous::getInvertedColor('000000'));
- self::assertEquals('#000000', Miscellaneous::getInvertedColor('#ffffff'));
- self::assertEquals('#ffffff', Miscellaneous::getInvertedColor('#000000'));
+ self::assertTrue(Miscellaneous::isDecimal(1.2));
+ self::assertTrue(Miscellaneous::isDecimal('1.2'));
+ self::assertFalse(Miscellaneous::isDecimal('a'));
+ self::assertFalse(Miscellaneous::isDecimal(1));
+ }
- /*
- * Advanced cases - part 1
- */
- self::assertEquals('ffffee', Miscellaneous::getInvertedColor('001'));
- self::assertEquals('ffeeff', Miscellaneous::getInvertedColor('010'));
- self::assertEquals('eeffff', Miscellaneous::getInvertedColor('100'));
- self::assertEquals('333333', Miscellaneous::getInvertedColor('ccc'));
- self::assertEquals('333333', Miscellaneous::getInvertedColor('CCC'));
+ public function testIsFilePath()
+ {
+ $filePath = __FILE__;
+ $directoryPath = dirname($filePath);
- /*
- * Advanced cases - part 2
- */
- self::assertEquals('3e3e3e', Miscellaneous::getInvertedColor('c1c1c1'));
- self::assertEquals('3e3e3e', Miscellaneous::getInvertedColor('C1C1C1'));
- self::assertEquals('#dd5a01', Miscellaneous::getInvertedColor('#22a5fe'));
- self::assertEquals('#22dbb3', Miscellaneous::getInvertedColor('#dd244c'));
- self::assertEquals('#464646', Miscellaneous::getInvertedColor('#b9b9b9'));
- self::assertEquals('#080808', Miscellaneous::getInvertedColor('#f7f7f7'));
+ self::assertTrue(Miscellaneous::isFilePath($filePath));
+ self::assertFalse(Miscellaneous::isFilePath($directoryPath));
+ }
- /*
- * Advanced cases - verification
- */
- self::assertEquals('000011', Miscellaneous::getInvertedColor('ffffee'));
- self::assertEquals('cccccc', Miscellaneous::getInvertedColor('333333'));
- self::assertEquals('#22a5fe', Miscellaneous::getInvertedColor('#dd5a01'));
- self::assertEquals('#22a5fe', Miscellaneous::getInvertedColor('#DD5A01'));
- self::assertEquals('#f7f7f7', Miscellaneous::getInvertedColor('#080808'));
+ public function testIsPhpModuleLoaded()
+ {
+ $loadedExtensions = get_loaded_extensions();
+ $firstExtension = $loadedExtensions[0];
+
+ self::assertTrue(Miscellaneous::isPhpModuleLoaded($firstExtension));
+ self::assertFalse(Miscellaneous::isPhpModuleLoaded('xyz123'));
+ }
+
+ public function testLowercaseFirst()
+ {
+ self::assertEquals('', Miscellaneous::lowercaseFirst(''));
+ self::assertEquals('', Miscellaneous::lowercaseFirst(null));
+ self::assertEquals('', Miscellaneous::lowercaseFirst(false));
+
+ $text = 'LorEM ipsum dolor sit Amet';
+ self::assertEquals('lorEM ipsum dolor sit Amet', Miscellaneous::lowercaseFirst($text));
+
+ $restLowercase = true;
+ self::assertEquals('lorem ipsum dolor sit amet', Miscellaneous::lowercaseFirst($text, $restLowercase));
+
+ $restLowercase = false;
+ self::assertEquals('lOREM IPSUM DOLOR SIT AMET', Miscellaneous::lowercaseFirst($text, $restLowercase));
+ }
+
+ public function testQuoteValue()
+ {
+ self::assertEquals(123, Miscellaneous::quoteValue(123));
+ self::assertEquals('\'lorem ipsum\'', Miscellaneous::quoteValue('lorem ipsum'));
+ self::assertEquals('"lorem ipsum"', Miscellaneous::quoteValue('lorem ipsum', false));
+ }
+
+ public function testRemoveDirectoryUsingComplexDirectory()
+ {
+ $directory1Path = sys_get_temp_dir().'/lorem/ipsum';
+ $directory2Path = sys_get_temp_dir().'/lorem/dolor/sit';
+
+ // Directory does not exist? Let's create it
+ // Required to avoid test failure
+ if (!file_exists($directory1Path)) {
+ mkdir($directory1Path, 0777, true);
+ }
+
+ // Directory does not exist? Let's create it
+ // Required to avoid test failure
+ if (!file_exists($directory2Path)) {
+ mkdir($directory2Path, 0777, true);
+ }
+
+ self::assertTrue(Miscellaneous::removeDirectory(sys_get_temp_dir().'/lorem'));
+ }
+
+ public function testRemoveDirectoryUsingNoDirectory()
+ {
+ $directoryPath = sys_get_temp_dir().'/ipsum.txt';
+ touch($directoryPath);
+ self::assertTrue(Miscellaneous::removeDirectory($directoryPath));
+ }
+
+ public function testRemoveDirectoryUsingNotExistingDirectory()
+ {
+ self::assertNull(Miscellaneous::removeDirectory('/abc/def/ghi'));
+ }
+
+ public function testRemoveDirectoryUsingSimpleDirectory()
+ {
+ $directoryPath = sys_get_temp_dir().'/lorem/ipsum';
+ mkdir($directoryPath, 0777, true);
+ self::assertTrue(Miscellaneous::removeDirectory($directoryPath));
}
/**
- * @param mixed $number Number for who the "0" characters should be inserted
- * @dataProvider provideEmptyValueToFillMissingZeros
- */
- public function testFillMissingZerosEmptyValue($number)
- {
- self::assertEquals('', Miscellaneous::fillMissingZeros($number, 1));
- }
-
- /**
- * @param mixed $number Number for who the "0" characters should be inserted
- * @param int $length Wanted length of final number
- * @param bool $before If false, 0 characters will be inserted after given number
- * @param string $expected String with added missing the "0" characters
+ * @param string $text Text that may contain a directory's separator at the end
+ * @param string $separator (optional) The directory's separator, e.g. "/"
+ * @param string $expected Text without the ending directory's separator
*
- * @dataProvider provideNumberToFillMissingZeros
+ * @dataProvider providePathsToRemoveEndingDirectorySeparator
*/
- public function testFillMissingZeros($number, $length, $before, $expected)
+ public function testRemoveEndingDirectorySeparator($text, $separator, $expected)
{
- self::assertSame($expected, Miscellaneous::fillMissingZeros($number, $length, $before));
- }
-
- public function testGetProjectRootPath()
- {
- self::assertNotEmpty(Miscellaneous::getProjectRootPath());
+ self::assertEquals($expected, Miscellaneous::removeEndingDirectorySeparator($text, $separator));
}
/**
- * Provides string to convert characters to latin characters and not lower cased and not human-readable
- *
- * @return Generator
+ * @param string $text Empty value, e.g. ""
+ * @dataProvider provideEmptyValue
*/
- public function provideStringToLatinNotLowerCaseHuman()
+ public function testRemoveEndingDirectorySeparatorEmptyValue($text)
{
- yield[
- 'asuo',
- 'ąśüö',
- ];
-
- yield[
- 'eoaslzzcn',
- 'ęóąśłżźćń',
- ];
-
- yield[
- 'loremipsum',
- 'loremipsum',
- ];
-
- yield[
- 'LoremIpsum',
- 'LoremIpsum',
- ];
-
- yield[
- 'Lorem.Ipsum',
- 'Lorem Ipsum',
- '.',
- ];
-
- yield[
- 'Lorem.Ipsum',
- 'Lorem=Ipsum',
- '.',
- ];
-
- yield[
- 'LoremIpsumD',
- 'LoremIpsumD',
- ];
-
- yield[
- 'LoremIpsumD',
- 'LoremIpsumD',
- '.',
- ];
-
- yield[
- 'lorem-ipsum',
- 'lorem ipsum',
- ];
-
- yield[
- 'lorem-ipsum',
- 'lorem;ipsum',
- ];
-
- yield[
- 'lorem1ipsum2',
- 'lorem1ipsum2',
- ];
-
- yield[
- 'lorem_ipsum',
- 'lorem ipsum',
- '_',
- ];
-
- yield[
- 'LoremIpsum',
- 'LoremIpsum',
- ];
-
- yield[
- 'Lorem Ipsum',
- 'Lorem!Ipsum',
- ' ',
- ];
-
- yield[
- 'Lorem Ipsum',
- 'Lorem.Ipsum',
- ' ',
- ];
-
- yield[
- 'Lorem|Ipsum',
- 'Lorem.Ipsum',
- '|',
- ];
+ self::assertEquals('', Miscellaneous::removeEndingDirectorySeparator($text));
}
/**
- * Provides string to convert characters to latin characters and lower cased and human-readable
+ * @param string $description Description of test case
+ * @param string $string The string which should be shortened
+ * @param bool $last (optional) If is set to true, last element is removed (default behaviour).
+ * Otherwise - first.
+ * @param null|string $expected Expected result
*
- * @return Generator
+ * @dataProvider provideStringToRemoveMarginalCharacter
*/
- public function provideStringToLatinLowerCaseHuman()
- {
- yield[
- 'asuo',
- 'ąśüö',
- ];
-
- yield[
- 'eoaslzzcn',
- 'ęóąśłżźćń',
- ];
-
- yield[
- 'loremipsum',
- 'loremipsum',
- ];
-
- yield[
- 'lorem-ipsum',
- 'lorem ipsum',
- ];
-
- yield[
- 'lorem-ipsum',
- 'lorem;ipsum',
- ];
-
- yield[
- 'lorem1ipsum2',
- 'lorem1ipsum2',
- ];
-
- yield[
- 'lorem_ipsum',
- 'lorem ipsum',
- '_',
- ];
-
- yield[
- 'lorem-ipsum',
- 'lorem-ipsum',
- ];
-
- yield[
- 'lorem ipsum',
- 'Lorem!Ipsum',
- ' ',
- ];
-
- yield[
- 'lorem ipsum',
- 'Lorem.Ipsum',
- ' ',
- ];
-
- yield[
- 'lorem|ipsum',
- 'Lorem.Ipsum',
- '|',
- ];
-
- yield[
- 'lorem-ipsum',
- 'LoremIpsum',
- ];
-
- yield[
- 'lorem.ipsum',
- 'Lorem Ipsum',
- '.',
- ];
-
- yield[
- 'lorem.ipsum',
- 'Lorem=Ipsum',
- '.',
- ];
-
- yield[
- 'lorem-ipsum-d',
- 'LoremIpsumD',
- ];
-
- yield[
- 'lorem.ipsum.d',
- 'LoremIpsumD',
- '.',
- ];
+ public function testRemoveMarginalCharacter(
+ string $description,
+ string $string,
+ bool $last,
+ ?string $expected
+ ): void {
+ self::assertEquals($expected, Miscellaneous::removeMarginalCharacter($string, $last), $description);
}
/**
- * Provides names of files
+ * @param string $text Text that may contain a directory's separator at the start / beginning
+ * @param string $separator The directory's separator, e.g. "/"
+ * @param string $expected Text without the starting / beginning directory's separator
*
- * @return Generator
+ * @dataProvider providePathsToRemoveStartingDirectorySeparator
*/
- public function provideFileNames()
+ public function testRemoveStartingDirectorySeparator($text, $separator, $expected)
{
- yield[
- 'Lorem.ipsum-dolor.sit.JPG',
- 'Lorem.ipsum-dolor.sit',
- ];
-
- yield[
- 'lets-test.doc',
- 'lets-test',
- ];
-
- yield[
- 'something/else.txt',
- 'something/else',
- ];
-
- yield[
- 'public/js/user.js',
- 'public/js/user',
- ];
+ self::assertEquals($expected, Miscellaneous::removeStartingDirectorySeparator($text, $separator));
}
/**
- * Provides string to convert to camel case
- *
- * @return Generator
+ * @param string $text Empty value, e.g. ""
+ * @dataProvider provideEmptyValue
*/
- public function provideStringToCamelCase()
+ public function testRemoveStartingDirectorySeparatorEmptyValue($text)
{
- yield[
- 'lorem ipsum',
- ' ',
- 'loremIpsum',
- ];
-
- yield[
- 'Lorem ipSum Dolor',
- ' ',
- 'loremIpsumDolor',
- ];
-
- yield[
- 'abc;def;ghi',
- ';',
- 'abcDefGhi',
- ];
+ self::assertEquals('', Miscellaneous::removeStartingDirectorySeparator($text));
}
/**
- * Provides path used to remove the starting / beginning directory's separator
- *
- * @return Generator
+ * @param array|string $search An empty value to find
+ * @dataProvider provideEmptyValue
*/
- public function providePathsToRemoveStartingDirectorySeparator()
+ public function testReplaceEmptyValue($search)
{
- yield[
- '/lorem/ipsum/dolor',
- '/',
- 'lorem/ipsum/dolor',
+ $replacement1 = '';
+ $replacement2 = [];
+
+ $replacement3 = [
+ 'commodo',
+ 'interdum',
];
- yield[
- 'lorem/ipsum/dolor',
- '/',
- 'lorem/ipsum/dolor',
- ];
+ self::assertEquals($this->stringSmall, Miscellaneous::replace($this->stringSmall, $search, $replacement1));
+ self::assertEquals($this->stringSmall, Miscellaneous::replace($this->stringSmall, $search, $replacement2));
+ self::assertEquals($this->stringSmall, Miscellaneous::replace($this->stringSmall, $search, $replacement3));
- yield[
- '\\lorem\ipsum\dolor',
- '\\',
- 'lorem\ipsum\dolor',
- ];
-
- yield[
- 'lorem\ipsum\dolor',
- '\\',
- 'lorem\ipsum\dolor',
- ];
-
- yield[
- ';lorem;ipsum;dolor',
- ';',
- 'lorem;ipsum;dolor',
- ];
-
- yield[
- 'lorem;ipsum;dolor',
- ';',
- 'lorem;ipsum;dolor',
- ];
+ self::assertEquals($this->stringSmall, Miscellaneous::replace($this->stringSmall, $search, $replacement1, true));
+ self::assertEquals($this->stringSmall, Miscellaneous::replace($this->stringSmall, $search, $replacement2, true));
+ self::assertEquals($this->stringSmall, Miscellaneous::replace($this->stringSmall, $search, $replacement3, true));
}
/**
- * Provides path used to remove the ending directory's separator
+ * @param string $description Description of test
+ * @param array|string $subject The string or an array of strings to search and replace
+ * @param array|string $search String or pattern or array of patterns to find. It may be: string, an array
+ * of strings or an array of patterns.
+ * @param array|string $replacement The string or an array of strings to replace. It may be: string or an array
+ * of strings.
+ * @param mixed $result Result of replacing
*
- * @return Generator
+ * @dataProvider provideEmptyValuesToReplace
*/
- public function providePathsToRemoveEndingDirectorySeparator()
+ public function testReplaceUsingEmptyValues($description, $subject, $search, $replacement, $result)
{
- yield[
- 'lorem/ipsum/dolor/',
- '/',
- 'lorem/ipsum/dolor',
- ];
-
- yield[
- 'lorem/ipsum/dolor',
- '/',
- 'lorem/ipsum/dolor',
- ];
-
- yield[
- 'lorem\ipsum\dolor\\',
- '\\',
- 'lorem\ipsum\dolor',
- ];
-
- yield[
- 'lorem\ipsum\dolor',
- '\\',
- 'lorem\ipsum\dolor',
- ];
-
- yield[
- 'lorem;ipsum;dolor;',
- ';',
- 'lorem;ipsum;dolor',
- ];
-
- yield[
- 'lorem;ipsum;dolor',
- ';',
- 'lorem;ipsum;dolor',
- ];
+ static::assertSame($result, Miscellaneous::replace($subject, $search, $replacement), $description);
}
/**
- * Provides empty value used to fill missing zeros
+ * @param string $description Description of test
+ * @param string $subject The string or an array of strings to search and replace
+ * @param string $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 $replacement The string or an array of strings to replace. It may be: string or an array of
+ * strings.
+ * @param mixed $result Result of replacing
*
- * @return Generator
+ * @dataProvider provideRegexToReplace
*/
- public function provideEmptyValueToFillMissingZeros()
+ public function testReplaceUsingRegex($description, $subject, $search, $replacement, $result)
{
- yield[''];
- yield[' '];
- yield[null];
- yield[false];
- yield[[]];
+ static::assertSame($result, Miscellaneous::replace($subject, $search, $replacement), $description);
}
/**
- * Provides number used to fill missing zeros
+ * @param string $description Description of test
+ * @param string $subject The string or an array of strings to search and replace
+ * @param string $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 $replacement The string or an array of strings to replace. It may be: string or an array of
+ * strings.
+ * @param mixed $result Result of replacing
*
- * @return Generator
+ * @dataProvider provideStringsToReplace
*/
- public function provideNumberToFillMissingZeros()
+ public function testReplaceUsingStrings($description, $subject, $search, $replacement, $result)
{
- yield[
- 0,
- 0,
- true,
- '0',
- ];
-
- yield[
- 0,
- 0,
- false,
- '0',
- ];
-
- yield[
- 1,
- 0,
- true,
- '1',
- ];
-
- yield[
- 1,
- 0,
- false,
- '1',
- ];
-
- yield[
- 1,
- 1,
- true,
- '1',
- ];
-
- yield[
- 1,
- 1,
- false,
- '1',
- ];
-
- yield[
- 123,
- 5,
- true,
- '00123',
- ];
-
- yield[
- 123,
- 5,
- false,
- '12300',
- ];
+ static::assertSame($result, Miscellaneous::replace($subject, $search, $replacement), $description);
}
- public function provideEmptyValuesToReplace()
+ /**
+ * @param string $description Description of test
+ * @param string $subject The string or an array of strings to search and replace
+ * @param string $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 $replacement The string or an array of strings to replace. It may be: string or an array of
+ * strings.
+ * @param mixed $result Result of replacing
+ *
+ * @dataProvider provideDataToReplaceWithQuoteStrings
+ */
+ public function testReplaceWithQuoteStrings($description, $subject, $search, $replacement, $result)
{
- yield[
- 'An empty string as subject',
- '',
- 'test',
- 'another test',
- '',
- ];
-
- yield[
- 'An empty array as subject',
- [],
- 'test',
- 'another test',
- [],
- ];
-
- yield[
- 'Null as subject',
- null,
- 'test',
- 'another test',
- null,
- ];
-
- yield[
- 'An empty string to search',
- 'test',
- '',
- 'another test',
- 'test',
- ];
-
- yield[
- 'An empty array to search',
- 'test',
- [],
- 'another test',
- 'test',
- ];
-
- yield[
- 'Null to search',
- 'test',
- null,
- 'another test',
- 'test',
- ];
-
- yield[
- 'An empty string as replacement',
- 'test',
- 'another test',
- '',
- 'test',
- ];
-
- yield[
- 'An empty array as replacement',
- 'test',
- 'another test',
- [],
- 'test',
- ];
-
- yield[
- 'Null as replacement',
- 'test',
- 'another test',
- null,
- 'test',
- ];
+ static::assertSame($result, Miscellaneous::replace($subject, $search, $replacement, true), $description);
}
- public function provideStringsToReplace()
+ public function testSubstringToWord()
{
- yield[
- 'Different count of strings to search and replace - 1st part',
- 'Lorem ipsum dolor sit amet',
- [
- 'ipsum',
- ],
- 'commodo',
- 'Lorem ipsum dolor sit amet',
- ];
+ $suffix = '...';
- yield[
- 'Different count of strings to search and replace - 2nd part',
- 'Lorem ipsum dolor sit amet',
- 'ipsum',
- [
- 'commodo',
- ],
- 'Lorem commodo dolor sit amet',
- ];
+ self::assertEquals('Lorem ipsum'.$suffix, Miscellaneous::substringToWord($this->stringCommaSeparated, 20));
+ self::assertEquals('Lorem ipsum dolor sit'.$suffix, Miscellaneous::substringToWord($this->stringCommaSeparated, 25));
- yield[
- 'Replace 1 not existing word in 1 sentence (nothing to replace)',
- 'Lorem ipsum dolor sit amet',
- 'plum',
- 'commodo',
- 'Lorem ipsum dolor sit amet',
- ];
-
- yield[
- 'Replace 1 word in 1 sentence',
- 'Lorem ipsum dolor sit amet',
- 'ipsum',
- 'commodo',
- 'Lorem commodo dolor sit amet',
- ];
-
- yield[
- 'Replace 1 not existing word in 2 sentences (nothing to replace)',
- [
- 'Lorem ipsum dolor sit amet',
- 'Maecenas sed diam eget risus varius blandit sit amet',
- ],
- 'plum',
- 'commodo',
- [
- 'Lorem ipsum dolor sit amet',
- 'Maecenas sed diam eget risus varius blandit sit amet',
- ],
- ];
-
- yield[
- 'Replace 1 word in 2 sentences',
- [
- 'Lorem ipsum dolor sit amet',
- 'Maecenas sed diam eget risus varius blandit sit amet',
- ],
- 'amet',
- 'commodo',
- [
- 'Lorem ipsum dolor sit commodo',
- 'Maecenas sed diam eget risus varius blandit sit commodo',
- ],
- ];
+ self::assertEquals('Lorem ipsum dolor', Miscellaneous::substringToWord($this->stringCommaSeparated, 20, ''));
+ self::assertEquals('Lorem ipsum dolor sit amet, consectetur', Miscellaneous::substringToWord($this->stringCommaSeparated, 40, ''));
}
- public function provideRegexToReplace()
+ /**
+ * @param mixed $string Empty value, e.g. ""
+ * @dataProvider provideEmptyValue
+ */
+ public function testToLatinEmptyValue($string)
{
- yield[
- 'Different count of strings to search and replace - 1st part',
- 'Lorem ipsum dolor sit amet',
- [
- '|ipsum|',
- ],
- 'commodo',
- 'Lorem ipsum dolor sit amet',
- ];
-
- yield[
- 'Different count of strings to search and replace - 2nd part',
- 'Lorem ipsum dolor sit amet',
- '|ipsum|',
- [
- 'commodo',
- ],
- 'Lorem ipsum dolor sit amet',
- ];
-
- yield[
- '1 pattern (word -> "")',
- 'Lorem ipsum dolor sit amet',
- '|ipsum|',
- '',
- 'Lorem dolor sit amet',
- ];
-
- yield[
- '1 pattern (word -> word)',
- 'Lorem ipsum dolor sit amet',
- '|ipsum|',
- 'commodo',
- 'Lorem commodo dolor sit amet',
- ];
-
- yield[
- '2 patterns (word -> word)',
- 'Lorem ipsum dolor sit amet',
- [
- '|ipsum|',
- '|amet|',
- ],
- [
- 'commodo',
- 'egestas',
- ],
- 'Lorem commodo dolor sit egestas',
- ];
-
- yield[
- '1 word in 2 sentences',
- [
- 'Lorem ipsum dolor sit amet',
- 'Maecenas sed diam eget risus varius blandit sit amet',
- ],
- '|amet|',
- 'commodo',
- [
- 'Lorem ipsum dolor sit commodo',
- 'Maecenas sed diam eget risus varius blandit sit commodo',
- ],
- ];
-
- yield[
- '2 words in 2 sentences',
- [
- 'Lorem ipsum dolor sit amet',
- 'Maecenas sed diam eget risus varius blandit sit amet',
- ],
- [
- '|ipsum|',
- '|amet|',
- ],
- [
- 'commodo',
- 'egestas',
- ],
- [
- 'Lorem commodo dolor sit egestas',
- 'Maecenas sed diam eget risus varius blandit sit egestas',
- ],
- ];
+ self::assertEquals('', Miscellaneous::toLatin($string));
}
- public function provideDataToReplaceWithQuoteStrings()
+ /**
+ * @param string $expected Expected/converted string
+ * @param string $string String to convert
+ * @param string $replacementChar (optional) Replacement character for all non-latin characters
+ *
+ * @dataProvider provideStringToLatinLowerCaseHuman
+ */
+ public function testToLatinLowerCaseHuman($expected, $string, $replacementChar = '-')
{
- yield[
- 'An empty string as subject',
- '',
- 'test',
- 'another test',
- '',
- ];
+ self::assertEquals($expected, Miscellaneous::toLatin($string, true, $replacementChar));
+ }
- yield[
- 'An empty string to search',
- 'test',
- '',
- 'another test',
- 'test',
- ];
+ /**
+ * @param string $expected Expected/converted string
+ * @param string $string String to convert
+ * @param string $replacementChar (optional) Replacement character for all non-latin characters
+ *
+ * @dataProvider provideStringToLatinNotLowerCaseHuman
+ */
+ public function testToLatinNotLowerCaseHuman($expected, $string, $replacementChar = '-')
+ {
+ self::assertEquals($expected, Miscellaneous::toLatin($string, false, $replacementChar));
+ }
- yield[
- 'An empty string as replacement',
- 'test',
- 'another test',
- '',
- 'test',
- ];
+ public function testTrimSmart()
+ {
+ self::assertNull(Miscellaneous::trimSmart(null));
+ self::assertEquals(' ', Miscellaneous::trimSmart(' '));
+ self::assertEquals('lorem ipsum', Miscellaneous::trimSmart(' lorem ipsum'));
+ self::assertEquals('lorem ipsum', Miscellaneous::trimSmart(' lorem ipsum '));
+ }
- yield[
- 'Replace 1 not existing word in 1 sentence (nothing to replace)',
- 'Lorem ipsum dolor sit amet',
- 'plum',
- 'commodo',
- 'Lorem ipsum dolor sit amet',
- ];
+ public function testUppercaseFirst()
+ {
+ self::assertEquals('', Miscellaneous::uppercaseFirst(''));
+ self::assertEquals('', Miscellaneous::uppercaseFirst(null));
+ self::assertEquals('', Miscellaneous::uppercaseFirst(false));
- yield[
- 'Replace 1 word in 1 sentence',
- 'Lorem ipsum dolor sit amet',
- 'ipsum',
- 'commodo',
- 'Lorem \'commodo\' dolor sit amet',
- ];
+ $text = 'lorEM ipsum dolor sit Amet';
+ self::assertEquals('LorEM ipsum dolor sit Amet', Miscellaneous::uppercaseFirst($text));
- yield[
- 'Replace 1 word in 2 sentences',
- [
- 'Lorem ipsum dolor sit amet',
- 'Maecenas sed diam eget risus varius blandit sit amet',
- ],
- 'amet',
- 'commodo',
- [
- 'Lorem ipsum dolor sit \'commodo\'',
- 'Maecenas sed diam eget risus varius blandit sit \'commodo\'',
- ],
- ];
+ $restLowercase = true;
+ self::assertEquals('Lorem ipsum dolor sit amet', Miscellaneous::uppercaseFirst($text, $restLowercase));
- yield[
- '1 pattern (word -> "")',
- 'Lorem ipsum dolor sit amet',
- '|ipsum|',
- '',
- 'Lorem \'\' dolor sit amet',
- ];
+ $restLowercase = false;
+ self::assertEquals('LOREM IPSUM DOLOR SIT AMET', Miscellaneous::uppercaseFirst($text, $restLowercase));
+ }
- yield[
- '1 pattern (word -> word)',
- 'Lorem ipsum dolor sit amet',
- '|ipsum|',
- 'commodo',
- 'Lorem \'commodo\' dolor sit amet',
- ];
-
- yield[
- '2 patterns (word -> word)',
- 'Lorem ipsum dolor sit amet',
- [
- '|ipsum|',
- '|amet|',
- ],
- [
- 'commodo',
- 'egestas',
- ],
- 'Lorem \'commodo\' dolor sit \'egestas\'',
- ];
+ public function testValue2NonNegativeInteger()
+ {
+ self::assertEquals(2, Miscellaneous::value2NonNegativeInteger('2'));
+ self::assertEquals(0, Miscellaneous::value2NonNegativeInteger('a'));
+ self::assertEquals('-', Miscellaneous::value2NonNegativeInteger('-4', '-'));
}
/**
* {@inheritdoc}
*/
- protected function setUp()
+ protected function setUp(): void
{
parent::setUp();
@@ -1483,7 +1730,7 @@ class MiscellaneousTest extends BaseTestCase
/**
* {@inheritdoc}
*/
- protected function tearDown()
+ protected function tearDown(): void
{
parent::tearDown();
unset($this->stringSmall, $this->stringCommaSeparated, $this->stringDotSeparated, $this->stringWithoutSpaces);
diff --git a/tests/Utilities/QueryBuilderUtilityTest.php b/tests/Utilities/QueryBuilderUtilityTest.php
index 0451ef8..2b59e6a 100644
--- a/tests/Utilities/QueryBuilderUtilityTest.php
+++ b/tests/Utilities/QueryBuilderUtilityTest.php
@@ -17,237 +17,19 @@ use Doctrine\ORM\QueryBuilder;
use Generator;
use Meritoo\Common\Test\Base\BaseTestCase;
use Meritoo\Common\Utilities\QueryBuilderUtility;
+use stdClass;
/**
* Test case of the useful methods for query builder (the Doctrine's QueryBuilder class)
*
* @author Meritoo
* @copyright Meritoo
+ *
+ * @internal
+ * @covers \Meritoo\Common\Utilities\QueryBuilderUtility
*/
class QueryBuilderUtilityTest extends BaseTestCase
{
- public function testConstructor()
- {
- static::assertHasNoConstructor(QueryBuilderUtility::class);
- }
-
- /**
- * @param QueryBuilder $queryBuilder The query builder to retrieve root alias
- * @param null|string $rootAlias Expected root alias of given query builder
- *
- * @dataProvider provideQueryBuilderAndRootAlias
- */
- public function testGetRootAlias(QueryBuilder $queryBuilder, $rootAlias)
- {
- static::assertSame($rootAlias, QueryBuilderUtility::getRootAlias($queryBuilder));
- }
-
- /**
- * @param QueryBuilder $queryBuilder The query builder to verify
- * @param string $propertyName Name of property that maybe is joined
- * @param null|string $propertyAlias Expected alias of given property joined in given query builder
- *
- * @dataProvider provideQueryBuilderAndPropertyAlias
- */
- public function testGetJoinedPropertyAlias(QueryBuilder $queryBuilder, $propertyName, $propertyAlias)
- {
- static::assertSame($propertyAlias, QueryBuilderUtility::getJoinedPropertyAlias($queryBuilder, $propertyName));
- }
-
- public function testSetCriteriaWithoutCriteria()
- {
- $entityManager = $this->getMock(EntityManagerInterface::class);
- $queryBuilder = new QueryBuilder($entityManager);
- $newQueryBuilder = QueryBuilderUtility::setCriteria($queryBuilder);
-
- static::assertSame($queryBuilder, $newQueryBuilder);
- static::assertCount(0, $newQueryBuilder->getParameters());
- static::assertNull($newQueryBuilder->getDQLPart('where'));
- }
-
- public function testSetCriteriaWithoutAlias()
- {
- $criteria = [
- 'lorem' => 11,
- 'ipsum' => 22,
- ];
-
- $entityManager = $this->getMock(EntityManagerInterface::class);
- $queryBuilder = new QueryBuilder($entityManager);
- $newQueryBuilder = QueryBuilderUtility::setCriteria($queryBuilder, $criteria);
-
- static::assertSame($queryBuilder, $newQueryBuilder);
- static::assertCount(count($criteria), $newQueryBuilder->getParameters());
- static::assertNotNull($newQueryBuilder->getDQLPart('where'));
- }
-
- /**
- * @param QueryBuilder $queryBuilder The query builder
- * @param array $criteria The criteria used in WHERE clause
- *
- * @dataProvider provideQueryBuilderAndCriteria
- */
- public function testSetCriteria(QueryBuilder $queryBuilder, array $criteria)
- {
- $newQueryBuilder = QueryBuilderUtility::setCriteria($queryBuilder, $criteria);
- $criteriaCount = count($criteria);
- $nullsCount = 0;
-
- /*
- * I have to verify count/amount of NULLs and decrease $criteriaCount, because for null parameter is not added
- */
- array_walk($criteria, function ($value) use (&$nullsCount) {
- if (null === $value) {
- ++$nullsCount;
- }
- });
-
- static::assertSame($queryBuilder, $newQueryBuilder);
- static::assertCount($criteriaCount - $nullsCount, $newQueryBuilder->getParameters());
- static::assertNotNull($newQueryBuilder->getDQLPart('where'));
- }
-
- public function testDeleteEntitiesWithoutFlush()
- {
- $methods = [
- 'remove',
- 'flush',
- ];
-
- $entityManager = $this->getMock(EntityManager::class, $methods, [], '', false);
- $entities1 = [];
-
- $entities2 = [
- new \stdClass(),
- ];
-
- static::assertFalse(QueryBuilderUtility::deleteEntities($entityManager, $entities1, false));
- static::assertTrue(QueryBuilderUtility::deleteEntities($entityManager, $entities2, false));
- }
-
- public function testDeleteEntities()
- {
- $methods = [
- 'remove',
- 'flush',
- ];
-
- $entityManager = $this->getMock(EntityManager::class, $methods, [], '', false);
- $entities1 = [];
-
- $entities2 = [
- new \stdClass(),
- ];
-
- static::assertFalse(QueryBuilderUtility::deleteEntities($entityManager, $entities1));
- static::assertTrue(QueryBuilderUtility::deleteEntities($entityManager, $entities2));
- }
-
- /**
- * @param QueryBuilder $queryBuilder The query builder
- * @param array|ArrayCollection $parameters Parameters to add. Collection of Doctrine\ORM\Query\Parameter
- * instances or an array with key-value pairs.
- *
- * @dataProvider provideQueryBuilderAndParameters
- */
- public function testAddParameters(QueryBuilder $queryBuilder, $parameters)
- {
- $newQueryBuilder = QueryBuilderUtility::addParameters($queryBuilder, $parameters);
-
- static::assertSame($queryBuilder, $newQueryBuilder);
- static::assertCount(count($parameters), $newQueryBuilder->getParameters());
- }
-
- /**
- * Provides query builder to retrieve root alias and expected root alias
- *
- * @return Generator
- */
- public function provideQueryBuilderAndRootAlias()
- {
- $entityManager = $this->getMock(EntityManagerInterface::class);
-
- yield[
- new QueryBuilder($entityManager),
- null,
- ];
-
- yield[
- (new QueryBuilder($entityManager))->from('lorem_ipsum', 'lm'),
- 'lm',
- ];
-
- yield[
- (new QueryBuilder($entityManager))
- ->from('lorem', 'l')
- ->leftJoin('l.ipsum', 'i'),
- 'l',
- ];
- }
-
- /**
- * Provides query builder, name of property and expected alias of given property
- *
- * @return Generator
- */
- public function provideQueryBuilderAndPropertyAlias()
- {
- $entityManager = $this->getMock(EntityManagerInterface::class);
-
- yield[
- new QueryBuilder($entityManager),
- '',
- null,
- ];
-
- yield[
- new QueryBuilder($entityManager),
- 'lorem',
- null,
- ];
-
- yield[
- (new QueryBuilder($entityManager))->from('lorem_ipsum', 'lm'),
- 'lm',
- null,
- ];
-
- yield[
- (new QueryBuilder($entityManager))
- ->from('lorem', 'l')
- ->leftJoin('l.ipsum', 'i'),
- 'ipsum',
- 'i',
- ];
-
- yield[
- (new QueryBuilder($entityManager))
- ->from('lorem', 'l')
- ->leftJoin('l.ipsum', 'i')
- ->innerJoin('i.dolor', 'd'),
- 'ipsum1',
- null,
- ];
-
- yield[
- (new QueryBuilder($entityManager))
- ->from('lorem', 'l')
- ->leftJoin('l.ipsum', 'i')
- ->innerJoin('i.dolor', 'd'),
- 'ipsum',
- 'i',
- ];
-
- yield[
- (new QueryBuilder($entityManager))
- ->from('lorem', 'l')
- ->leftJoin('l.ipsum', 'i')
- ->innerJoin('i.dolor', 'd'),
- 'dolor',
- 'd',
- ];
- }
-
/**
* Provides query builder and criteria used in WHERE clause
*
@@ -255,7 +37,11 @@ class QueryBuilderUtilityTest extends BaseTestCase
*/
public function provideQueryBuilderAndCriteria()
{
- $entityManager = $this->getMock(EntityManager::class, ['getExpressionBuilder'], [], '', false);
+ $entityManager = $this
+ ->getMockBuilder(EntityManager::class)
+ ->disableOriginalConstructor()
+ ->setMethods(['getExpressionBuilder'])
+ ->getMock();
$entityManager
->expects(static::any())
@@ -263,7 +49,7 @@ class QueryBuilderUtilityTest extends BaseTestCase
->willReturn(new Expr())
;
- yield[
+ yield [
(new QueryBuilder($entityManager))->from('lorem_ipsum', 'lm'),
[
'lorem' => 11,
@@ -272,7 +58,7 @@ class QueryBuilderUtilityTest extends BaseTestCase
],
];
- yield[
+ yield [
(new QueryBuilder($entityManager))->from('lorem_ipsum', 'lm'),
[
'lorem' => [
@@ -295,19 +81,19 @@ class QueryBuilderUtilityTest extends BaseTestCase
*/
public function provideQueryBuilderAndParameters()
{
- $entityManager = $this->getMock(EntityManagerInterface::class);
+ $entityManager = $this->createMock(EntityManagerInterface::class);
- yield[
+ yield [
new QueryBuilder($entityManager),
[],
];
- yield[
+ yield [
new QueryBuilder($entityManager),
new ArrayCollection(),
];
- yield[
+ yield [
new QueryBuilder($entityManager),
[
'lorem' => 11,
@@ -315,7 +101,7 @@ class QueryBuilderUtilityTest extends BaseTestCase
],
];
- yield[
+ yield [
new QueryBuilder($entityManager),
new ArrayCollection([
'lorem' => 11,
@@ -323,7 +109,7 @@ class QueryBuilderUtilityTest extends BaseTestCase
]),
];
- yield[
+ yield [
new QueryBuilder($entityManager),
[
new Parameter('lorem', 11),
@@ -331,7 +117,7 @@ class QueryBuilderUtilityTest extends BaseTestCase
],
];
- yield[
+ yield [
new QueryBuilder($entityManager),
new ArrayCollection([
new Parameter('lorem', 11),
@@ -339,4 +125,234 @@ class QueryBuilderUtilityTest extends BaseTestCase
]),
];
}
+
+ /**
+ * Provides query builder, name of property and expected alias of given property
+ *
+ * @return Generator
+ */
+ public function provideQueryBuilderAndPropertyAlias()
+ {
+ $entityManager = $this->createMock(EntityManagerInterface::class);
+
+ yield [
+ new QueryBuilder($entityManager),
+ '',
+ null,
+ ];
+
+ yield [
+ new QueryBuilder($entityManager),
+ 'lorem',
+ null,
+ ];
+
+ yield [
+ (new QueryBuilder($entityManager))->from('lorem_ipsum', 'lm'),
+ 'lm',
+ null,
+ ];
+
+ yield [
+ (new QueryBuilder($entityManager))
+ ->from('lorem', 'l')
+ ->leftJoin('l.ipsum', 'i'),
+ 'ipsum',
+ 'i',
+ ];
+
+ yield [
+ (new QueryBuilder($entityManager))
+ ->from('lorem', 'l')
+ ->leftJoin('l.ipsum', 'i')
+ ->innerJoin('i.dolor', 'd'),
+ 'ipsum1',
+ null,
+ ];
+
+ yield [
+ (new QueryBuilder($entityManager))
+ ->from('lorem', 'l')
+ ->leftJoin('l.ipsum', 'i')
+ ->innerJoin('i.dolor', 'd'),
+ 'ipsum',
+ 'i',
+ ];
+
+ yield [
+ (new QueryBuilder($entityManager))
+ ->from('lorem', 'l')
+ ->leftJoin('l.ipsum', 'i')
+ ->innerJoin('i.dolor', 'd'),
+ 'dolor',
+ 'd',
+ ];
+ }
+
+ /**
+ * Provides query builder to retrieve root alias and expected root alias
+ *
+ * @return Generator
+ */
+ public function provideQueryBuilderAndRootAlias()
+ {
+ $entityManager = $this->createMock(EntityManagerInterface::class);
+
+ yield [
+ new QueryBuilder($entityManager),
+ null,
+ ];
+
+ yield [
+ (new QueryBuilder($entityManager))->from('lorem_ipsum', 'lm'),
+ 'lm',
+ ];
+
+ yield [
+ (new QueryBuilder($entityManager))
+ ->from('lorem', 'l')
+ ->leftJoin('l.ipsum', 'i'),
+ 'l',
+ ];
+ }
+
+ /**
+ * @param QueryBuilder $queryBuilder The query builder
+ * @param array|ArrayCollection $parameters Parameters to add. Collection of Doctrine\ORM\Query\Parameter
+ * instances or an array with key-value pairs.
+ *
+ * @dataProvider provideQueryBuilderAndParameters
+ */
+ public function testAddParameters(QueryBuilder $queryBuilder, $parameters)
+ {
+ $newQueryBuilder = QueryBuilderUtility::addParameters($queryBuilder, $parameters);
+
+ static::assertSame($queryBuilder, $newQueryBuilder);
+ static::assertCount(count($parameters), $newQueryBuilder->getParameters());
+ }
+
+ public function testConstructor()
+ {
+ static::assertHasNoConstructor(QueryBuilderUtility::class);
+ }
+
+ public function testDeleteEntities()
+ {
+ $methods = [
+ 'remove',
+ 'flush',
+ ];
+
+ $entityManager = $this
+ ->getMockBuilder(EntityManager::class)
+ ->disableOriginalConstructor()
+ ->setMethods($methods)
+ ->getMock();
+
+ $entities1 = [];
+
+ $entities2 = [
+ new stdClass(),
+ ];
+
+ static::assertFalse(QueryBuilderUtility::deleteEntities($entityManager, $entities1));
+ static::assertTrue(QueryBuilderUtility::deleteEntities($entityManager, $entities2));
+ }
+
+ public function testDeleteEntitiesWithoutFlush()
+ {
+ $methods = [
+ 'remove',
+ 'flush',
+ ];
+
+ $entityManager = $this
+ ->getMockBuilder(EntityManager::class)
+ ->disableOriginalConstructor()
+ ->setMethods($methods)
+ ->getMock();
+
+ $entities1 = [];
+
+ $entities2 = [
+ new stdClass(),
+ ];
+
+ static::assertFalse(QueryBuilderUtility::deleteEntities($entityManager, $entities1, false));
+ static::assertTrue(QueryBuilderUtility::deleteEntities($entityManager, $entities2, false));
+ }
+
+ /**
+ * @param QueryBuilder $queryBuilder The query builder to verify
+ * @param string $propertyName Name of property that maybe is joined
+ * @param null|string $propertyAlias Expected alias of given property joined in given query builder
+ *
+ * @dataProvider provideQueryBuilderAndPropertyAlias
+ */
+ public function testGetJoinedPropertyAlias(QueryBuilder $queryBuilder, $propertyName, $propertyAlias)
+ {
+ static::assertSame($propertyAlias, QueryBuilderUtility::getJoinedPropertyAlias($queryBuilder, $propertyName));
+ }
+
+ /**
+ * @param QueryBuilder $queryBuilder The query builder to retrieve root alias
+ * @param null|string $rootAlias Expected root alias of given query builder
+ *
+ * @dataProvider provideQueryBuilderAndRootAlias
+ */
+ public function testGetRootAlias(QueryBuilder $queryBuilder, $rootAlias)
+ {
+ static::assertSame($rootAlias, QueryBuilderUtility::getRootAlias($queryBuilder));
+ }
+
+ /**
+ * @param QueryBuilder $queryBuilder The query builder
+ * @param array $criteria The criteria used in WHERE clause
+ *
+ * @dataProvider provideQueryBuilderAndCriteria
+ */
+ public function testSetCriteria(QueryBuilder $queryBuilder, array $criteria)
+ {
+ $newQueryBuilder = QueryBuilderUtility::setCriteria($queryBuilder, $criteria);
+ $criteriaCount = count($criteria);
+ $nullsCount = 0;
+
+ // I have to verify count/amount of NULLs and decrease $criteriaCount, because for null parameter is not added
+ array_walk($criteria, function ($value) use (&$nullsCount) {
+ if (null === $value) {
+ ++$nullsCount;
+ }
+ });
+
+ static::assertSame($queryBuilder, $newQueryBuilder);
+ static::assertCount($criteriaCount - $nullsCount, $newQueryBuilder->getParameters());
+ static::assertNotNull($newQueryBuilder->getDQLPart('where'));
+ }
+
+ public function testSetCriteriaWithoutAlias()
+ {
+ $criteria = [
+ 'lorem' => 11,
+ 'ipsum' => 22,
+ ];
+
+ $entityManager = $this->createMock(EntityManagerInterface::class);
+ $queryBuilder = new QueryBuilder($entityManager);
+ $newQueryBuilder = QueryBuilderUtility::setCriteria($queryBuilder, $criteria);
+
+ static::assertSame($queryBuilder, $newQueryBuilder);
+ static::assertCount(count($criteria), $newQueryBuilder->getParameters());
+ static::assertNotNull($newQueryBuilder->getDQLPart('where'));
+ }
+
+ public function testSetCriteriaWithoutCriteria()
+ {
+ $entityManager = $this->createMock(EntityManagerInterface::class);
+ $queryBuilder = new QueryBuilder($entityManager);
+ $newQueryBuilder = QueryBuilderUtility::setCriteria($queryBuilder);
+
+ static::assertSame($queryBuilder, $newQueryBuilder);
+ static::assertCount(0, $newQueryBuilder->getParameters());
+ static::assertNull($newQueryBuilder->getDQLPart('where'));
+ }
}
diff --git a/tests/Utilities/Reflection/A.php b/tests/Utilities/Reflection/A.php
index f20ca1a..b5fcbcb 100644
--- a/tests/Utilities/Reflection/A.php
+++ b/tests/Utilities/Reflection/A.php
@@ -14,6 +14,9 @@ namespace Meritoo\Test\Common\Utilities\Reflection;
*
* @author Meritoo
* @copyright Meritoo
+ *
+ * @internal
+ * @coversNothing
*/
class A
{
@@ -21,13 +24,13 @@ class A
private $count = 1;
- protected function lorem()
- {
- return 'ipsum';
- }
-
protected function getCount()
{
return $this->count;
}
+
+ protected function lorem()
+ {
+ return 'ipsum';
+ }
}
diff --git a/tests/Utilities/Reflection/B.php b/tests/Utilities/Reflection/B.php
index 101cdce..aa676be 100644
--- a/tests/Utilities/Reflection/B.php
+++ b/tests/Utilities/Reflection/B.php
@@ -14,6 +14,9 @@ namespace Meritoo\Test\Common\Utilities\Reflection;
*
* @author Meritoo
* @copyright Meritoo
+ *
+ * @internal
+ * @coversNothing
*/
class B extends A implements I
{
diff --git a/tests/Utilities/Reflection/C.php b/tests/Utilities/Reflection/C.php
index 3c4d598..cf8b860 100644
--- a/tests/Utilities/Reflection/C.php
+++ b/tests/Utilities/Reflection/C.php
@@ -14,16 +14,19 @@ namespace Meritoo\Test\Common\Utilities\Reflection;
*
* @author Meritoo
* @copyright Meritoo
+ *
+ * @internal
+ * @coversNothing
*/
class C extends B
{
- public function getPositive()
- {
- return true;
- }
-
public function getNegative()
{
return false;
}
+
+ public function getPositive()
+ {
+ return true;
+ }
}
diff --git a/tests/Utilities/Reflection/D.php b/tests/Utilities/Reflection/D.php
index 06f6550..2467723 100644
--- a/tests/Utilities/Reflection/D.php
+++ b/tests/Utilities/Reflection/D.php
@@ -14,6 +14,9 @@ namespace Meritoo\Test\Common\Utilities\Reflection;
*
* @author Meritoo
* @copyright Meritoo
+ *
+ * @internal
+ * @coversNothing
*/
class D
{
diff --git a/tests/Utilities/Reflection/E.php b/tests/Utilities/Reflection/E.php
index 7a72efc..96afb85 100644
--- a/tests/Utilities/Reflection/E.php
+++ b/tests/Utilities/Reflection/E.php
@@ -14,6 +14,8 @@ namespace Meritoo\Test\Common\Utilities\Reflection;
*
* @author Meritoo
* @copyright Meritoo
+ *
+ * @internal
*/
trait E
{
diff --git a/tests/Utilities/Reflection/F.php b/tests/Utilities/Reflection/F.php
index 7206544..03a0c3c 100644
--- a/tests/Utilities/Reflection/F.php
+++ b/tests/Utilities/Reflection/F.php
@@ -14,6 +14,9 @@ namespace Meritoo\Test\Common\Utilities\Reflection;
*
* @author Meritoo
* @copyright Meritoo
+ *
+ * @internal
+ * @coversNothing
*/
class F
{
@@ -21,7 +24,7 @@ class F
private $accountBalance;
private $city;
private $country;
- private $gInstance;
+ private $g;
public function __construct($accountBalance, $city, $country, $username, $firstName = 'John', $lastName = 'Scott')
{
@@ -29,11 +32,9 @@ class F
$this->city = $city;
$this->country = $country;
$this->username = $username;
- $this->gInstance = new G($firstName, $lastName);
+ $this->g = new G($firstName, $lastName);
- /*
- * Called to avoid "Unused private method getAccountBalance" warning only
- */
+ // Called to avoid "Unused private method getAccountBalance" warning only
$this->getAccountBalance();
}
diff --git a/tests/Utilities/Reflection/G.php b/tests/Utilities/Reflection/G.php
index d7f2c54..34fdcf8 100644
--- a/tests/Utilities/Reflection/G.php
+++ b/tests/Utilities/Reflection/G.php
@@ -14,6 +14,9 @@ namespace Meritoo\Test\Common\Utilities\Reflection;
*
* @author Meritoo
* @copyright Meritoo
+ *
+ * @internal
+ * @coversNothing
*/
class G
{
diff --git a/tests/Utilities/Reflection/H.php b/tests/Utilities/Reflection/H.php
index a5ce14d..a47725b 100644
--- a/tests/Utilities/Reflection/H.php
+++ b/tests/Utilities/Reflection/H.php
@@ -14,14 +14,17 @@ namespace Meritoo\Test\Common\Utilities\Reflection;
*
* @author Meritoo
* @copyright Meritoo
+ *
+ * @internal
+ * @coversNothing
*/
class H
{
- const DOLOR = 'sit';
+ public const DOLOR = 'sit';
- const LOREM = 'ipsum';
+ public const LOREM = 'ipsum';
- const MAX_USERS = 5;
+ public const MAX_USERS = 5;
- const MIN_USERS = 2;
+ public const MIN_USERS = 2;
}
diff --git a/tests/Utilities/Reflection/I.php b/tests/Utilities/Reflection/I.php
index 020b149..50652a2 100644
--- a/tests/Utilities/Reflection/I.php
+++ b/tests/Utilities/Reflection/I.php
@@ -14,6 +14,8 @@ namespace Meritoo\Test\Common\Utilities\Reflection;
*
* @author Meritoo
* @copyright Meritoo
+ *
+ * @internal
*/
interface I
{
diff --git a/src/Traits/Collection/IteratorAggregateTrait.php b/tests/Utilities/Reflection/J.php
similarity index 52%
rename from src/Traits/Collection/IteratorAggregateTrait.php
rename to tests/Utilities/Reflection/J.php
index 9c814b1..3affeb4 100644
--- a/src/Traits/Collection/IteratorAggregateTrait.php
+++ b/tests/Utilities/Reflection/J.php
@@ -6,23 +6,27 @@
* file that was distributed with this source code.
*/
-namespace Meritoo\Common\Traits\Collection;
-
-use ArrayIterator;
+namespace Meritoo\Test\Common\Utilities\Reflection;
/**
- * Trait for the Collection required by IteratorAggregate interface
+ * The J class.
+ * Used for testing the Reflection class.
*
* @author Meritoo
* @copyright Meritoo
+ *
+ * @internal
+ * @coversNothing
*/
-trait IteratorAggregateTrait
+class J
{
+ private $f;
+
/**
- * {@inheritdoc}
+ * Class constructor
*/
- public function getIterator()
+ public function __construct()
{
- return new ArrayIterator($this->elements);
+ $this->f = new F(1000, 'New York', 'USA', 'john.scott');
}
}
diff --git a/tests/Utilities/Reflection/ObjectsCollection.php b/tests/Utilities/Reflection/ObjectsCollection.php
new file mode 100644
index 0000000..d51ea05
--- /dev/null
+++ b/tests/Utilities/Reflection/ObjectsCollection.php
@@ -0,0 +1,34 @@
+
+ * @copyright Meritoo
+ *
+ * @internal
+ * @coversNothing
+ */
+class ObjectsCollection extends BaseCollection
+{
+ protected function isValidType($element): bool
+ {
+ return $element instanceof A
+ || $element instanceof B
+ || $element instanceof C
+ || $element instanceof D
+ || $element instanceof F;
+ }
+}
diff --git a/tests/Utilities/ReflectionTest.php b/tests/Utilities/ReflectionTest.php
index 2507d7e..6f16f0a 100644
--- a/tests/Utilities/ReflectionTest.php
+++ b/tests/Utilities/ReflectionTest.php
@@ -10,7 +10,8 @@ namespace Meritoo\Test\Common\Utilities;
use DateTime;
use Generator;
-use Meritoo\Common\Collection\Collection;
+use Meritoo\Common\Collection\BaseCollection;
+use Meritoo\Common\Collection\Templates;
use Meritoo\Common\Exception\Reflection\CannotResolveClassNameException;
use Meritoo\Common\Exception\Reflection\MissingChildClassesException;
use Meritoo\Common\Exception\Reflection\NotExistingPropertyException;
@@ -26,128 +27,204 @@ use Meritoo\Test\Common\Utilities\Reflection\F;
use Meritoo\Test\Common\Utilities\Reflection\G;
use Meritoo\Test\Common\Utilities\Reflection\H;
use Meritoo\Test\Common\Utilities\Reflection\I;
+use Meritoo\Test\Common\Utilities\Reflection\J;
+use Meritoo\Test\Common\Utilities\Reflection\ObjectsCollection;
use ReflectionProperty;
+use stdClass;
/**
* Test case of the useful reflection methods
*
* @author Meritoo
* @copyright Meritoo
+ *
+ * @internal
+ * @covers \Meritoo\Common\Utilities\Reflection
*/
class ReflectionTest extends BaseTestCase
{
- public function testConstructor()
+ public function provideClassToGetConstants(): ?Generator
+ {
+ yield [
+ new stdClass(),
+ [],
+ ];
+
+ yield [
+ stdClass::class,
+ [],
+ ];
+
+ yield [
+ H::class,
+ [
+ 'DOLOR' => 'sit',
+ 'LOREM' => 'ipsum',
+ 'MAX_USERS' => 5,
+ 'MIN_USERS' => 2,
+ ],
+ ];
+ }
+
+ public function provideInvalidClassAndTrait(): ?Generator
+ {
+ yield [
+ '',
+ '',
+ ];
+
+ yield [
+ null,
+ null,
+ ];
+
+ yield [
+ 0,
+ 0,
+ ];
+ }
+
+ public function provideObjectAndNotExistingProperties(): ?Generator
+ {
+ yield [
+ new stdClass(),
+ [
+ 'test' => 1,
+ ],
+ ];
+
+ yield [
+ new A(),
+ [
+ 'test' => 2,
+ ],
+ ];
+
+ yield [
+ new B(),
+ [
+ 'firstName' => '',
+ ],
+ ];
+ }
+
+ public function provideObjectAndNotExistingProperty(): ?Generator
+ {
+ yield [
+ new stdClass(),
+ 'test',
+ ];
+
+ yield [
+ new A(),
+ 'test',
+ ];
+
+ yield [
+ new B(),
+ 'firstName',
+ ];
+ }
+
+ public function provideObjectAndPropertiesValues(): ?Generator
+ {
+ yield [
+ new A(),
+ [
+ 'count' => 123,
+ ],
+ ];
+
+ yield [
+ new B(),
+ [
+ 'name' => 'test test',
+ ],
+ ];
+
+ yield [
+ new G(),
+ [
+ 'firstName' => 'Jane',
+ ],
+ ];
+
+ yield [
+ new G(),
+ [
+ 'lastName' => 'Smith',
+ ],
+ ];
+
+ yield [
+ new G(),
+ [
+ 'firstName' => 'Jane',
+ 'lastName' => 'Brown',
+ ],
+ ];
+
+ yield [
+ new F(
+ 123,
+ 'New York',
+ 'USA',
+ 'UnKnown'
+ ),
+ [
+ 'g' => new G(),
+ ],
+ ];
+
+ yield [
+ new F(
+ 123,
+ 'New York',
+ 'USA',
+ 'UnKnown',
+ 'Mary',
+ 'Brown'
+ ),
+ [
+ 'country' => 'Canada',
+ 'accountBalance' => 456,
+ ],
+ ];
+ }
+
+ public function provideObjectPropertyAndValue(): ?Generator
+ {
+ yield [
+ new A(),
+ 'count',
+ 123,
+ ];
+
+ yield [
+ new B(),
+ 'name',
+ 'test test',
+ ];
+
+ yield [
+ new G(),
+ 'firstName',
+ 'Jane',
+ ];
+
+ yield [
+ new G(),
+ 'lastName',
+ 'Smith',
+ ];
+ }
+
+ public function testConstructor(): void
{
static::assertHasNoConstructor(Reflection::class);
}
- /**
- * @param mixed $invalidClass Empty value, e.g. ""
- * @dataProvider provideEmptyValue
- */
- public function testGetClassNameInvalidClass($invalidClass)
- {
- self::assertNull(Reflection::getClassName($invalidClass));
- self::assertNull(Reflection::getClassName(123));
- }
-
- public function testGetClassNameNotExistingClass()
- {
- /*
- * Not existing class
- */
- self::assertEquals('', Reflection::getClassName('xyz'));
- self::assertEquals('', Reflection::getClassName('xyz', true));
- }
-
- public function testGetClassNameExistingClass()
- {
- /*
- * Existing class
- */
- self::assertEquals(self::class, Reflection::getClassName(self::class));
- self::assertEquals('ReflectionTest', Reflection::getClassName(self::class, true));
- self::assertEquals(DateTime::class, Reflection::getClassName(new DateTime()));
- self::assertEquals(DateTime::class, Reflection::getClassName(new DateTime(), true));
-
- self::assertEquals(DateTime::class, Reflection::getClassName([
- new DateTime(),
- new DateTime('yesterday'),
- ]));
- }
-
- public function testGetClassNameDuplicatedName()
- {
- /*
- * Class with namespace containing name of class (duplicated string)
- */
- if (class_exists('Symfony\Bundle\SecurityBundle\SecurityBundle')) {
- self::assertEquals(
- 'Symfony\Bundle\SecurityBundle\SecurityBundle',
- Reflection::getClassName('Symfony\Bundle\SecurityBundle\SecurityBundle')
- );
-
- self::assertEquals(
- 'SecurityBundle',
- Reflection::getClassName('Symfony\Bundle\SecurityBundle\SecurityBundle', true)
- );
- }
- }
-
- public function testGetClassNamespaceNotExistingClass()
- {
- /*
- * Not existing class
- */
- self::assertEquals('', Reflection::getClassNamespace('xyz'));
- }
-
- public function testGetClassNamespaceExistingClass()
- {
- /*
- * Existing class
- */
- self::assertEquals('Meritoo\Test\Common\Utilities', Reflection::getClassNamespace(self::class));
- self::assertEquals(DateTime::class, Reflection::getClassNamespace(new DateTime()));
-
- self::assertEquals(DateTime::class, Reflection::getClassNamespace([
- new DateTime(),
- new DateTime('yesterday'),
- ]));
- }
-
- public function testGetClassNamespaceDuplicatedName()
- {
- /*
- * Class with namespace containing name of class (duplicated string)
- */
- if (class_exists('Symfony\Bundle\SecurityBundle\SecurityBundle')) {
- self::assertEquals(
- 'Symfony\Bundle\SecurityBundle',
- Reflection::getClassNamespace('Symfony\Bundle\SecurityBundle\SecurityBundle')
- );
- }
- }
-
- /**
- * @param mixed $invalidClass Empty value, e.g. ""
- * @dataProvider provideEmptyValue
- */
- public function testGetChildClassesInvalidClass($invalidClass)
- {
- $this->setExpectedException(CannotResolveClassNameException::class);
-
- self::assertNull(Reflection::getChildClasses($invalidClass));
- self::assertNull(Reflection::getChildClasses(123));
- }
-
- public function testGetChildClassesNotExistingClass()
- {
- $this->setExpectedException(CannotResolveClassNameException::class);
- self::assertEquals('', Reflection::getChildClasses('xyz'));
- }
-
- public function testGetChildClassesExistingClass()
+ public function testGetChildClassesExistingClass(): void
{
/*
* Attention. I have to create instances of these classes to load them and be available while using
@@ -172,26 +249,132 @@ class ReflectionTest extends BaseTestCase
self::assertEquals($effect, Reflection::getChildClasses(A::class));
}
- public function testGetOneChildClassWithMissingChildClasses()
+ /**
+ * @param mixed $invalidClass Empty value, e.g. ""
+ * @dataProvider provideEmptyValue
+ */
+ public function testGetChildClassesInvalidClass($invalidClass): void
{
- $this->setExpectedException(MissingChildClassesException::class);
- self::assertEquals('LoremIpsum', Reflection::getOneChildClass(C::class));
+ $this->expectException(CannotResolveClassNameException::class);
+
+ self::assertNull(Reflection::getChildClasses($invalidClass));
+ self::assertNull(Reflection::getChildClasses(123));
}
- public function testGetOneChildClassWithTooManyChildClasses()
+ public function testGetChildClassesNotExistingClass(): void
{
- $this->setExpectedException(TooManyChildClassesException::class);
-
- self::assertEquals(B::class, Reflection::getOneChildClass(A::class));
- self::assertEquals(C::class, Reflection::getOneChildClass(A::class));
+ $this->expectException(CannotResolveClassNameException::class);
+ self::assertEquals('', Reflection::getChildClasses('xyz'));
}
- public function testGetOneChildClass()
+ public function testGetClassNameExistingClass(): void
{
- self::assertEquals(C::class, Reflection::getOneChildClass(B::class));
+ // Existing class
+ self::assertEquals(self::class, Reflection::getClassName(self::class));
+ self::assertEquals('ReflectionTest', Reflection::getClassName(self::class, true));
+ self::assertEquals(DateTime::class, Reflection::getClassName(new DateTime()));
+ self::assertEquals(DateTime::class, Reflection::getClassName(new DateTime(), true));
+
+ self::assertEquals(DateTime::class, Reflection::getClassName([
+ new DateTime(),
+ new DateTime('yesterday'),
+ ]));
}
- public function testGetMethods()
+ /**
+ * @param mixed $invalidClass Empty value, e.g. ""
+ * @dataProvider provideEmptyValue
+ */
+ public function testGetClassNameInvalidClass($invalidClass): void
+ {
+ self::assertNull(Reflection::getClassName($invalidClass));
+ self::assertNull(Reflection::getClassName(123));
+ }
+
+ public function testGetClassNameNotExistingClass(): void
+ {
+ // Not existing class
+ self::assertEquals('', Reflection::getClassName('xyz'));
+ self::assertEquals('', Reflection::getClassName('xyz', true));
+ }
+
+ public function testGetClassNamespaceExistingClass(): void
+ {
+ // Existing class
+ self::assertEquals('Meritoo\Test\Common\Utilities', Reflection::getClassNamespace(self::class));
+ self::assertEquals(DateTime::class, Reflection::getClassNamespace(new DateTime()));
+
+ self::assertEquals(DateTime::class, Reflection::getClassNamespace([
+ new DateTime(),
+ new DateTime('yesterday'),
+ ]));
+ }
+
+ public function testGetClassNamespaceNotExistingClass(): void
+ {
+ // Not existing class
+ self::assertEquals('', Reflection::getClassNamespace('xyz'));
+ }
+
+ /**
+ * A case when namespace of class contains name of class (name of class is duplicated, occurs twice)
+ */
+ public function testGetClassNamespaceWhileNamespaceContainsClassName(): void
+ {
+ self::assertEquals(
+ 'Meritoo\Common\Collection',
+ Reflection::getClassNamespace(BaseCollection::class)
+ );
+ }
+
+ /**
+ * A case when namespace of class contains name of class (iow. name of class occurs twice)
+ */
+ public function testGetClassWhileNamespaceContainsClassName(): void
+ {
+ self::assertEquals(
+ BaseCollection::class,
+ Reflection::getClassName(BaseCollection::class)
+ );
+
+ self::assertEquals(
+ 'BaseCollection',
+ Reflection::getClassName(BaseCollection::class, true)
+ );
+ }
+
+ public function testGetConstantValue(): void
+ {
+ static::assertSame(H::LOREM, Reflection::getConstantValue(H::class, 'LOREM'));
+ }
+
+ public function testGetConstantValueUsingClassWithoutConstant(): void
+ {
+ static::assertNull(Reflection::getConstantValue(H::class, 'users'));
+ }
+
+ /**
+ * @param object|string $class The object or name of object's class
+ * @param array $expected Expected constants
+ *
+ * @dataProvider provideClassToGetConstants
+ */
+ public function testGetConstants($class, array $expected): void
+ {
+ static::assertSame($expected, Reflection::getConstants($class));
+ }
+
+ public function testGetMaxNumberConstant(): void
+ {
+ static::assertSame(5, Reflection::getMaxNumberConstant(H::class));
+ }
+
+ public function testGetMaxNumberConstantUsingClassWithoutConstants(): void
+ {
+ static::assertNull(Reflection::getMaxNumberConstant(A::class));
+ }
+
+ public function testGetMethods(): void
{
self::assertCount(1, Reflection::getMethods(B::class, true));
self::assertCount(3, Reflection::getMethods(B::class));
@@ -200,50 +383,39 @@ class ReflectionTest extends BaseTestCase
self::assertCount(5, Reflection::getMethods(C::class));
}
- /**
- * @param array|object|string $class An array of objects, namespaces, object or namespace
- * @param array|string $trait An array of strings or string
- *
- * @dataProvider provideInvalidClassAndTrait
- */
- public function testUsesTraitInvalidClass($class, $trait)
+ public function testGetOneChildClass(): void
{
- $this->setExpectedException(CannotResolveClassNameException::class);
- self::assertNull(Reflection::usesTrait($class, $trait));
+ // Required to get all classes by get_declared_classes() function and avoid throw of
+ // Meritoo\Common\Exception\Reflection\MissingChildClassesException exception
+ new C();
+
+ self::assertEquals(C::class, Reflection::getOneChildClass(B::class));
}
- /**
- * @param mixed $trait Empty value, e.g. ""
- * @dataProvider provideEmptyValue
- */
- public function testUsesTraitInvalidTrait($trait)
+ public function testGetOneChildClassWithMissingChildClasses(): void
{
- $this->setExpectedException(CannotResolveClassNameException::class);
- self::assertNull(Reflection::usesTrait(DateTime::class, $trait));
+ $this->expectException(MissingChildClassesException::class);
+ self::assertEquals('LoremIpsum', Reflection::getOneChildClass(C::class));
}
- public function testUsesTraitExistingClass()
+ public function testGetOneChildClassWithTooManyChildClasses(): void
{
- self::assertTrue(Reflection::usesTrait(A::class, E::class));
- self::assertFalse(Reflection::usesTrait(B::class, E::class));
- self::assertFalse(Reflection::usesTrait(C::class, E::class));
- self::assertFalse(Reflection::usesTrait(D::class, E::class));
+ // Required to get all classes by get_declared_classes() function and avoid failure:
+ //
+ // Failed asserting that exception of type "Meritoo\Common\Exception\Reflection\TooManyChildClassesException"
+ // is thrown
+ new C();
+
+ $this->expectException(TooManyChildClassesException::class);
+ Reflection::getOneChildClass(A::class);
}
- public function testUsesTraitExistingClassAndVerifyParents()
- {
- self::assertTrue(Reflection::usesTrait(A::class, E::class, true));
- self::assertTrue(Reflection::usesTrait(B::class, E::class, true));
- self::assertTrue(Reflection::usesTrait(C::class, E::class, true));
- self::assertFalse(Reflection::usesTrait(D::class, E::class, true));
- }
-
- public function testGetProperties()
+ public function testGetProperties(): void
{
self::assertCount(1, Reflection::getProperties(B::class));
}
- public function testGetPropertiesUsingFilter()
+ public function testGetPropertiesUsingFilter(): void
{
self::assertCount(
1,
@@ -261,40 +433,53 @@ class ReflectionTest extends BaseTestCase
);
}
- public function testGetPropertiesWithParents()
+ public function testGetPropertiesWithParents(): void
{
self::assertCount(2, Reflection::getProperties(B::class, null, true));
}
- public function testGetPropertyValueOfNotExistingProperty()
+ public function testGetPropertyUsingClassWithPrivateProperty(): void
+ {
+ $property = Reflection::getProperty(A::class, 'count', ReflectionProperty::IS_PRIVATE);
+
+ static::assertInstanceOf(ReflectionProperty::class, $property);
+ static::assertTrue($property->isPrivate());
+ static::assertSame('count', $property->getName());
+ }
+
+ public function testGetPropertyUsingClassWithProtectedProperty(): void
+ {
+ $property = Reflection::getProperty(B::class, 'name', ReflectionProperty::IS_PROTECTED);
+
+ static::assertInstanceOf(ReflectionProperty::class, $property);
+ static::assertTrue($property->isProtected());
+ static::assertSame('name', $property->getName());
+ }
+
+ public function testGetPropertyUsingClassWithoutProperty(): void
+ {
+ static::assertNull(Reflection::getProperty(A::class, 'lorem'));
+ }
+
+ public function testGetPropertyValueFromChain(): void
+ {
+ $f = new F(1000, 'New York', 'USA', 'john.scott');
+ self::assertEquals('John', Reflection::getPropertyValue($f, 'g.firstName'));
+ }
+
+ public function testGetPropertyValueFromParentClass(): void
+ {
+ $c = new C();
+ self::assertEquals(1, Reflection::getPropertyValue($c, 'count', true));
+ }
+
+ public function testGetPropertyValueOfNotExistingProperty(): void
{
self::assertNull(Reflection::getPropertyValue(new D(), 'something'));
self::assertNull(Reflection::getPropertyValue(new D(), 'something', true));
}
- public function testGetPropertyValueFromChain()
- {
- $f = new F(1000, 'New York', 'USA', 'john.scott');
- self::assertEquals('John', Reflection::getPropertyValue($f, 'gInstance.firstName'));
- }
-
- public function testGetPropertyValueWithPublicGetter()
- {
- $country = 'USA';
- $f = new F(1000, 'New York', $country, 'john.scott');
-
- self::assertEquals($country, Reflection::getPropertyValue($f, 'country'));
- }
-
- public function testGetPropertyValueWithProtectedGetter()
- {
- $city = 'New York';
- $f = new F(1000, $city, 'USA', 'john.scott');
-
- self::assertEquals($city, Reflection::getPropertyValue($f, 'city'));
- }
-
- public function testGetPropertyValueWithPrivateGetter()
+ public function testGetPropertyValueWithPrivateGetter(): void
{
$accountBalance = 1000;
$f = new F($accountBalance, 'New York', 'USA', 'john.scott');
@@ -302,7 +487,23 @@ class ReflectionTest extends BaseTestCase
self::assertEquals($accountBalance, Reflection::getPropertyValue($f, 'accountBalance'));
}
- public function testGetPropertyValueWithoutGetter()
+ public function testGetPropertyValueWithProtectedGetter(): void
+ {
+ $city = 'New York';
+ $f = new F(1000, $city, 'USA', 'john.scott');
+
+ self::assertEquals($city, Reflection::getPropertyValue($f, 'city'));
+ }
+
+ public function testGetPropertyValueWithPublicGetter(): void
+ {
+ $country = 'USA';
+ $f = new F(1000, 'New York', $country, 'john.scott');
+
+ self::assertEquals($country, Reflection::getPropertyValue($f, 'country'));
+ }
+
+ public function testGetPropertyValueWithoutGetter(): void
{
$username = 'john.scott';
$f = new F(1000, 'New York', 'USA', $username);
@@ -310,46 +511,48 @@ class ReflectionTest extends BaseTestCase
self::assertEquals($username, Reflection::getPropertyValue($f, 'username'));
}
- public function testGetPropertyValuesFromEmptySource()
+ public function testGetPropertyValuesFromChainAndMultipleObjects(): void
{
- self::assertEquals([], Reflection::getPropertyValues([], 'something'));
- self::assertEquals([], Reflection::getPropertyValues(new Collection(), 'something'));
- }
-
- public function testGetPropertyValuesOfNotExistingPropertyFromSingleObject()
- {
- self::assertEquals([], Reflection::getPropertyValues(new D(), 'something'));
- self::assertEquals([], Reflection::getPropertyValues(new D(), 'something', true));
- }
-
- public function testGetPropertyValuesOfNotExistingPropertyFromMultipleObjects()
- {
- $objects = [
- new A(),
- new A(),
- new A(),
- new B(),
- new B(),
- new C(),
- new D(),
+ $expected = [
+ 'John',
+ 'Mary',
+ 'Peter',
];
- self::assertEquals([], Reflection::getPropertyValues($objects, 'something'));
- self::assertEquals([], Reflection::getPropertyValues($objects, 'something', true));
+ $objects = [
+ new F(1000, 'New York', 'USA', 'john.scott'),
+ new F(2000, 'London', 'GB', 'john.scott', 'Mary', 'Jane'),
+ new F(3000, 'Tokyo', 'Japan', 'john.scott', 'Peter', 'Brown'),
+ ];
- $collection = new Collection($objects);
+ self::assertEquals($expected, Reflection::getPropertyValues($objects, 'g.firstName'));
+ self::assertEquals($expected, Reflection::getPropertyValues($objects, 'g.firstName', true));
- self::assertEquals([], Reflection::getPropertyValues($collection, 'something'));
- self::assertEquals([], Reflection::getPropertyValues($collection, 'something', true));
+ $collection = new ObjectsCollection($objects);
+
+ self::assertEquals($expected, Reflection::getPropertyValues($collection, 'g.firstName'));
+ self::assertEquals($expected, Reflection::getPropertyValues($collection, 'g.firstName', true));
}
- public function testGetPropertyValuesOfExistingPropertyFromSingleObject()
+ public function testGetPropertyValuesFromChainAndSingleObject(): void
{
- self::assertEquals(['John'], Reflection::getPropertyValues(new G(), 'firstName'));
- self::assertEquals(['John'], Reflection::getPropertyValues(new G(), 'firstName', true));
+ $f = new F(1000, 'New York', 'USA', 'john.scott');
+ $j = new J();
+
+ self::assertEquals(['John'], Reflection::getPropertyValues($f, 'g.firstName'));
+ self::assertEquals(['John'], Reflection::getPropertyValues($f, 'g.firstName', true));
+
+ self::assertEquals(['John'], Reflection::getPropertyValues($j, 'f.g.firstName'));
+ self::assertEquals(['John'], Reflection::getPropertyValues($j, 'f.g.firstName', true));
}
- public function testGetPropertyValuesOfExistingPropertyFromMultipleObjects()
+ public function testGetPropertyValuesFromEmptySource(): void
+ {
+ self::assertEquals([], Reflection::getPropertyValues([], 'something'));
+ self::assertEquals([], Reflection::getPropertyValues(new Templates(), 'something'));
+ }
+
+ public function testGetPropertyValuesOfExistingPropertyFromMultipleObjects(): void
{
$expected = [
'New York',
@@ -366,184 +569,93 @@ class ReflectionTest extends BaseTestCase
self::assertEquals($expected, Reflection::getPropertyValues($objects, 'city'));
self::assertEquals($expected, Reflection::getPropertyValues($objects, 'city', true));
- $collection = new Collection($objects);
+ $collection = new ObjectsCollection($objects);
self::assertEquals($expected, Reflection::getPropertyValues($collection, 'city'));
self::assertEquals($expected, Reflection::getPropertyValues($collection, 'city', true));
}
- public function testGetPropertyValuesFromChainAndSingleObject()
+ public function testGetPropertyValuesOfExistingPropertyFromSingleObject(): void
{
- $f = new F(1000, 'New York', 'USA', 'john.scott');
-
- self::assertEquals(['John'], Reflection::getPropertyValues($f, 'gInstance.firstName'));
- self::assertEquals(['John'], Reflection::getPropertyValues($f, 'gInstance.firstName', true));
+ self::assertEquals(['John'], Reflection::getPropertyValues(new G(), 'firstName'));
+ self::assertEquals(['John'], Reflection::getPropertyValues(new G(), 'firstName', true));
}
- public function testGetPropertyValuesFromChainAndMultipleObjects()
+ public function testGetPropertyValuesOfNotExistingPropertyFromMultipleObjects(): void
{
- $expected = [
- 'John',
- 'Mary',
- 'Peter',
- ];
-
$objects = [
- new F(1000, 'New York', 'USA', 'john.scott'),
- new F(2000, 'London', 'GB', 'john.scott', 'Mary', 'Jane'),
- new F(3000, 'Tokyo', 'Japan', 'john.scott', 'Peter', 'Brown'),
+ new A(),
+ new A(),
+ new A(),
+ new B(),
+ new B(),
+ new C(),
+ new D(),
];
- self::assertEquals($expected, Reflection::getPropertyValues($objects, 'gInstance.firstName'));
- self::assertEquals($expected, Reflection::getPropertyValues($objects, 'gInstance.firstName', true));
+ self::assertEquals([], Reflection::getPropertyValues($objects, 'something'));
+ self::assertEquals([], Reflection::getPropertyValues($objects, 'something', true));
- $collection = new Collection($objects);
+ $collection = new ObjectsCollection($objects);
- self::assertEquals($expected, Reflection::getPropertyValues($collection, 'gInstance.firstName'));
- self::assertEquals($expected, Reflection::getPropertyValues($collection, 'gInstance.firstName', true));
+ self::assertEquals([], Reflection::getPropertyValues($collection, 'something'));
+ self::assertEquals([], Reflection::getPropertyValues($collection, 'something', true));
}
- public function testGetMaxNumberConstantUsingClassWithoutConstants()
+ public function testGetPropertyValuesOfNotExistingPropertyFromSingleObject(): void
{
- static::assertNull(Reflection::getMaxNumberConstant(A::class));
+ self::assertEquals([], Reflection::getPropertyValues(new D(), 'something'));
+ self::assertEquals([], Reflection::getPropertyValues(new D(), 'something', true));
}
- public function testGetMaxNumberConstant()
- {
- static::assertSame(5, Reflection::getMaxNumberConstant(H::class));
- }
-
- public function testHasMethodUsingClassWithoutMethod()
- {
- static::assertFalse(Reflection::hasMethod(A::class, 'getUser'));
- }
-
- public function testHasMethod()
- {
- static::assertTrue(Reflection::hasMethod(A::class, 'getCount'));
- }
-
- public function testHasPropertyUsingClassWithoutProperty()
- {
- static::assertFalse(Reflection::hasProperty(A::class, 'users'));
- }
-
- public function testHasProperty()
- {
- static::assertTrue(Reflection::hasProperty(A::class, 'count'));
- }
-
- public function testHasConstantUsingClassWithoutConstant()
- {
- static::assertFalse(Reflection::hasConstant(H::class, 'users'));
- }
-
- public function testHasConstant()
+ public function testHasConstant(): void
{
static::assertTrue(Reflection::hasConstant(H::class, 'LOREM'));
}
- public function testGetConstantValueUsingClassWithoutConstant()
+ public function testHasConstantUsingClassWithoutConstant(): void
{
- static::assertNull(Reflection::getConstantValue(H::class, 'users'));
+ static::assertFalse(Reflection::hasConstant(H::class, 'users'));
}
- public function testGetConstantValue()
+ public function testHasMethod(): void
{
- static::assertSame(H::LOREM, Reflection::getConstantValue(H::class, 'LOREM'));
+ static::assertTrue(Reflection::hasMethod(A::class, 'getCount'));
}
- public function testIsInterfaceImplementedUsingClassWithoutInterface()
+ public function testHasMethodUsingClassWithoutMethod(): void
{
- static::assertFalse(Reflection::isInterfaceImplemented(A::class, I::class));
+ static::assertFalse(Reflection::hasMethod(A::class, 'getUser'));
}
- public function testIsInterfaceImplemented()
+ public function testHasProperty(): void
{
- static::assertTrue(Reflection::isInterfaceImplemented(B::class, I::class));
+ static::assertTrue(Reflection::hasProperty(A::class, 'count'));
}
- public function testIsChildOfClassUsingClassWithoutChildClass()
+ public function testHasPropertyUsingClassWithoutProperty(): void
{
- static::assertFalse(Reflection::isChildOfClass(A::class, B::class));
+ static::assertFalse(Reflection::hasProperty(A::class, 'users'));
}
- public function testIsChildOfClass()
+ public function testIsChildOfClass(): void
{
static::assertTrue(Reflection::isChildOfClass(B::class, A::class));
}
- public function testGetPropertyUsingClassWithoutProperty()
+ public function testIsChildOfClassUsingClassWithoutChildClass(): void
{
- static::assertNull(Reflection::getProperty(A::class, 'lorem'));
+ static::assertFalse(Reflection::isChildOfClass(A::class, B::class));
}
- public function testGetPropertyUsingClassWithPrivateProperty()
+ public function testIsInterfaceImplemented(): void
{
- $property = Reflection::getProperty(A::class, 'count', ReflectionProperty::IS_PRIVATE);
-
- static::assertInstanceOf(ReflectionProperty::class, $property);
- static::assertTrue($property->isPrivate());
- static::assertSame('count', $property->getName());
+ static::assertTrue(Reflection::isInterfaceImplemented(B::class, I::class));
}
- public function testGetPropertyUsingClassWithProtectedProperty()
+ public function testIsInterfaceImplementedUsingClassWithoutInterface(): void
{
- $property = Reflection::getProperty(B::class, 'name', ReflectionProperty::IS_PROTECTED);
-
- static::assertInstanceOf(ReflectionProperty::class, $property);
- static::assertTrue($property->isProtected());
- static::assertSame('name', $property->getName());
- }
-
- /**
- * @param mixed $object Object that should contains given property
- * @param string $property Name of the property
- *
- * @dataProvider provideObjectAndNotExistingProperty
- */
- public function testSetPropertyValueUsingNotExistingProperty($object, $property)
- {
- $this->setExpectedException(NotExistingPropertyException::class);
- Reflection::setPropertyValue($object, $property, 'test test test');
- }
-
- /**
- * @param mixed $object Object that should contains given property
- * @param string $property Name of the property
- * @param mixed $value Value of the property
- *
- * @dataProvider provideObjectPropertyAndValue
- */
- public function testSetPropertyValue($object, $property, $value)
- {
- $oldValue = Reflection::getPropertyValue($object, $property);
- Reflection::setPropertyValue($object, $property, $value);
- $newValue = Reflection::getPropertyValue($object, $property);
-
- static::assertNotSame($oldValue, $value);
- static::assertSame($newValue, $value);
- }
-
- public function testSetPropertiesValuesWithoutProperties()
- {
- $object = new G();
- Reflection::setPropertiesValues($object, []);
-
- static::assertSame($object->getFirstName(), 'John');
- static::assertSame($object->getLastName(), 'Scott');
- }
-
- /**
- * @param mixed $object Object that should contains given property
- * @param array $propertiesValues Key-value pairs, where key - name of the property, value - value of the property
- *
- * @dataProvider provideObjectAndNotExistingProperties
- */
- public function testSetPropertiesValuesUsingNotExistingProperties($object, array $propertiesValues)
- {
- $this->setExpectedException(NotExistingPropertyException::class);
- Reflection::setPropertiesValues($object, $propertiesValues);
+ static::assertFalse(Reflection::isInterfaceImplemented(A::class, I::class));
}
/**
@@ -552,7 +664,7 @@ class ReflectionTest extends BaseTestCase
*
* @dataProvider provideObjectAndPropertiesValues
*/
- public function testSetPropertiesValues($object, array $propertiesValues)
+ public function testSetPropertiesValues($object, array $propertiesValues): void
{
Reflection::setPropertiesValues($object, $propertiesValues);
@@ -563,185 +675,90 @@ class ReflectionTest extends BaseTestCase
}
/**
- * Provides invalid class and trait
+ * @param mixed $object Object that should contains given property
+ * @param array $propertiesValues Key-value pairs, where key - name of the property, value - value of the property
*
- * @return Generator
+ * @dataProvider provideObjectAndNotExistingProperties
*/
- public function provideInvalidClassAndTrait()
+ public function testSetPropertiesValuesUsingNotExistingProperties($object, array $propertiesValues): void
{
- yield[
- '',
- '',
- ];
+ $this->expectException(NotExistingPropertyException::class);
+ Reflection::setPropertiesValues($object, $propertiesValues);
+ }
- yield[
- null,
- null,
- ];
+ public function testSetPropertiesValuesWithoutProperties(): void
+ {
+ $object = new G();
+ Reflection::setPropertiesValues($object, []);
- yield[
- 0,
- 0,
- ];
-
- yield[
- [],
- [],
- ];
+ static::assertSame($object->getFirstName(), 'John');
+ static::assertSame($object->getLastName(), 'Scott');
}
/**
- * Provides object and name of not existing property
+ * @param mixed $object Object that should contains given property
+ * @param string $property Name of the property
+ * @param mixed $value Value of the property
*
- * @return Generator
+ * @dataProvider provideObjectPropertyAndValue
*/
- public function provideObjectAndNotExistingProperty()
+ public function testSetPropertyValue($object, $property, $value): void
{
- yield[
- new \stdClass(),
- 'test',
- ];
+ $oldValue = Reflection::getPropertyValue($object, $property);
+ Reflection::setPropertyValue($object, $property, $value);
+ $newValue = Reflection::getPropertyValue($object, $property);
- yield[
- new A(),
- 'test',
- ];
-
- yield[
- new B(),
- 'firstName',
- ];
+ static::assertNotSame($oldValue, $value);
+ static::assertSame($newValue, $value);
}
/**
- * Provides object, name of property and value of the property
+ * @param mixed $object Object that should contains given property
+ * @param string $property Name of the property
*
- * @return Generator
+ * @dataProvider provideObjectAndNotExistingProperty
*/
- public function provideObjectPropertyAndValue()
+ public function testSetPropertyValueUsingNotExistingProperty($object, $property): void
{
- yield[
- new A(),
- 'count',
- 123,
- ];
+ $this->expectException(NotExistingPropertyException::class);
+ Reflection::setPropertyValue($object, $property, 'test test test');
+ }
- yield[
- new B(),
- 'name',
- 'test test',
- ];
+ public function testUsesTraitExistingClass(): void
+ {
+ self::assertTrue(Reflection::usesTrait(A::class, E::class));
+ self::assertFalse(Reflection::usesTrait(B::class, E::class));
+ self::assertFalse(Reflection::usesTrait(C::class, E::class));
+ self::assertFalse(Reflection::usesTrait(D::class, E::class));
+ }
- yield[
- new G(),
- 'firstName',
- 'Jane',
- ];
-
- yield[
- new G(),
- 'lastName',
- 'Smith',
- ];
+ public function testUsesTraitExistingClassAndVerifyParents(): void
+ {
+ self::assertTrue(Reflection::usesTrait(A::class, E::class, true));
+ self::assertTrue(Reflection::usesTrait(B::class, E::class, true));
+ self::assertTrue(Reflection::usesTrait(C::class, E::class, true));
+ self::assertFalse(Reflection::usesTrait(D::class, E::class, true));
}
/**
- * Provides object and not existing properties
+ * @param array|object|string $class An array of objects, namespaces, object or namespace
+ * @param array|string $trait An array of strings or string
*
- * @return Generator
+ * @dataProvider provideInvalidClassAndTrait
*/
- public function provideObjectAndNotExistingProperties()
+ public function testUsesTraitInvalidClass($class, $trait): void
{
- yield[
- new \stdClass(),
- [
- 'test' => 1,
- ],
- ];
-
- yield[
- new A(),
- [
- 'test' => 2,
- ],
- ];
-
- yield[
- new B(),
- [
- 'firstName' => '',
- ],
- ];
+ $this->expectException(CannotResolveClassNameException::class);
+ self::assertNull(Reflection::usesTrait($class, $trait));
}
/**
- * Provides object and its new values of properties
- *
- * @return Generator
+ * @param mixed $trait Empty value, e.g. ""
+ * @dataProvider provideEmptyValue
*/
- public function provideObjectAndPropertiesValues()
+ public function testUsesTraitInvalidTrait($trait): void
{
- yield[
- new A(),
- [
- 'count' => 123,
- ],
- ];
-
- yield[
- new B(),
- [
- 'name' => 'test test',
- ],
- ];
-
- yield[
- new G(),
- [
- 'firstName' => 'Jane',
- ],
- ];
-
- yield[
- new G(),
- [
- 'lastName' => 'Smith',
- ],
- ];
-
- yield[
- new G(),
- [
- 'firstName' => 'Jane',
- 'lastName' => 'Brown',
- ],
- ];
-
- yield[
- new F(
- 123,
- 'New York',
- 'USA',
- 'UnKnown'
- ),
- [
- 'gInstance' => new G(),
- ],
- ];
-
- yield[
- new F(
- 123,
- 'New York',
- 'USA',
- 'UnKnown',
- 'Mary',
- 'Brown'
- ),
- [
- 'country' => 'Canada',
- 'accountBalance' => 456,
- ],
- ];
+ $this->expectException(CannotResolveClassNameException::class);
+ Reflection::usesTrait(DateTime::class, $trait);
}
}
diff --git a/tests/Utilities/RegexTest.php b/tests/Utilities/RegexTest.php
index c1fb3bc..a92021e 100644
--- a/tests/Utilities/RegexTest.php
+++ b/tests/Utilities/RegexTest.php
@@ -6,29 +6,1774 @@
* file that was distributed with this source code.
*/
-namespace Meritoo\Common\Utilities;
+namespace Meritoo\Test\Common\Utilities;
use Generator;
use Meritoo\Common\Exception\Regex\IncorrectColorHexLengthException;
use Meritoo\Common\Exception\Regex\InvalidColorHexValueException;
use Meritoo\Common\Test\Base\BaseTestCase;
+use Meritoo\Common\Utilities\Regex;
+use stdClass;
/**
* Test case of the useful regular expressions methods
*
* @author Meritoo
* @copyright Meritoo
+ *
+ * @internal
+ * @covers \Meritoo\Common\Utilities\Regex
*/
class RegexTest extends BaseTestCase
{
private $simpleText;
private $camelCaseText;
+ /**
+ * Provides value to verify if it is a binary value
+ *
+ * @return Generator
+ */
+ public function provideBinaryValue()
+ {
+ $file1Path = $this->getFilePathForTesting('lorem-ipsum.txt');
+ $file2Path = $this->getFilePathForTesting('minion.jpg');
+
+ yield [
+ null,
+ false,
+ ];
+
+ yield [
+ [],
+ false,
+ ];
+
+ yield [
+ '',
+ false,
+ ];
+
+ yield [
+ 'abc',
+ false,
+ ];
+
+ yield [
+ '1234',
+ false,
+ ];
+
+ yield [
+ 1234,
+ false,
+ ];
+
+ yield [
+ 12.34,
+ false,
+ ];
+
+ yield [
+ fread(fopen($file1Path, 'rb'), 1),
+ false,
+ ];
+
+ yield [
+ fread(fopen($file2Path, 'rb'), 1),
+ true,
+ ];
+ }
+
+ /**
+ * Provides name of bundle and information if it's valid name
+ *
+ * @return Generator
+ */
+ public function provideBundleName()
+ {
+ yield [
+ 'something',
+ false,
+ ];
+
+ yield [
+ 'something_different',
+ false,
+ ];
+
+ yield [
+ 'something-else',
+ false,
+ ];
+
+ yield [
+ 'myExtraBundle',
+ false,
+ ];
+
+ yield [
+ 'MyExtra',
+ false,
+ ];
+
+ yield [
+ 'MyExtraBundle',
+ true,
+ ];
+
+ yield [
+ 'MySuperExtraGorgeousBundle',
+ true,
+ ];
+ }
+
+ /**
+ * Provides value of color
+ *
+ * @return Generator
+ */
+ public function provideColor()
+ {
+ yield [
+ '#1b0',
+ '11bb00',
+ ];
+
+ yield [
+ '#1B0',
+ '11bb00',
+ ];
+
+ yield [
+ '#1ab1ab',
+ '1ab1ab',
+ ];
+
+ yield [
+ '#1AB1AB',
+ '1ab1ab',
+ ];
+
+ yield [
+ '#000',
+ '000000',
+ ];
+ }
+
+ /**
+ * Provides empty non color-related value
+ *
+ * @return Generator
+ */
+ public function provideColorEmptyValue()
+ {
+ yield [
+ '',
+ ];
+
+ yield [
+ 0,
+ ];
+
+ yield [
+ '0',
+ ];
+
+ yield [
+ false,
+ ];
+ }
+
+ /**
+ * Provides value of color with incorrect length
+ *
+ * @return Generator
+ */
+ public function provideColorIncorrectLength()
+ {
+ yield [
+ '12',
+ ];
+
+ yield [
+ '1234',
+ ];
+
+ yield [
+ '12345678',
+ ];
+
+ yield [
+ '#12',
+ ];
+
+ yield [
+ '#1234',
+ ];
+
+ yield [
+ '#12345678',
+ ];
+ }
+
+ /**
+ * Provides invalid value of color
+ *
+ * @return Generator
+ */
+ public function provideColorInvalidValue()
+ {
+ yield [
+ '#qwerty',
+ ];
+
+ yield [
+ 'qwerty',
+ ];
+ }
+
+ /**
+ * Provides e-mail and information if it's valid
+ *
+ * @return Generator
+ */
+ public function provideEmail()
+ {
+ yield [
+ '1',
+ false,
+ ];
+
+ yield [
+ 1,
+ false,
+ ];
+
+ yield [
+ 'a@a',
+ false,
+ ];
+
+ yield [
+ 'a@a.com',
+ false,
+ ];
+
+ yield [
+ 'aa@a.com',
+ true,
+ ];
+
+ yield [
+ 'a.b@d.com',
+ true,
+ ];
+ }
+
+ /**
+ * Provides empty non money-related value
+ *
+ * @return Generator
+ */
+ public function provideEmptyNonMoneyValue()
+ {
+ yield [''];
+ yield [' '];
+ yield [null];
+ yield [false];
+ yield [[]];
+ }
+
+ public function provideFileName(): ?Generator
+ {
+ yield [
+ 'An empty string',
+ '',
+ false,
+ ];
+
+ yield [
+ 'Path of this file, of file with test case',
+ __DIR__,
+ false,
+ ];
+
+ yield [
+ 'Name of this file, of file with test case',
+ __FILE__,
+ true,
+ ];
+
+ yield [
+ 'Complicated name of file',
+ 'this-1_2 3 & my! 4+file.jpg',
+ true,
+ ];
+
+ yield [
+ 'Complicated name of file',
+ 'directory1/directory2/this-1_2 3 & my! 4+file.jpg',
+ true,
+ ];
+ }
+
+ /**
+ * Provides html attribute and information if it's valid
+ *
+ * @return Generator
+ */
+ public function provideHtmlAttribute()
+ {
+ yield [
+ 'abc = def',
+ false,
+ ];
+
+ yield [
+ 'a b c=def',
+ false,
+ ];
+
+ yield [
+ 'abc=def',
+ false,
+ ];
+
+ yield [
+ 'a1b2c=d3e4f',
+ false,
+ ];
+
+ yield [
+ 'abc="def"',
+ true,
+ ];
+
+ yield [
+ 'a1b2c="d3e4f"',
+ true,
+ ];
+ }
+
+ /**
+ * Provides html attribute and information if attributes are valid
+ *
+ * @return Generator
+ */
+ public function provideHtmlAttributes()
+ {
+ yield [
+ 'abc = def',
+ false,
+ ];
+
+ yield [
+ 'abc = def ghi = jkl',
+ false,
+ ];
+
+ yield [
+ 'abc=def ghi=jkl',
+ false,
+ ];
+
+ yield [
+ 'abc=def ghi=jkl mno=pqr',
+ false,
+ ];
+
+ yield [
+ 'abc="def"',
+ true,
+ ];
+
+ yield [
+ 'abc="def" ghi="jkl"',
+ true,
+ ];
+
+ yield [
+ 'abc="def" ghi="jkl" mno="pqr"',
+ true,
+ ];
+
+ yield [
+ 'a2bc="d4ef" ghi="j k l" mno="pq9r"',
+ true,
+ ];
+ }
+
+ /**
+ * Provides money-related value and information if the value is valid
+ *
+ * @return Generator
+ */
+ public function provideMoneyValue()
+ {
+ yield [
+ 'abc',
+ false,
+ ];
+
+ yield [
+ '-a.b',
+ false,
+ ];
+
+ yield [
+ 'a,b',
+ false,
+ ];
+
+ yield [
+ 0,
+ true,
+ ];
+
+ yield [
+ 1,
+ true,
+ ];
+
+ yield [
+ -1,
+ true,
+ ];
+
+ yield [
+ 1.2,
+ true,
+ ];
+
+ yield [
+ 1.202,
+ true,
+ ];
+
+ yield [
+ -1.202,
+ true,
+ ];
+
+ yield [
+ '0',
+ true,
+ ];
+
+ yield [
+ '1',
+ true,
+ ];
+
+ yield [
+ '-1',
+ true,
+ ];
+
+ yield [
+ '1.2',
+ true,
+ ];
+
+ yield [
+ '1.202',
+ true,
+ ];
+
+ yield [
+ '-1.202',
+ true,
+ ];
+
+ yield [
+ '1,202',
+ true,
+ ];
+
+ yield [
+ '-1,2',
+ true,
+ ];
+
+ yield [
+ '-1,202',
+ true,
+ ];
+ }
+
+ /**
+ * Provides pattern and array with keys that should match that pattern
+ *
+ * @return Generator
+ */
+ public function providePatternForArrayKeys()
+ {
+ yield [
+ '/\d/',
+ [],
+ [],
+ ];
+
+ yield [
+ '/\d+/',
+ [
+ 'lorem' => 'ipsum',
+ 'dolor' => 123,
+ 'sit',
+ 4 => '456',
+ ],
+ [
+ 0 => 'sit',
+ 4 => '456',
+ ],
+ ];
+
+ yield [
+ '/\d+-[a-z]+/',
+ [
+ 'lorem',
+ '456-ipsum' => 123,
+ '001-sit' => false,
+ 'dolor',
+ ],
+ [
+ '456-ipsum' => 123,
+ '001-sit' => false,
+ ],
+ ];
+ }
+
+ /**
+ * Provides pattern and array with values that should match that pattern
+ *
+ * @return Generator
+ */
+ public function providePatternForArrayValues()
+ {
+ yield [
+ '/\d/',
+ [],
+ [],
+ ];
+
+ yield [
+ '/\d+/',
+ [
+ 'lorem',
+ 'ipsum',
+ 123,
+ 'dolor',
+ '456',
+ ],
+ [
+ 2 => 123,
+ 4 => '456',
+ ],
+ ];
+
+ yield [
+ '/\d+-[a-z]+/',
+ [
+ 'lorem',
+ 123,
+ false,
+ 'dolor',
+ '456-ipsum',
+ ],
+ [
+ 4 => '456-ipsum',
+ ],
+ ];
+ }
+
+ /**
+ * Provides patterns and subject for the pregMultiMatch() method
+ *
+ * @return Generator
+ */
+ public function providePatternsAndSubjectForPregMultiMatch()
+ {
+ yield [
+ '',
+ '',
+ false,
+ ];
+
+ yield [
+ [],
+ '',
+ false,
+ ];
+
+ yield [
+ '/\d+/',
+ 'Lorem ipsum dolor sit',
+ false,
+ ];
+
+ yield [
+ [
+ '/\d+/',
+ '/^[a-z]{4}$/',
+ ],
+ 'Lorem ipsum dolor sit',
+ false,
+ ];
+
+ yield [
+ '/\w+/',
+ 'Lorem ipsum dolor sit',
+ true,
+ ];
+
+ yield [
+ [
+ '/\d+/',
+ '/\w+/',
+ ],
+ 'Lorem ipsum dolor sit',
+ true,
+ ];
+ }
+
+ /**
+ * Provides patterns and subject for the pregMultiMatch() method when must match all patterns
+ *
+ * @return Generator
+ */
+ public function providePatternsAndSubjectForPregMultiMatchWhenMustMatchAllPatterns()
+ {
+ yield [
+ '',
+ '',
+ false,
+ ];
+
+ yield [
+ [],
+ '',
+ false,
+ ];
+
+ yield [
+ '/\d+/',
+ 'Lorem ipsum dolor sit',
+ false,
+ ];
+
+ yield [
+ [
+ '/\d+/',
+ '/^[a-z]{4}$/',
+ ],
+ 'Lorem ipsum dolor sit',
+ false,
+ ];
+
+ yield [
+ '/\w+/',
+ 'Lorem ipsum dolor sit',
+ true,
+ ];
+
+ yield [
+ [
+ '/[a-zA-Z ]+/',
+ '/\w+/',
+ ],
+ 'Lorem ipsum dolor sit',
+ true,
+ ];
+ }
+
+ /**
+ * Provides phone number and information if it's valid
+ *
+ * @return Generator
+ */
+ public function providePhoneNumber()
+ {
+ yield [
+ 'abc',
+ false,
+ ];
+
+ yield [
+ '1-2-3',
+ false,
+ ];
+
+ yield [
+ '123',
+ true,
+ ];
+
+ yield [
+ '123 456 789',
+ true,
+ ];
+
+ yield [
+ '123456789',
+ true,
+ ];
+ }
+
+ /**
+ * Provides regular expression for array filtering and the array
+ *
+ * @return Generator
+ */
+ public function provideRegularExpressionForArrayFiltering()
+ {
+ yield [
+ [],
+ 'id',
+ '/\d+/',
+ [],
+ ];
+
+ yield [
+ [
+ [
+ 'id' => 1,
+ 'first_name' => 'Jane',
+ 'last_name' => 'Scott',
+ 'is_active' => true,
+ ],
+ [
+ 'id' => 2,
+ 'first_name' => 'George',
+ 'last_name' => 'Brown',
+ 'is_active' => true,
+ ],
+ [
+ 'id' => 3,
+ 'first_name' => 'Mike',
+ 'last_name' => 'Green',
+ 'is_active' => false,
+ ],
+ ],
+ 'birth_date',
+ '/\d+/',
+ [
+ [
+ 'id' => 1,
+ 'first_name' => 'Jane',
+ 'last_name' => 'Scott',
+ 'is_active' => true,
+ ],
+ [
+ 'id' => 2,
+ 'first_name' => 'George',
+ 'last_name' => 'Brown',
+ 'is_active' => true,
+ ],
+ [
+ 'id' => 3,
+ 'first_name' => 'Mike',
+ 'last_name' => 'Green',
+ 'is_active' => false,
+ ],
+ ],
+ ];
+
+ yield [
+ [
+ [
+ 'id' => 1,
+ 'first_name' => 'Jane',
+ 'last_name' => 'Scott',
+ 'is_active' => true,
+ ],
+ [
+ 'id' => 123,
+ 'first_name' => 'George',
+ 'last_name' => 'Brown',
+ 'is_active' => true,
+ ],
+ [
+ 'id' => 3,
+ 'first_name' => 'Mike',
+ 'last_name' => 'Green',
+ 'is_active' => false,
+ ],
+ ],
+ 'id',
+ '/\d{3}/',
+ [
+ 1 => [
+ 'id' => 123,
+ 'first_name' => 'George',
+ 'last_name' => 'Brown',
+ 'is_active' => true,
+ ],
+ ],
+ ];
+
+ yield [
+ [
+ [
+ 'id' => 1,
+ 'first_name' => 'Jane',
+ 'last_name' => 'Scott',
+ 'is_active' => true,
+ ],
+ [
+ 'id' => 123,
+ 'first_name' => 'George',
+ 'last_name' => 'Brown',
+ 'is_active' => true,
+ ],
+ [
+ 'id' => 456,
+ 'first_name' => 'Mike',
+ 'last_name' => 'Green',
+ 'is_active' => false,
+ ],
+ ],
+ 'first_name',
+ '/George|Mike/',
+ [
+ 1 => [
+ 'id' => 123,
+ 'first_name' => 'George',
+ 'last_name' => 'Brown',
+ 'is_active' => true,
+ ],
+ 2 => [
+ 'id' => 456,
+ 'first_name' => 'Mike',
+ 'last_name' => 'Green',
+ 'is_active' => false,
+ ],
+ ],
+ ];
+
+ yield [
+ [
+ [
+ 'id' => 1,
+ 'first_name' => 'Jane',
+ 'last_name' => 'Scott',
+ 'is_active' => true,
+ ],
+ [
+ 'id' => 2,
+ 'first_name' => 'George',
+ 'last_name' => 'Brown',
+ 'is_active' => true,
+ ],
+ [
+ 'id' => 3,
+ 'first_name' => 'Mike',
+ 'last_name' => 'Green-Blue',
+ 'is_active' => false,
+ ],
+ ],
+ 'last_name',
+ '/\w+-\w+/',
+ [
+ 2 => [
+ 'id' => 3,
+ 'first_name' => 'Mike',
+ 'last_name' => 'Green-Blue',
+ 'is_active' => false,
+ ],
+ ],
+ ];
+ }
+
+ /**
+ * Provides simple compare expression for array filtering and the array
+ *
+ * @return Generator
+ */
+ public function provideSimpleExpressionForArrayFiltering()
+ {
+ yield [
+ [],
+ 'id',
+ ' == 2',
+ [],
+ ];
+
+ yield [
+ [
+ [
+ 'id' => 1,
+ 'first_name' => 'Jane',
+ 'last_name' => 'Scott',
+ 'is_active' => true,
+ ],
+ [
+ 'id' => 2,
+ 'first_name' => 'George',
+ 'last_name' => 'Brown',
+ 'is_active' => true,
+ ],
+ [
+ 'id' => 3,
+ 'first_name' => 'Mike',
+ 'last_name' => 'Green',
+ 'is_active' => false,
+ ],
+ ],
+ 'birth_date',
+ ' == 2',
+ [
+ [
+ 'id' => 1,
+ 'first_name' => 'Jane',
+ 'last_name' => 'Scott',
+ 'is_active' => true,
+ ],
+ [
+ 'id' => 2,
+ 'first_name' => 'George',
+ 'last_name' => 'Brown',
+ 'is_active' => true,
+ ],
+ [
+ 'id' => 3,
+ 'first_name' => 'Mike',
+ 'last_name' => 'Green',
+ 'is_active' => false,
+ ],
+ ],
+ ];
+
+ yield [
+ [
+ [
+ 'id' => 1,
+ 'first_name' => 'Jane',
+ 'last_name' => 'Scott',
+ 'is_active' => true,
+ ],
+ [
+ 'id' => 2,
+ 'first_name' => 'George',
+ 'last_name' => 'Brown',
+ 'is_active' => true,
+ ],
+ [
+ 'id' => 3,
+ 'first_name' => 'Mike',
+ 'last_name' => 'Green',
+ 'is_active' => false,
+ ],
+ ],
+ 'id',
+ ' == 2',
+ [
+ 1 => [
+ 'id' => 2,
+ 'first_name' => 'George',
+ 'last_name' => 'Brown',
+ 'is_active' => true,
+ ],
+ ],
+ ];
+
+ yield [
+ [
+ [
+ 'id' => 1,
+ 'first_name' => 'Jane',
+ 'last_name' => 'Scott',
+ 'is_active' => true,
+ ],
+ [
+ 'id' => 2,
+ 'first_name' => 'George',
+ 'last_name' => 'Brown',
+ 'is_active' => true,
+ ],
+ [
+ 'id' => 3,
+ 'first_name' => 'Mike',
+ 'last_name' => 'Green',
+ 'is_active' => false,
+ ],
+ ],
+ 'id',
+ ' >= 2',
+ [
+ 1 => [
+ 'id' => 2,
+ 'first_name' => 'George',
+ 'last_name' => 'Brown',
+ 'is_active' => true,
+ ],
+ 2 => [
+ 'id' => 3,
+ 'first_name' => 'Mike',
+ 'last_name' => 'Green',
+ 'is_active' => false,
+ ],
+ ],
+ ];
+
+ yield [
+ [
+ [
+ 'id' => 1,
+ 'first_name' => 'Jane',
+ 'last_name' => 'Scott',
+ 'is_active' => true,
+ ],
+ [
+ 'id' => 2,
+ 'first_name' => 'George',
+ 'last_name' => 'Brown',
+ 'is_active' => true,
+ ],
+ [
+ 'id' => 3,
+ 'first_name' => 'Mike',
+ 'last_name' => 'Green',
+ 'is_active' => false,
+ ],
+ ],
+ 'is_active',
+ ' !== true',
+ [
+ 2 => [
+ 'id' => 3,
+ 'first_name' => 'Mike',
+ 'last_name' => 'Green',
+ 'is_active' => false,
+ ],
+ ],
+ ];
+
+ yield [
+ [
+ [
+ 'id' => 1,
+ 'first_name' => 'Jane',
+ 'last_name' => 'Scott',
+ 'is_active' => true,
+ ],
+ [
+ 'id' => 2,
+ 'first_name' => 'George',
+ 'last_name' => 'Brown',
+ 'is_active' => true,
+ ],
+ [
+ 'id' => 3,
+ 'first_name' => 'Mike',
+ 'last_name' => 'Green',
+ 'is_active' => false,
+ ],
+ ],
+ 'first_name',
+ ' == \'Mike\'',
+ [
+ 2 => [
+ 'id' => 3,
+ 'first_name' => 'Mike',
+ 'last_name' => 'Green',
+ 'is_active' => false,
+ ],
+ ],
+ ];
+ }
+
+ public function provideSizeToVerify()
+ {
+ yield [
+ 'One number only',
+ 200,
+ ' x ',
+ false,
+ ];
+
+ yield [
+ 'One number only as string',
+ '200',
+ ' x ',
+ false,
+ ];
+
+ yield [
+ 'The " " as invalid separator',
+ '200 100',
+ ' x ',
+ false,
+ ];
+
+ yield [
+ 'The "|" as separator (invalid separator)',
+ '200 | 100',
+ ' x ',
+ false,
+ ];
+
+ yield [
+ 'The "|" as invalid separator and no spaces around separator',
+ '200|100',
+ ' x ',
+ false,
+ ];
+
+ yield [
+ 'The "X" as invalid separator',
+ '200 X 100',
+ ' x ',
+ false,
+ ];
+
+ yield [
+ 'Simple, valid size',
+ '200 x 100',
+ ' x ',
+ true,
+ ];
+
+ yield [
+ 'Too much spaces at the right of separator',
+ '200 x 100',
+ ' x ',
+ true,
+ ];
+
+ yield [
+ 'Too much spaces at the left of separator',
+ '200 x 100',
+ ' x ',
+ true,
+ ];
+
+ yield [
+ 'Too much spaces around separator',
+ '200 x 100',
+ ' x ',
+ true,
+ ];
+
+ yield [
+ 'Too much spaces before width',
+ ' 200 x 100',
+ ' x ',
+ true,
+ ];
+
+ yield [
+ 'Too much spaces after height',
+ '200 x 100 ',
+ ' x ',
+ true,
+ ];
+
+ yield [
+ 'Too much spaces before width and after height',
+ ' 200 x 100 ',
+ ' x ',
+ true,
+ ];
+
+ yield [
+ 'Too much spaces everywhere (1st)',
+ ' 200 x 100 ',
+ ' x ',
+ true,
+ ];
+
+ yield [
+ 'Too much spaces everywhere (2nd)',
+ ' 200 x 100 ',
+ ' x ',
+ true,
+ ];
+
+ yield [
+ 'Too much spaces everywhere (3rd)',
+ ' 200 x 100 ',
+ ' x ',
+ true,
+ ];
+
+ yield [
+ 'The " X " as custom separator',
+ '200 X 100',
+ ' X ',
+ true,
+ ];
+
+ yield [
+ 'The "|" as custom separator',
+ '200|100',
+ '|',
+ true,
+ ];
+
+ yield [
+ 'The " | " as custom separator',
+ '200 | 100',
+ ' | ',
+ true,
+ ];
+
+ yield [
+ 'The "::" as custom separator',
+ '200::100',
+ '::',
+ true,
+ ];
+
+ yield [
+ 'The " :: " as custom separator',
+ '200 :: 100',
+ ' :: ',
+ true,
+ ];
+
+ yield [
+ 'The "." as custom separator',
+ '200.100',
+ '.',
+ true,
+ ];
+
+ yield [
+ 'The " . " as custom separator',
+ '200 . 100',
+ ' . ',
+ true,
+ ];
+
+ yield [
+ 'The "/" as custom separator',
+ '200/100',
+ '/',
+ true,
+ ];
+
+ yield [
+ 'The " / " as custom separator',
+ '200 / 100',
+ ' / ',
+ true,
+ ];
+
+ yield [
+ 'The " : " as custom separator and too much spaces everywhere',
+ ' 200 : 100 ',
+ ' : ',
+ true,
+ ];
+ }
+
+ public function provideStringToClearBeginningSlash(): ?Generator
+ {
+ yield [
+ '',
+ '',
+ ];
+
+ yield [
+ '/',
+ '',
+ ];
+
+ yield [
+ '\\',
+ '\\',
+ ];
+
+ yield [
+ '//',
+ '/',
+ ];
+
+ yield [
+ 'lorem ipsum',
+ 'lorem ipsum',
+ ];
+
+ yield [
+ '1234',
+ '1234',
+ ];
+
+ yield [
+ 'lorem/ipsum',
+ 'lorem/ipsum',
+ ];
+
+ yield [
+ 'lorem / ipsum',
+ 'lorem / ipsum',
+ ];
+
+ yield [
+ 'lorem\ipsum',
+ 'lorem\ipsum',
+ ];
+
+ yield [
+ 'lorem \ ipsum',
+ 'lorem \ ipsum',
+ ];
+
+ yield [
+ '\lorem ipsum',
+ '\lorem ipsum',
+ ];
+
+ yield [
+ '\ lorem ipsum',
+ '\ lorem ipsum',
+ ];
+
+ yield [
+ 'lorem ipsum/',
+ 'lorem ipsum/',
+ ];
+
+ yield [
+ 'lorem ipsum /',
+ 'lorem ipsum /',
+ ];
+
+ yield [
+ '/lorem ipsum',
+ 'lorem ipsum',
+ ];
+
+ yield [
+ '/ lorem ipsum',
+ ' lorem ipsum',
+ ];
+
+ yield [
+ '/123 456',
+ '123 456',
+ ];
+
+ yield [
+ '/ 123 456',
+ ' 123 456',
+ ];
+
+ yield [
+ '/lorem 123 ipsum 456',
+ 'lorem 123 ipsum 456',
+ ];
+
+ yield [
+ '/ lorem 123 ipsum 456',
+ ' lorem 123 ipsum 456',
+ ];
+ }
+
+ public function provideStringToClearEndingSlash(): ?Generator
+ {
+ yield [
+ '',
+ '',
+ ];
+
+ yield [
+ '/',
+ '',
+ ];
+
+ yield [
+ '\\',
+ '\\',
+ ];
+
+ yield [
+ '//',
+ '/',
+ ];
+
+ yield [
+ 'lorem ipsum',
+ 'lorem ipsum',
+ ];
+
+ yield [
+ '1234',
+ '1234',
+ ];
+
+ yield [
+ 'lorem/ipsum',
+ 'lorem/ipsum',
+ ];
+
+ yield [
+ 'lorem / ipsum',
+ 'lorem / ipsum',
+ ];
+
+ yield [
+ 'lorem\ipsum',
+ 'lorem\ipsum',
+ ];
+
+ yield [
+ 'lorem \ ipsum',
+ 'lorem \ ipsum',
+ ];
+
+ yield [
+ '\lorem ipsum',
+ '\lorem ipsum',
+ ];
+
+ yield [
+ '\ lorem ipsum',
+ '\ lorem ipsum',
+ ];
+
+ yield [
+ '/lorem ipsum',
+ '/lorem ipsum',
+ ];
+
+ yield [
+ '/ lorem ipsum',
+ '/ lorem ipsum',
+ ];
+
+ yield [
+ 'lorem ipsum/',
+ 'lorem ipsum',
+ ];
+
+ yield [
+ 'lorem ipsum /',
+ 'lorem ipsum ',
+ ];
+
+ yield [
+ '123 456/',
+ '123 456',
+ ];
+
+ yield [
+ '123 456 /',
+ '123 456 ',
+ ];
+
+ yield [
+ 'lorem 123 ipsum 456/',
+ 'lorem 123 ipsum 456',
+ ];
+
+ yield [
+ 'lorem 123 ipsum 456 /',
+ 'lorem 123 ipsum 456 ',
+ ];
+ }
+
+ /**
+ * Provides tax ID and information if it's valid
+ *
+ * @return Generator
+ */
+ public function provideTaxId()
+ {
+ yield [
+ '123',
+ false,
+ ];
+
+ yield [
+ '12345',
+ false,
+ ];
+
+ yield [
+ '1122334455',
+ false,
+ ];
+
+ yield [
+ '1234567890',
+ false,
+ ];
+
+ yield [
+ '0987654321',
+ false,
+ ];
+
+ // Microsoft sp. z o.o.
+ yield [
+ '5270103391',
+ true,
+ ];
+
+ // Onet S.A.
+ yield [
+ '7340009469',
+ true,
+ ];
+ }
+
+ /**
+ * Provide value to create slug
+ *
+ * @return Generator
+ */
+ public function provideValueSlug()
+ {
+ yield [
+ [],
+ false,
+ ];
+
+ yield [
+ null,
+ false,
+ ];
+
+ yield [
+ '',
+ '',
+ ];
+
+ yield [
+ 1234,
+ '1234',
+ ];
+
+ yield [
+ '1234',
+ '1234',
+ ];
+
+ yield [
+ '1/2/3/4',
+ '1234',
+ ];
+
+ yield [
+ '1 / 2 / 3 / 4',
+ '1-2-3-4',
+ ];
+
+ yield [
+ 'test',
+ 'test',
+ ];
+
+ yield [
+ 'test test',
+ 'test-test',
+ ];
+
+ yield [
+ 'lorem ipsum dolor sit',
+ 'lorem-ipsum-dolor-sit',
+ ];
+
+ yield [
+ 'Lorem ipsum. Dolor sit 12.34 amet.',
+ 'lorem-ipsum-dolor-sit-1234-amet',
+ ];
+
+ yield [
+ 'Was sind Löwen, Bären, Vögel und Käfer (für die Prüfung)?',
+ 'was-sind-lowen-baren-vogel-und-kafer-fur-die-prufung',
+ ];
+
+ yield [
+ 'äöü (ÄÖÜ)',
+ 'aou-aou',
+ ];
+
+ yield [
+ 'Półka dębowa. Kolor: żółędziowy. Wymiary: 80 x 30 cm.',
+ 'polka-debowa-kolor-zoledziowy-wymiary-80-x-30-cm',
+ ];
+
+ yield [
+ 'ąęółńśżźć (ĄĘÓŁŃŚŻŹĆ)',
+ 'aeolnszzc-aeolnszzc',
+ ];
+ }
+
+ /**
+ * @param string $htmlAttributes The html attributes to verify
+ * @param bool $expected Information if attributes are valid
+ *
+ * @dataProvider provideHtmlAttributes
+ */
+ public static function testAreValidHtmlAttributes($htmlAttributes, $expected)
+ {
+ self::assertEquals($expected, Regex::areValidHtmlAttributes($htmlAttributes));
+ }
+
+ /**
+ * @param mixed $emptyValue Empty value, e.g. ""
+ * @dataProvider provideEmptyValue
+ */
+ public static function testAreValidHtmlAttributesUsingEmptyValue($emptyValue)
+ {
+ self::assertFalse(Regex::areValidHtmlAttributes($emptyValue));
+ }
+
+ /**
+ * @param array $array The array that should be filtered
+ * @param string $arrayColumnKey Column name
+ * @param string $filterExpression Regular expression, e.g. "/\d+/" or "/[a-z]+[,;]{2,}/"
+ * @param array $expected Expected array
+ *
+ * @dataProvider provideRegularExpressionForArrayFiltering
+ */
+ public function testArrayFilterUsingRegularExpression($array, $arrayColumnKey, $filterExpression, $expected)
+ {
+ self::assertEquals($expected, Regex::arrayFilter($array, $arrayColumnKey, $filterExpression, true));
+ }
+
+ /**
+ * @param array $array The array that should be filtered
+ * @param string $arrayColumnKey Column name
+ * @param string $filterExpression Simple filter expression, e.g. "== 2" or "!= \'home\'"
+ * @param array $expected Expected array
+ *
+ * @dataProvider provideSimpleExpressionForArrayFiltering
+ */
+ public function testArrayFilterUsingSimpleExpression($array, $arrayColumnKey, $filterExpression, $expected)
+ {
+ self::assertEquals($expected, Regex::arrayFilter($array, $arrayColumnKey, $filterExpression));
+ }
+
+ public function testCamelCase2humanReadable()
+ {
+ self::assertEquals('', Regex::camelCase2humanReadable(''));
+ self::assertEquals('lorem', Regex::camelCase2humanReadable('lorem'));
+
+ self::assertEquals($this->simpleText, Regex::camelCase2humanReadable($this->camelCaseText));
+ self::assertEquals(ucfirst($this->simpleText), Regex::camelCase2humanReadable($this->camelCaseText, true));
+ }
+
+ public function testCamelCase2simpleLowercase()
+ {
+ self::assertEquals('', Regex::camelCase2simpleLowercase(''));
+ self::assertEquals('lorem', Regex::camelCase2simpleLowercase('lorem'));
+ self::assertEquals('Lorem', Regex::camelCase2simpleLowercase('Lorem', '', false));
+ self::assertEquals('lorem-ipsum-dolor-sit', Regex::camelCase2simpleLowercase($this->camelCaseText, '-'));
+ self::assertEquals('lorem-Ipsum-Dolor-Sit', Regex::camelCase2simpleLowercase($this->camelCaseText, '-', false));
+ }
+
+ /**
+ * @param string $string
+ * @param string $expected
+ *
+ * @dataProvider provideStringToClearBeginningSlash
+ */
+ public function testClearBeginningSlash(string $string, string $expected): void
+ {
+ static::assertSame($expected, Regex::clearBeginningSlash($string));
+ }
+
+ /**
+ * @param string $string
+ * @param string $expected
+ *
+ * @dataProvider provideStringToClearEndingSlash
+ */
+ public function testClearEndingSlash(string $string, string $expected): void
+ {
+ static::assertSame($expected, Regex::clearEndingSlash($string));
+ }
+
public function testConstructor()
{
static::assertHasNoConstructor(Regex::class);
}
+ public function testContains()
+ {
+ self::assertTrue(Regex::contains($this->simpleText, 'ipsum'));
+ self::assertFalse(Regex::contains($this->simpleText, 'neque'));
+
+ self::assertFalse(Regex::contains($this->simpleText, '.'));
+ self::assertTrue(Regex::contains($this->simpleText, 'l'));
+ }
+
+ public function testContainsEntities()
+ {
+ self::assertFalse(Regex::containsEntities('Lorem ipsum'));
+ self::assertTrue(Regex::containsEntities('Lorem ipsum »'));
+ }
+
+ /**
+ * @param string $value Value that should be transformed to slug
+ * @param string $expected Expected slug
+ *
+ * @dataProvider provideValueSlug
+ */
+ public function testCreateSlug($value, $expected)
+ {
+ self::assertSame($expected, Regex::createSlug($value));
+ }
+
+ public function testEndsWith()
+ {
+ self::assertFalse(Regex::endsWith($this->simpleText, '\.\.\.'));
+ self::assertFalse(Regex::endsWith($this->simpleText, '\.'));
+ self::assertTrue(Regex::endsWith($this->simpleText, 't'));
+ }
+
+ public function testEndsWithDirectorySeparator()
+ {
+ // Not provided, default separator
+ self::assertTrue(Regex::endsWithDirectorySeparator('my simple text/'));
+ self::assertFalse(Regex::endsWithDirectorySeparator('my simple text'));
+
+ // Slash as separator
+ $separatorSlash = '/';
+
+ self::assertTrue(Regex::endsWithDirectorySeparator('my simple text/', $separatorSlash));
+ self::assertFalse(Regex::endsWithDirectorySeparator('my simple text', $separatorSlash));
+
+ // Backslash as separator
+ $separatorBackslash = '\\';
+
+ self::assertTrue(Regex::endsWithDirectorySeparator('my simple text\\', $separatorBackslash));
+ self::assertFalse(Regex::endsWithDirectorySeparator('my simple text', $separatorBackslash));
+ }
+
+ /**
+ * @param string $pattern Pattern to match
+ * @param array $dataArray The array
+ * @param array $expected Expected array
+ *
+ * @dataProvider providePatternForArrayKeys
+ */
+ public static function testGetArrayValuesByPatternUsingKeys($pattern, array $dataArray, $expected)
+ {
+ self::assertEquals($expected, Regex::getArrayValuesByPattern($pattern, $dataArray, true));
+ }
+
+ /**
+ * @param string $pattern Pattern to match
+ * @param array $dataArray The array
+ * @param array $expected Expected array
+ *
+ * @dataProvider providePatternForArrayValues
+ */
+ public static function testGetArrayValuesByPatternUsingValues($pattern, array $dataArray, $expected)
+ {
+ self::assertEquals($expected, Regex::getArrayValuesByPattern($pattern, $dataArray));
+ }
+
+ public function testGetBundleNamePattern()
+ {
+ self::assertEquals('/^(([A-Z]{1}[a-z0-9]+)((?2))*)(Bundle)$/', Regex::getBundleNamePattern());
+ }
+
public function testGetCamelCaseParts()
{
$parts = [];
@@ -60,22 +1805,328 @@ class RegexTest extends BaseTestCase
self::assertEquals($parts, Regex::getCamelCaseParts($string));
}
- public function testCamelCase2humanReadable()
+ public function testGetHtmlAttributePattern()
{
- self::assertEquals('', Regex::camelCase2humanReadable(''));
- self::assertEquals('lorem', Regex::camelCase2humanReadable('lorem'));
-
- self::assertEquals($this->simpleText, Regex::camelCase2humanReadable($this->camelCaseText));
- self::assertEquals(ucfirst($this->simpleText), Regex::camelCase2humanReadable($this->camelCaseText, true));
+ self::assertEquals('/([\w-]+)="([\w -]+)"/', Regex::getHtmlAttributePattern());
}
- public function testCamelCase2simpleLowercase()
+ public function testGetMoneyPattern()
{
- self::assertEquals('', Regex::camelCase2simpleLowercase(''));
- self::assertEquals('lorem', Regex::camelCase2simpleLowercase('lorem'));
- self::assertEquals('Lorem', Regex::camelCase2simpleLowercase('Lorem', '', false));
- self::assertEquals('lorem-ipsum-dolor-sit', Regex::camelCase2simpleLowercase($this->camelCaseText, '-'));
- self::assertEquals('lorem-Ipsum-Dolor-Sit', Regex::camelCase2simpleLowercase($this->camelCaseText, '-', false));
+ self::assertEquals('/^[-+]?\d+([\.,]{1}\d*)?$/', Regex::getMoneyPattern());
+ }
+
+ public static function testGetUrlPatternWithProtocolRequired()
+ {
+ $pattern = '/^([a-z]+:\/\/)([\da-z\.-]+)\.([a-z\.]{2,6})(\/)?([\w\.\-]*)?(\?)?([\w \.\-\/=&]*)\/?$/i';
+ self::assertEquals($pattern, Regex::getUrlPattern(true));
+ }
+
+ public static function testGetUrlPatternWithoutProtocol()
+ {
+ $pattern = '/^([a-z]+:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})(\/)?([\w\.\-]*)?(\?)?([\w \.\-\/=&]*)\/?$/i';
+ self::assertEquals($pattern, Regex::getUrlPattern());
+ }
+
+ /**
+ * @param string $color Color to verify
+ * @param string $expected Expected value of color
+ *
+ * @dataProvider provideColor
+ */
+ public function testGetValidColorHexValue($color, $expected)
+ {
+ self::assertEquals($expected, Regex::getValidColorHexValue($color));
+ }
+
+ /**
+ * @param mixed $emptyValue Empty value, e.g. ""
+ * @dataProvider provideColorEmptyValue
+ */
+ public function testGetValidColorHexValueUsingEmptyValue($emptyValue)
+ {
+ $this->expectException(IncorrectColorHexLengthException::class);
+ Regex::getValidColorHexValue($emptyValue);
+ }
+
+ /**
+ * @param mixed $emptyValue Empty value, e.g. ""
+ * @dataProvider provideColorEmptyValue
+ */
+ public function testGetValidColorHexValueUsingEmptyValueWithoutException($emptyValue)
+ {
+ self::assertFalse(Regex::getValidColorHexValue($emptyValue, false));
+ }
+
+ /**
+ * @param string $incorrectColor Incorrect value of color
+ * @dataProvider provideColorIncorrectLength
+ */
+ public function testGetValidColorHexValueUsingIncorrectValue($incorrectColor)
+ {
+ $this->expectException(IncorrectColorHexLengthException::class);
+ Regex::getValidColorHexValue($incorrectColor);
+ }
+
+ /**
+ * @param string $incorrectColor Incorrect value of color
+ * @dataProvider provideColorIncorrectLength
+ */
+ public function testGetValidColorHexValueUsingIncorrectValueWithoutException($incorrectColor)
+ {
+ self::assertFalse(Regex::getValidColorHexValue($incorrectColor, false));
+ }
+
+ /**
+ * @param string $invalidColor Invalid value of color
+ * @dataProvider provideColorInvalidValue
+ */
+ public function testGetValidColorHexValueUsingInvalidValue($invalidColor)
+ {
+ $this->expectException(InvalidColorHexValueException::class);
+ Regex::getValidColorHexValue($invalidColor);
+ }
+
+ /**
+ * @param string $invalidColor Invalid value of color
+ * @dataProvider provideColorInvalidValue
+ */
+ public function testGetValidColorHexValueUsingInvalidValueWithoutException($invalidColor)
+ {
+ self::assertFalse(Regex::getValidColorHexValue($invalidColor, false));
+ }
+
+ /**
+ * @param mixed $nonScalarValue Non scalar value, e.g. [] or null
+ * @dataProvider provideNonScalarValue
+ */
+ public function testGetValidColorHexValueUsingNonScalarValue($nonScalarValue)
+ {
+ self::assertFalse(Regex::getValidColorHexValue($nonScalarValue));
+ }
+
+ /**
+ * @param string $value Value to verify
+ * @param bool $expected Information if value is a binary value
+ *
+ * @dataProvider provideBinaryValue
+ */
+ public static function testIsBinaryValue($value, $expected)
+ {
+ self::assertEquals($expected, Regex::isBinaryValue($value));
+ }
+
+ /**
+ * @param string $description Description of test
+ * @param string $fileName
+ * @param bool $expected Expected result
+ *
+ * @dataProvider provideFileName
+ */
+ public function testIsFileName(string $description, string $fileName, bool $expected): void
+ {
+ static::assertSame($expected, Regex::isFileName($fileName), $description);
+ }
+
+ public function testIsLetterOrDigit()
+ {
+ self::assertTrue(Regex::isLetterOrDigit('a'));
+ self::assertTrue(Regex::isLetterOrDigit(10));
+ self::assertFalse(Regex::isLetterOrDigit(';'));
+ }
+
+ public function testIsQuoted()
+ {
+ self::assertTrue(Regex::isQuoted('\'lorem ipsum\''));
+ self::assertTrue(Regex::isQuoted('"lorem ipsum"'));
+
+ self::assertFalse(Regex::isQuoted('lorem ipsum'));
+ self::assertFalse(Regex::isQuoted(new stdClass()));
+ }
+
+ public function testIsSetUriParameter()
+ {
+ $uri = 'www.domain.com/?name=phil&type=4';
+
+ $parameterName = 'type';
+ self::assertTrue(Regex::isSetUriParameter($uri, $parameterName));
+
+ $parameterName = 'color';
+ self::assertFalse(Regex::isSetUriParameter($uri, $parameterName));
+ }
+
+ /**
+ * @param string $description Description of test
+ * @param string $value Value to verify
+ * @param string $separator Separator used to split width and height
+ * @param bool $expected Expected result of verification
+ *
+ * @dataProvider provideSizeToVerify
+ */
+ public function testIsSizeValue($description, $value, $separator, $expected)
+ {
+ self::assertEquals($expected, Regex::isSizeValue($value, $separator), $description);
+ }
+
+ /**
+ * @param mixed $emptyValue Empty value, e.g. ""
+ * @dataProvider provideEmptyValue
+ */
+ public static function testIsSizeValueUsingEmptyValue($emptyValue)
+ {
+ self::assertFalse(Regex::isSizeValue($emptyValue));
+ }
+
+ public function testIsSubPathOf()
+ {
+ self::assertFalse(Regex::isSubPathOf(null, null));
+ self::assertFalse(Regex::isSubPathOf('', ''));
+
+ self::assertFalse(Regex::isSubPathOf('', '/my/directory'));
+ self::assertFalse(Regex::isSubPathOf('/my/file', ''));
+ self::assertFalse(Regex::isSubPathOf('/my/file', '/my/directory'));
+
+ self::assertTrue(Regex::isSubPathOf('/my/directory', '/my/directory'));
+ self::assertTrue(Regex::isSubPathOf('/my/directory/', '/my/directory'));
+ self::assertTrue(Regex::isSubPathOf('/my/directory', '/my/directory/'));
+ self::assertTrue(Regex::isSubPathOf('/my/directory/', '/my/directory/'));
+
+ self::assertTrue(Regex::isSubPathOf('/my/another/directory/another/file', '/my/another/directory'));
+ }
+
+ /**
+ * @param string $bundleName Full name of bundle to verify, e.g. "MyExtraBundle"
+ * @param bool $expected Information if it's valid name
+ *
+ * @dataProvider provideBundleName
+ */
+ public function testIsValidBundleName($bundleName, $expected)
+ {
+ self::assertEquals($expected, Regex::isValidBundleName($bundleName));
+ }
+
+ /**
+ * @param mixed $emptyValue Empty value, e.g. ""
+ * @dataProvider provideEmptyValue
+ */
+ public function testIsValidBundleNameUsingEmptyValue($emptyValue)
+ {
+ self::assertFalse(Regex::isValidBundleName($emptyValue));
+ }
+
+ /**
+ * @param string $email E-mail address to validate / verify
+ * @param bool $expected Information if e-mail is valid
+ *
+ * @dataProvider provideEmail
+ */
+ public static function testIsValidEmail($email, $expected)
+ {
+ self::assertEquals($expected, Regex::isValidEmail($email));
+ }
+
+ /**
+ * @param mixed $emptyValue Empty value, e.g. ""
+ * @dataProvider provideEmptyValue
+ */
+ public static function testIsValidEmailUsingEmptyValue($emptyValue)
+ {
+ self::assertFalse(Regex::isValidEmail($emptyValue));
+ }
+
+ /**
+ * @param string $htmlAttribute The html attribute to verify
+ * @param bool $expected Information if it's valid attribute
+ *
+ * @dataProvider provideHtmlAttribute
+ */
+ public function testIsValidHtmlAttribute($htmlAttribute, $expected)
+ {
+ self::assertEquals($expected, Regex::isValidHtmlAttribute($htmlAttribute));
+ }
+
+ /**
+ * @param mixed $emptyValue Empty value, e.g. ""
+ * @dataProvider provideEmptyValue
+ */
+ public function testIsValidHtmlAttributeUsingEmptyValue($emptyValue)
+ {
+ self::assertFalse(Regex::isValidHtmlAttribute($emptyValue));
+ }
+
+ /**
+ * @param mixed $value Value to verify
+ * @param bool $expected Information if given value is a money value
+ *
+ * @dataProvider provideMoneyValue
+ */
+ public function testIsValidMoneyValue($value, $expected)
+ {
+ self::assertEquals($expected, Regex::isValidMoneyValue($value));
+ }
+
+ /**
+ * @param mixed $emptyValue Empty value, e.g. ""
+ * @dataProvider provideEmptyNonMoneyValue
+ */
+ public function testIsValidMoneyValueUsingEmptyValue($emptyValue)
+ {
+ self::assertFalse(Regex::isValidMoneyValue($emptyValue));
+ }
+
+ public function testIsValidNip()
+ {
+ self::assertFalse(Regex::isValidNip(null));
+ self::assertFalse(Regex::isValidNip(''));
+ self::assertFalse(Regex::isValidNip(1234));
+ self::assertFalse(Regex::isValidNip(1234567890));
+ self::assertFalse(Regex::isValidNip(0000000000));
+ self::assertFalse(Regex::isValidNip('1234567890'));
+ self::assertFalse(Regex::isValidNip('0000000000'));
+ self::assertFalse(Regex::isValidNip('abc'));
+ self::assertFalse(Regex::isValidNip($this->simpleText));
+
+ self::assertTrue(Regex::isValidNip('7340009469')); // Onet S.A.
+ self::assertTrue(Regex::isValidNip('5252530705')); // Facebook Poland sp. z o.o.
+ }
+
+ /**
+ * @param string $phoneNumber The phone number to validate / verify
+ * @param bool $expected Information if phone number is valid
+ *
+ * @dataProvider providePhoneNumber
+ */
+ public static function testIsValidPhoneNumber($phoneNumber, $expected)
+ {
+ self::assertEquals($expected, Regex::isValidPhoneNumber($phoneNumber));
+ }
+
+ /**
+ * @param mixed $emptyValue Empty value, e.g. ""
+ * @dataProvider provideEmptyValue
+ */
+ public static function testIsValidPhoneNumberUsingEmptyValue($emptyValue)
+ {
+ self::assertFalse(Regex::isValidPhoneNumber($emptyValue));
+ }
+
+ /**
+ * @param string $taxIdString Tax ID (NIP) string
+ * @param bool $expected Information if tax ID is valid
+ *
+ * @dataProvider provideTaxId
+ */
+ public static function testIsValidTaxId($taxIdString, $expected)
+ {
+ self::assertEquals($expected, Regex::isValidTaxId($taxIdString));
+ }
+
+ /**
+ * @param mixed $emptyValue Empty value, e.g. ""
+ * @dataProvider provideEmptyValue
+ */
+ public static function testIsValidTaxIdUsingEmptyValue($emptyValue)
+ {
+ self::assertFalse(Regex::isValidTaxId($emptyValue));
}
public function testIsValidUrl()
@@ -120,28 +2171,37 @@ class RegexTest extends BaseTestCase
}
}
- public function testIsSubPathOf()
+ public function testIsWindowsBasedPath()
{
- self::assertFalse(Regex::isSubPathOf(null, null));
- self::assertFalse(Regex::isSubPathOf('', ''));
+ self::assertTrue(Regex::isWindowsBasedPath('C:\path\to\directory'));
+ self::assertTrue(Regex::isWindowsBasedPath('C:\path\to\file.jpg'));
- self::assertFalse(Regex::isSubPathOf('', '/my/directory'));
- self::assertFalse(Regex::isSubPathOf('/my/file', ''));
- self::assertFalse(Regex::isSubPathOf('/my/file', '/my/directory'));
-
- self::assertTrue(Regex::isSubPathOf('/my/directory', '/my/directory'));
- self::assertTrue(Regex::isSubPathOf('/my/directory/', '/my/directory'));
- self::assertTrue(Regex::isSubPathOf('/my/directory', '/my/directory/'));
- self::assertTrue(Regex::isSubPathOf('/my/directory/', '/my/directory/'));
-
- self::assertTrue(Regex::isSubPathOf('/my/another/directory/another/file', '/my/another/directory'));
+ self::assertFalse(Regex::isWindowsBasedPath('/path/to/directory'));
+ self::assertFalse(Regex::isWindowsBasedPath('/path/to/file.jpg'));
}
- public function testIsLetterOrDigit()
+ /**
+ * @param array|string $patterns The patterns to match
+ * @param string $subject The string to check
+ * @param bool $expected Information if given $subject matches given $patterns
+ *
+ * @dataProvider providePatternsAndSubjectForPregMultiMatch
+ */
+ public function testPregMultiMatch($patterns, $subject, $expected)
{
- self::assertTrue(Regex::isLetterOrDigit('a'));
- self::assertTrue(Regex::isLetterOrDigit(10));
- self::assertFalse(Regex::isLetterOrDigit(';'));
+ self::assertEquals($expected, Regex::pregMultiMatch($patterns, $subject));
+ }
+
+ /**
+ * @param array|string $patterns The patterns to match
+ * @param string $subject The string to check
+ * @param bool $expected Information if given $subject matches given $patterns
+ *
+ * @dataProvider providePatternsAndSubjectForPregMultiMatchWhenMustMatchAllPatterns
+ */
+ public function testPregMultiMatchWhenMustMatchAllPatterns($patterns, $subject, $expected)
+ {
+ self::assertEquals($expected, Regex::pregMultiMatch($patterns, $subject, true));
}
public function testStartsWith()
@@ -171,1834 +2231,27 @@ class RegexTest extends BaseTestCase
public function testStartsWithDirectorySeparator()
{
- /*
- * Not provided, default separator
- */
+ // Not provided, default separator
self::assertTrue(Regex::startsWithDirectorySeparator('/my/extra/directory'));
self::assertFalse(Regex::startsWithDirectorySeparator('my/extra/directory'));
- /*
- * Slash as separator
- */
+ // Slash as separator
$separatorSlash = '/';
self::assertTrue(Regex::startsWithDirectorySeparator('/my/extra/directory', $separatorSlash));
self::assertFalse(Regex::startsWithDirectorySeparator('my/extra/directory', $separatorSlash));
- /*
- * Backslash as separator
- */
+ // Backslash as separator
$separatorBackslash = '\\';
self::assertTrue(Regex::startsWithDirectorySeparator('\my\extra\directory', $separatorBackslash));
self::assertFalse(Regex::startsWithDirectorySeparator('my\extra\directory', $separatorBackslash));
}
- public function testEndsWithDirectorySeparator()
- {
- /*
- * Not provided, default separator
- */
- self::assertTrue(Regex::endsWithDirectorySeparator('my simple text/'));
- self::assertFalse(Regex::endsWithDirectorySeparator('my simple text'));
-
- /*
- * Slash as separator
- */
- $separatorSlash = '/';
-
- self::assertTrue(Regex::endsWithDirectorySeparator('my simple text/', $separatorSlash));
- self::assertFalse(Regex::endsWithDirectorySeparator('my simple text', $separatorSlash));
-
- /*
- * Backslash as separator
- */
- $separatorBackslash = '\\';
-
- self::assertTrue(Regex::endsWithDirectorySeparator('my simple text\\', $separatorBackslash));
- self::assertFalse(Regex::endsWithDirectorySeparator('my simple text', $separatorBackslash));
- }
-
- public function testEndsWith()
- {
- self::assertFalse(Regex::endsWith($this->simpleText, '\.\.\.'));
- self::assertFalse(Regex::endsWith($this->simpleText, '\.'));
- self::assertTrue(Regex::endsWith($this->simpleText, 't'));
- }
-
- public function testIsSetUriParameter()
- {
- $uri = 'www.domain.com/?name=phil&type=4';
-
- $parameterName = 'type';
- self::assertTrue(Regex::isSetUriParameter($uri, $parameterName));
-
- $parameterName = 'color';
- self::assertFalse(Regex::isSetUriParameter($uri, $parameterName));
- }
-
- public function testContainsEntities()
- {
- self::assertFalse(Regex::containsEntities('Lorem ipsum'));
- self::assertTrue(Regex::containsEntities('Lorem ipsum »'));
- }
-
- public function testContains()
- {
- self::assertTrue(Regex::contains($this->simpleText, 'ipsum'));
- self::assertFalse(Regex::contains($this->simpleText, 'neque'));
-
- self::assertFalse(Regex::contains($this->simpleText, '.'));
- self::assertTrue(Regex::contains($this->simpleText, 'l'));
- }
-
- public function testIsFileName()
- {
- $filePath = __FILE__;
- $directoryPath = dirname($filePath);
-
- self::assertTrue(Regex::isFileName($filePath));
- self::assertFalse(Regex::isFileName($directoryPath));
- }
-
- public function testIsQuoted()
- {
- self::assertTrue(Regex::isQuoted('\'lorem ipsum\''));
- self::assertTrue(Regex::isQuoted('"lorem ipsum"'));
-
- self::assertFalse(Regex::isQuoted('lorem ipsum'));
- self::assertFalse(Regex::isQuoted(new \stdClass()));
- }
-
- public function testIsWindowsBasedPath()
- {
- self::assertTrue(Regex::isWindowsBasedPath('C:\path\to\directory'));
- self::assertTrue(Regex::isWindowsBasedPath('C:\path\to\file.jpg'));
-
- self::assertFalse(Regex::isWindowsBasedPath('/path/to/directory'));
- self::assertFalse(Regex::isWindowsBasedPath('/path/to/file.jpg'));
- }
-
- public function testIsValidNip()
- {
- self::assertFalse(Regex::isValidNip(null));
- self::assertFalse(Regex::isValidNip(''));
- self::assertFalse(Regex::isValidNip(1234));
- self::assertFalse(Regex::isValidNip(1234567890));
- self::assertFalse(Regex::isValidNip(0000000000));
- self::assertFalse(Regex::isValidNip('1234567890'));
- self::assertFalse(Regex::isValidNip('0000000000'));
- self::assertFalse(Regex::isValidNip('abc'));
- self::assertFalse(Regex::isValidNip($this->simpleText));
-
- self::assertTrue(Regex::isValidNip('7340009469')); // Onet S.A.
- self::assertTrue(Regex::isValidNip('5252530705')); // Facebook Poland sp. z o.o.
- }
-
- /**
- * @param mixed $emptyValue Empty value, e.g. ""
- * @dataProvider provideEmptyValue
- */
- public function testIsValidBundleNameUsingEmptyValue($emptyValue)
- {
- self::assertFalse(Regex::isValidBundleName($emptyValue));
- }
-
- /**
- * @param string $bundleName Full name of bundle to verify, e.g. "MyExtraBundle"
- * @param bool $expected Information if it's valid name
- *
- * @dataProvider provideBundleName
- */
- public function testIsValidBundleName($bundleName, $expected)
- {
- self::assertEquals($expected, Regex::isValidBundleName($bundleName));
- }
-
- public function testGetBundleNamePattern()
- {
- self::assertEquals('/^(([A-Z]{1}[a-z0-9]+)((?2))*)(Bundle)$/', Regex::getBundleNamePattern());
- }
-
- public function testGetHtmlAttributePattern()
- {
- self::assertEquals('/([\w-]+)="([\w -]+)"/', Regex::getHtmlAttributePattern());
- }
-
- /**
- * @param mixed $emptyValue Empty value, e.g. ""
- * @dataProvider provideEmptyValue
- */
- public function testIsValidHtmlAttributeUsingEmptyValue($emptyValue)
- {
- self::assertFalse(Regex::isValidHtmlAttribute($emptyValue));
- }
-
- /**
- * @param string $htmlAttribute The html attribute to verify
- * @param bool $expected Information if it's valid attribute
- *
- * @dataProvider provideHtmlAttribute
- */
- public function testIsValidHtmlAttribute($htmlAttribute, $expected)
- {
- self::assertEquals($expected, Regex::isValidHtmlAttribute($htmlAttribute));
- }
-
- /**
- * @param mixed $emptyValue Empty value, e.g. ""
- * @dataProvider provideEmptyValue
- */
- public static function testAreValidHtmlAttributesUsingEmptyValue($emptyValue)
- {
- self::assertFalse(Regex::areValidHtmlAttributes($emptyValue));
- }
-
- /**
- * @param string $htmlAttributes The html attributes to verify
- * @param bool $expected Information if attributes are valid
- *
- * @dataProvider provideHtmlAttributes
- */
- public static function testAreValidHtmlAttributes($htmlAttributes, $expected)
- {
- self::assertEquals($expected, Regex::areValidHtmlAttributes($htmlAttributes));
- }
-
- /**
- * @param string $value Value to verify
- * @param bool $expected Information if value is a binary value
- *
- * @dataProvider provideBinaryValue
- */
- public static function testIsBinaryValue($value, $expected)
- {
- self::assertEquals($expected, Regex::isBinaryValue($value));
- }
-
- /**
- * @param mixed $emptyValue Empty value, e.g. ""
- * @dataProvider provideEmptyValue
- */
- public static function testIsValidEmailUsingEmptyValue($emptyValue)
- {
- self::assertFalse(Regex::isValidEmail($emptyValue));
- }
-
- /**
- * @param string $email E-mail address to validate / verify
- * @param bool $expected Information if e-mail is valid
- *
- * @dataProvider provideEmail
- */
- public static function testIsValidEmail($email, $expected)
- {
- self::assertEquals($expected, Regex::isValidEmail($email));
- }
-
- /**
- * @param mixed $emptyValue Empty value, e.g. ""
- * @dataProvider provideEmptyValue
- */
- public static function testIsValidTaxIdUsingEmptyValue($emptyValue)
- {
- self::assertFalse(Regex::isValidTaxId($emptyValue));
- }
-
- /**
- * @param string $taxIdString Tax ID (NIP) string
- * @param bool $expected Information if tax ID is valid
- *
- * @dataProvider provideTaxId
- */
- public static function testIsValidTaxId($taxIdString, $expected)
- {
- self::assertEquals($expected, Regex::isValidTaxId($taxIdString));
- }
-
- /**
- * @param mixed $emptyValue Empty value, e.g. ""
- * @dataProvider provideEmptyValue
- */
- public static function testIsValidPhoneNumberUsingEmptyValue($emptyValue)
- {
- self::assertFalse(Regex::isValidPhoneNumber($emptyValue));
- }
-
- /**
- * @param string $phoneNumber The phone number to validate / verify
- * @param bool $expected Information if phone number is valid
- *
- * @dataProvider providePhoneNumber
- */
- public static function testIsValidPhoneNumber($phoneNumber, $expected)
- {
- self::assertEquals($expected, Regex::isValidPhoneNumber($phoneNumber));
- }
-
- /**
- * @param string $pattern Pattern to match
- * @param array $dataArray The array
- * @param array $expected Expected array
- *
- * @dataProvider providePatternForArrayValues
- */
- public static function testGetArrayValuesByPatternUsingValues($pattern, array $dataArray, $expected)
- {
- self::assertEquals($expected, Regex::getArrayValuesByPattern($pattern, $dataArray));
- }
-
- /**
- * @param string $pattern Pattern to match
- * @param array $dataArray The array
- * @param array $expected Expected array
- *
- * @dataProvider providePatternForArrayKeys
- */
- public static function testGetArrayValuesByPatternUsingKeys($pattern, array $dataArray, $expected)
- {
- self::assertEquals($expected, Regex::getArrayValuesByPattern($pattern, $dataArray, true));
- }
-
- public static function testGetUrlPatternWithProtocolRequired()
- {
- $pattern = '/^([a-z]+:\/\/)([\da-z\.-]+)\.([a-z\.]{2,6})(\/)?([\w\.\-]*)?(\?)?([\w \.\-\/=&]*)\/?$/i';
- self::assertEquals($pattern, Regex::getUrlPattern(true));
- }
-
- public static function testGetUrlPatternWithoutProtocol()
- {
- $pattern = '/^([a-z]+:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})(\/)?([\w\.\-]*)?(\?)?([\w \.\-\/=&]*)\/?$/i';
- self::assertEquals($pattern, Regex::getUrlPattern());
- }
-
- /**
- * @param array $array The array that should be filtered
- * @param string $arrayColumnKey Column name
- * @param string $filterExpression Simple filter expression, e.g. "== 2" or "!= \'home\'"
- * @param array $expected Expected array
- *
- * @dataProvider provideSimpleExpressionForArrayFiltering
- */
- public function testArrayFilterUsingSimpleExpression($array, $arrayColumnKey, $filterExpression, $expected)
- {
- self::assertEquals($expected, Regex::arrayFilter($array, $arrayColumnKey, $filterExpression));
- }
-
- /**
- * @param array $array The array that should be filtered
- * @param string $arrayColumnKey Column name
- * @param string $filterExpression Regular expression, e.g. "/\d+/" or "/[a-z]+[,;]{2,}/"
- * @param array $expected Expected array
- *
- * @dataProvider provideRegularExpressionForArrayFiltering
- */
- public function testArrayFilterUsingRegularExpression($array, $arrayColumnKey, $filterExpression, $expected)
- {
- self::assertEquals($expected, Regex::arrayFilter($array, $arrayColumnKey, $filterExpression, true));
- }
-
- /**
- * @param array|string $patterns The patterns to match
- * @param string $subject The string to check
- * @param bool $expected Information if given $subject matches given $patterns
- *
- * @dataProvider providePatternsAndSubjectForPregMultiMatch
- */
- public function testPregMultiMatch($patterns, $subject, $expected)
- {
- self::assertEquals($expected, Regex::pregMultiMatch($patterns, $subject));
- }
-
- /**
- * @param array|string $patterns The patterns to match
- * @param string $subject The string to check
- * @param bool $expected Information if given $subject matches given $patterns
- *
- * @dataProvider providePatternsAndSubjectForPregMultiMatchWhenMustMatchAllPatterns
- */
- public function testPregMultiMatchWhenMustMatchAllPatterns($patterns, $subject, $expected)
- {
- self::assertEquals($expected, Regex::pregMultiMatch($patterns, $subject, true));
- }
-
- public function testGetMoneyPattern()
- {
- self::assertEquals('/^[-+]?\d+([\.,]{1}\d*)?$/', Regex::getMoneyPattern());
- }
-
- /**
- * @param mixed $emptyValue Empty value, e.g. ""
- * @dataProvider provideEmptyNonMoneyValue
- */
- public function testIsValidMoneyValueUsingEmptyValue($emptyValue)
- {
- self::assertFalse(Regex::isValidMoneyValue($emptyValue));
- }
-
- /**
- * @param mixed $value Value to verify
- * @param bool $expected Information if given value is a money value
- *
- * @dataProvider provideMoneyValue
- */
- public function testIsValidMoneyValue($value, $expected)
- {
- self::assertEquals($expected, Regex::isValidMoneyValue($value));
- }
-
- /**
- * @param mixed $nonScalarValue Non scalar value, e.g. [] or null
- * @dataProvider provideNonScalarValue
- */
- public function testGetValidColorHexValueUsingNonScalarValue($nonScalarValue)
- {
- self::assertFalse(Regex::getValidColorHexValue($nonScalarValue));
- }
-
- /**
- * @param mixed $emptyValue Empty value, e.g. ""
- * @dataProvider provideColorEmptyValue
- */
- public function testGetValidColorHexValueUsingEmptyValueWithoutException($emptyValue)
- {
- self::assertFalse(Regex::getValidColorHexValue($emptyValue, false));
- }
-
- /**
- * @param mixed $emptyValue Empty value, e.g. ""
- * @dataProvider provideColorEmptyValue
- */
- public function testGetValidColorHexValueUsingEmptyValue($emptyValue)
- {
- $this->setExpectedException(IncorrectColorHexLengthException::class);
- Regex::getValidColorHexValue($emptyValue);
- }
-
- /**
- * @param string $incorrectColor Incorrect value of color
- * @dataProvider provideColorIncorrectLength
- */
- public function testGetValidColorHexValueUsingIncorrectValueWithoutException($incorrectColor)
- {
- self::assertFalse(Regex::getValidColorHexValue($incorrectColor, false));
- }
-
- /**
- * @param string $incorrectColor Incorrect value of color
- * @dataProvider provideColorIncorrectLength
- */
- public function testGetValidColorHexValueUsingIncorrectValue($incorrectColor)
- {
- $this->setExpectedException(IncorrectColorHexLengthException::class);
- Regex::getValidColorHexValue($incorrectColor);
- }
-
- /**
- * @param string $invalidColor Invalid value of color
- * @dataProvider provideColorInvalidValue
- */
- public function testGetValidColorHexValueUsingInvalidValueWithoutException($invalidColor)
- {
- self::assertFalse(Regex::getValidColorHexValue($invalidColor, false));
- }
-
- /**
- * @param string $invalidColor Invalid value of color
- * @dataProvider provideColorInvalidValue
- */
- public function testGetValidColorHexValueUsingInvalidValue($invalidColor)
- {
- $this->setExpectedException(InvalidColorHexValueException::class);
- Regex::getValidColorHexValue($invalidColor);
- }
-
- /**
- * @param string $color Color to verify
- * @param string $expected Expected value of color
- *
- * @dataProvider provideColor
- */
- public function testGetValidColorHexValue($color, $expected)
- {
- self::assertEquals($expected, Regex::getValidColorHexValue($color));
- }
-
- /**
- * @param mixed $emptyValue Empty value, e.g. ""
- * @dataProvider provideEmptyValue
- */
- public static function testIsSizeValueUsingEmptyValue($emptyValue)
- {
- self::assertFalse(Regex::isSizeValue($emptyValue));
- }
-
- /**
- * @param string $description Description of test
- * @param string $value Value to verify
- * @param string $separator Separator used to split width and height
- * @param bool $expected Expected result of verification
- *
- * @dataProvider provideSizeToVerify
- */
- public function testIsSizeValue($description, $value, $separator, $expected)
- {
- self::assertEquals($expected, Regex::isSizeValue($value, $separator), $description);
- }
-
- /**
- * @param string $value Value that should be transformed to slug
- * @param string $expected Expected slug
- *
- * @dataProvider provideValueSlug
- */
- public function testCreateSlug($value, $expected)
- {
- self::assertSame($expected, Regex::createSlug($value));
- }
-
- /**
- * Provides name of bundle and information if it's valid name
- *
- * @return Generator
- */
- public function provideBundleName()
- {
- yield[
- 'something',
- false,
- ];
-
- yield[
- 'something_different',
- false,
- ];
-
- yield[
- 'something-else',
- false,
- ];
-
- yield[
- 'myExtraBundle',
- false,
- ];
-
- yield[
- 'MyExtra',
- false,
- ];
-
- yield[
- 'MyExtraBundle',
- true,
- ];
-
- yield[
- 'MySuperExtraGorgeousBundle',
- true,
- ];
- }
-
- /**
- * Provides html attribute and information if it's valid
- *
- * @return Generator
- */
- public function provideHtmlAttribute()
- {
- yield[
- 'abc = def',
- false,
- ];
-
- yield[
- 'a b c=def',
- false,
- ];
-
- yield[
- 'abc=def',
- false,
- ];
-
- yield[
- 'a1b2c=d3e4f',
- false,
- ];
-
- yield[
- 'abc="def"',
- true,
- ];
-
- yield[
- 'a1b2c="d3e4f"',
- true,
- ];
- }
-
- /**
- * Provides html attribute and information if attributes are valid
- *
- * @return Generator
- */
- public function provideHtmlAttributes()
- {
- yield[
- 'abc = def',
- false,
- ];
-
- yield[
- 'abc = def ghi = jkl',
- false,
- ];
-
- yield[
- 'abc=def ghi=jkl',
- false,
- ];
-
- yield[
- 'abc=def ghi=jkl mno=pqr',
- false,
- ];
-
- yield[
- 'abc="def"',
- true,
- ];
-
- yield[
- 'abc="def" ghi="jkl"',
- true,
- ];
-
- yield[
- 'abc="def" ghi="jkl" mno="pqr"',
- true,
- ];
-
- yield[
- 'a2bc="d4ef" ghi="j k l" mno="pq9r"',
- true,
- ];
- }
-
- /**
- * Provides value to verify if it is a binary value
- *
- * @return Generator
- */
- public function provideBinaryValue()
- {
- $file1Path = $this->getFilePathForTesting('lorem-ipsum.txt');
- $file2Path = $this->getFilePathForTesting('minion.jpg');
-
- yield[
- null,
- false,
- ];
-
- yield[
- [],
- false,
- ];
-
- yield[
- '',
- false,
- ];
-
- yield[
- 'abc',
- false,
- ];
-
- yield[
- '1234',
- false,
- ];
-
- yield[
- 1234,
- false,
- ];
-
- yield[
- 12.34,
- false,
- ];
-
- yield[
- fread(fopen($file1Path, 'rb'), 1),
- false,
- ];
-
- yield[
- fread(fopen($file2Path, 'rb'), 1),
- true,
- ];
- }
-
- /**
- * Provides e-mail and information if it's valid
- *
- * @return Generator
- */
- public function provideEmail()
- {
- yield[
- '1',
- false,
- ];
-
- yield[
- 1,
- false,
- ];
-
- yield[
- 'a@a',
- false,
- ];
-
- yield[
- 'a@a.com',
- false,
- ];
-
- yield[
- 'aa@a.com',
- true,
- ];
-
- yield[
- 'a.b@d.com',
- true,
- ];
- }
-
- /**
- * Provides tax ID and information if it's valid
- *
- * @return Generator
- */
- public function provideTaxId()
- {
- yield[
- '123',
- false,
- ];
-
- yield[
- '12345',
- false,
- ];
-
- yield[
- '1122334455',
- false,
- ];
-
- yield[
- '1234567890',
- false,
- ];
-
- yield[
- '0987654321',
- false,
- ];
-
- /*
- * Microsoft sp. z o.o.
- */
- yield[
- '5270103391',
- true,
- ];
-
- /*
- * Onet S.A.
- */
- yield[
- '7340009469',
- true,
- ];
- }
-
- /**
- * Provides phone number and information if it's valid
- *
- * @return Generator
- */
- public function providePhoneNumber()
- {
- yield[
- 'abc',
- false,
- ];
-
- yield[
- '1-2-3',
- false,
- ];
-
- yield[
- '123',
- true,
- ];
-
- yield[
- '123 456 789',
- true,
- ];
-
- yield[
- '123456789',
- true,
- ];
- }
-
- /**
- * Provides pattern and array with values that should match that pattern
- *
- * @return Generator
- */
- public function providePatternForArrayValues()
- {
- yield[
- '/\d/',
- [],
- [],
- ];
-
- yield[
- '/\d+/',
- [
- 'lorem',
- 'ipsum',
- 123,
- 'dolor',
- '456',
- ],
- [
- 2 => 123,
- 4 => '456',
- ],
- ];
-
- yield[
- '/\d+-[a-z]+/',
- [
- 'lorem',
- 123,
- false,
- 'dolor',
- '456-ipsum',
- ],
- [
- 4 => '456-ipsum',
- ],
- ];
- }
-
- /**
- * Provides pattern and array with keys that should match that pattern
- *
- * @return Generator
- */
- public function providePatternForArrayKeys()
- {
- yield[
- '/\d/',
- [],
- [],
- ];
-
- yield[
- '/\d+/',
- [
- 'lorem' => 'ipsum',
- 'dolor' => 123,
- 'sit',
- 4 => '456',
- ],
- [
- 0 => 'sit',
- 4 => '456',
- ],
- ];
-
- yield[
- '/\d+-[a-z]+/',
- [
- 'lorem',
- '456-ipsum' => 123,
- '001-sit' => false,
- 'dolor',
- ],
- [
- '456-ipsum' => 123,
- '001-sit' => false,
- ],
- ];
- }
-
- /**
- * Provides simple compare expression for array filtering and the array
- *
- * @return Generator
- */
- public function provideSimpleExpressionForArrayFiltering()
- {
- yield[
- [],
- 'id',
- ' == 2',
- [],
- ];
-
- yield[
- [
- [
- 'id' => 1,
- 'first_name' => 'Jane',
- 'last_name' => 'Scott',
- 'is_active' => true,
- ],
- [
- 'id' => 2,
- 'first_name' => 'George',
- 'last_name' => 'Brown',
- 'is_active' => true,
- ],
- [
- 'id' => 3,
- 'first_name' => 'Mike',
- 'last_name' => 'Green',
- 'is_active' => false,
- ],
- ],
- 'birth_date',
- ' == 2',
- [
- [
- 'id' => 1,
- 'first_name' => 'Jane',
- 'last_name' => 'Scott',
- 'is_active' => true,
- ],
- [
- 'id' => 2,
- 'first_name' => 'George',
- 'last_name' => 'Brown',
- 'is_active' => true,
- ],
- [
- 'id' => 3,
- 'first_name' => 'Mike',
- 'last_name' => 'Green',
- 'is_active' => false,
- ],
- ],
- ];
-
- yield[
- [
- [
- 'id' => 1,
- 'first_name' => 'Jane',
- 'last_name' => 'Scott',
- 'is_active' => true,
- ],
- [
- 'id' => 2,
- 'first_name' => 'George',
- 'last_name' => 'Brown',
- 'is_active' => true,
- ],
- [
- 'id' => 3,
- 'first_name' => 'Mike',
- 'last_name' => 'Green',
- 'is_active' => false,
- ],
- ],
- 'id',
- ' == 2',
- [
- 1 => [
- 'id' => 2,
- 'first_name' => 'George',
- 'last_name' => 'Brown',
- 'is_active' => true,
- ],
- ],
- ];
-
- yield[
- [
- [
- 'id' => 1,
- 'first_name' => 'Jane',
- 'last_name' => 'Scott',
- 'is_active' => true,
- ],
- [
- 'id' => 2,
- 'first_name' => 'George',
- 'last_name' => 'Brown',
- 'is_active' => true,
- ],
- [
- 'id' => 3,
- 'first_name' => 'Mike',
- 'last_name' => 'Green',
- 'is_active' => false,
- ],
- ],
- 'id',
- ' >= 2',
- [
- 1 => [
- 'id' => 2,
- 'first_name' => 'George',
- 'last_name' => 'Brown',
- 'is_active' => true,
- ],
- 2 => [
- 'id' => 3,
- 'first_name' => 'Mike',
- 'last_name' => 'Green',
- 'is_active' => false,
- ],
- ],
- ];
-
- yield[
- [
- [
- 'id' => 1,
- 'first_name' => 'Jane',
- 'last_name' => 'Scott',
- 'is_active' => true,
- ],
- [
- 'id' => 2,
- 'first_name' => 'George',
- 'last_name' => 'Brown',
- 'is_active' => true,
- ],
- [
- 'id' => 3,
- 'first_name' => 'Mike',
- 'last_name' => 'Green',
- 'is_active' => false,
- ],
- ],
- 'is_active',
- ' !== true',
- [
- 2 => [
- 'id' => 3,
- 'first_name' => 'Mike',
- 'last_name' => 'Green',
- 'is_active' => false,
- ],
- ],
- ];
-
- yield[
- [
- [
- 'id' => 1,
- 'first_name' => 'Jane',
- 'last_name' => 'Scott',
- 'is_active' => true,
- ],
- [
- 'id' => 2,
- 'first_name' => 'George',
- 'last_name' => 'Brown',
- 'is_active' => true,
- ],
- [
- 'id' => 3,
- 'first_name' => 'Mike',
- 'last_name' => 'Green',
- 'is_active' => false,
- ],
- ],
- 'first_name',
- ' == \'Mike\'',
- [
- 2 => [
- 'id' => 3,
- 'first_name' => 'Mike',
- 'last_name' => 'Green',
- 'is_active' => false,
- ],
- ],
- ];
- }
-
- /**
- * Provides regular expression for array filtering and the array
- *
- * @return Generator
- */
- public function provideRegularExpressionForArrayFiltering()
- {
- yield[
- [],
- 'id',
- '/\d+/',
- [],
- ];
-
- yield[
- [
- [
- 'id' => 1,
- 'first_name' => 'Jane',
- 'last_name' => 'Scott',
- 'is_active' => true,
- ],
- [
- 'id' => 2,
- 'first_name' => 'George',
- 'last_name' => 'Brown',
- 'is_active' => true,
- ],
- [
- 'id' => 3,
- 'first_name' => 'Mike',
- 'last_name' => 'Green',
- 'is_active' => false,
- ],
- ],
- 'birth_date',
- '/\d+/',
- [
- [
- 'id' => 1,
- 'first_name' => 'Jane',
- 'last_name' => 'Scott',
- 'is_active' => true,
- ],
- [
- 'id' => 2,
- 'first_name' => 'George',
- 'last_name' => 'Brown',
- 'is_active' => true,
- ],
- [
- 'id' => 3,
- 'first_name' => 'Mike',
- 'last_name' => 'Green',
- 'is_active' => false,
- ],
- ],
- ];
-
- yield[
- [
- [
- 'id' => 1,
- 'first_name' => 'Jane',
- 'last_name' => 'Scott',
- 'is_active' => true,
- ],
- [
- 'id' => 123,
- 'first_name' => 'George',
- 'last_name' => 'Brown',
- 'is_active' => true,
- ],
- [
- 'id' => 3,
- 'first_name' => 'Mike',
- 'last_name' => 'Green',
- 'is_active' => false,
- ],
- ],
- 'id',
- '/\d{3}/',
- [
- 1 => [
- 'id' => 123,
- 'first_name' => 'George',
- 'last_name' => 'Brown',
- 'is_active' => true,
- ],
- ],
- ];
-
- yield[
- [
- [
- 'id' => 1,
- 'first_name' => 'Jane',
- 'last_name' => 'Scott',
- 'is_active' => true,
- ],
- [
- 'id' => 123,
- 'first_name' => 'George',
- 'last_name' => 'Brown',
- 'is_active' => true,
- ],
- [
- 'id' => 456,
- 'first_name' => 'Mike',
- 'last_name' => 'Green',
- 'is_active' => false,
- ],
- ],
- 'first_name',
- '/George|Mike/',
- [
- 1 => [
- 'id' => 123,
- 'first_name' => 'George',
- 'last_name' => 'Brown',
- 'is_active' => true,
- ],
- 2 => [
- 'id' => 456,
- 'first_name' => 'Mike',
- 'last_name' => 'Green',
- 'is_active' => false,
- ],
- ],
- ];
-
- yield[
- [
- [
- 'id' => 1,
- 'first_name' => 'Jane',
- 'last_name' => 'Scott',
- 'is_active' => true,
- ],
- [
- 'id' => 2,
- 'first_name' => 'George',
- 'last_name' => 'Brown',
- 'is_active' => true,
- ],
- [
- 'id' => 3,
- 'first_name' => 'Mike',
- 'last_name' => 'Green-Blue',
- 'is_active' => false,
- ],
- ],
- 'last_name',
- '/\w+-\w+/',
- [
- 2 => [
- 'id' => 3,
- 'first_name' => 'Mike',
- 'last_name' => 'Green-Blue',
- 'is_active' => false,
- ],
- ],
- ];
- }
-
- /**
- * Provides patterns and subject for the pregMultiMatch() method
- *
- * @return Generator
- */
- public function providePatternsAndSubjectForPregMultiMatch()
- {
- yield[
- '',
- '',
- false,
- ];
-
- yield[
- [],
- '',
- false,
- ];
-
- yield[
- '/\d+/',
- 'Lorem ipsum dolor sit',
- false,
- ];
-
- yield[
- [
- '/\d+/',
- '/^[a-z]{4}$/',
- ],
- 'Lorem ipsum dolor sit',
- false,
- ];
-
- yield[
- '/\w+/',
- 'Lorem ipsum dolor sit',
- true,
- ];
-
- yield[
- [
- '/\d+/',
- '/\w+/',
- ],
- 'Lorem ipsum dolor sit',
- true,
- ];
- }
-
- /**
- * Provides patterns and subject for the pregMultiMatch() method when must match all patterns
- *
- * @return Generator
- */
- public function providePatternsAndSubjectForPregMultiMatchWhenMustMatchAllPatterns()
- {
- yield[
- '',
- '',
- false,
- ];
-
- yield[
- [],
- '',
- false,
- ];
-
- yield[
- '/\d+/',
- 'Lorem ipsum dolor sit',
- false,
- ];
-
- yield[
- [
- '/\d+/',
- '/^[a-z]{4}$/',
- ],
- 'Lorem ipsum dolor sit',
- false,
- ];
-
- yield[
- '/\w+/',
- 'Lorem ipsum dolor sit',
- true,
- ];
-
- yield[
- [
- '/[a-zA-Z ]+/',
- '/\w+/',
- ],
- 'Lorem ipsum dolor sit',
- true,
- ];
- }
-
- /**
- * Provides empty non money-related value
- *
- * @return Generator
- */
- public function provideEmptyNonMoneyValue()
- {
- yield[''];
- yield[' '];
- yield[null];
- yield[false];
- yield[[]];
- }
-
- /**
- * Provides money-related value and information if the value is valid
- *
- * @return Generator
- */
- public function provideMoneyValue()
- {
- yield[
- 'abc',
- false,
- ];
-
- yield[
- '-a.b',
- false,
- ];
-
- yield[
- 'a,b',
- false,
- ];
-
- yield[
- 0,
- true,
- ];
-
- yield[
- 1,
- true,
- ];
-
- yield[
- -1,
- true,
- ];
-
- yield[
- 1.2,
- true,
- ];
-
- yield[
- 1.202,
- true,
- ];
-
- yield[
- -1.202,
- true,
- ];
-
- yield[
- '0',
- true,
- ];
-
- yield[
- '1',
- true,
- ];
-
- yield[
- '-1',
- true,
- ];
-
- yield[
- '1.2',
- true,
- ];
-
- yield[
- '1.202',
- true,
- ];
-
- yield[
- '-1.202',
- true,
- ];
-
- yield[
- '1,202',
- true,
- ];
-
- yield[
- '-1,2',
- true,
- ];
-
- yield[
- '-1,202',
- true,
- ];
- }
-
- /**
- * Provides value of color with incorrect length
- *
- * @return Generator
- */
- public function provideColorIncorrectLength()
- {
- yield[
- '12',
- ];
-
- yield[
- '1234',
- ];
-
- yield[
- '12345678',
- ];
-
- yield[
- '#12',
- ];
-
- yield[
- '#1234',
- ];
-
- yield[
- '#12345678',
- ];
- }
-
- /**
- * Provides invalid value of color
- *
- * @return Generator
- */
- public function provideColorInvalidValue()
- {
- yield[
- '#qwerty',
- ];
-
- yield[
- 'qwerty',
- ];
- }
-
- /**
- * Provides empty non color-related value
- *
- * @return Generator
- */
- public function provideColorEmptyValue()
- {
- yield[
- '',
- ];
-
- yield[
- 0,
- ];
-
- yield[
- '0',
- ];
-
- yield[
- false,
- ];
- }
-
- /**
- * Provides value of color
- *
- * @return Generator
- */
- public function provideColor()
- {
- yield[
- '#1b0',
- '11bb00',
- ];
-
- yield[
- '#1B0',
- '11bb00',
- ];
-
- yield[
- '#1ab1ab',
- '1ab1ab',
- ];
-
- yield[
- '#1AB1AB',
- '1ab1ab',
- ];
-
- yield[
- '#000',
- '000000',
- ];
- }
-
- /**
- * Provide value to create slug
- *
- * @return Generator
- */
- public function provideValueSlug()
- {
- yield[
- [],
- false,
- ];
-
- yield[
- null,
- false,
- ];
-
- yield[
- '',
- '',
- ];
-
- yield[
- 1234,
- '1234',
- ];
-
- yield[
- '1234',
- '1234',
- ];
-
- yield[
- '1/2/3/4',
- '1234',
- ];
-
- yield[
- '1 / 2 / 3 / 4',
- '1-2-3-4',
- ];
-
- yield[
- 'test',
- 'test',
- ];
-
- yield[
- 'test test',
- 'test-test',
- ];
-
- yield[
- 'lorem ipsum dolor sit',
- 'lorem-ipsum-dolor-sit',
- ];
-
- yield[
- 'Lorem ipsum. Dolor sit 12.34 amet.',
- 'lorem-ipsum-dolor-sit-1234-amet',
- ];
-
- yield[
- 'Was sind Löwen, Bären, Vögel und Käfer (für die Prüfung)?',
- 'was-sind-lowen-baren-vogel-und-kafer-fur-die-prufung',
- ];
-
- yield[
- 'äöü (ÄÖÜ)',
- 'aou-aou',
- ];
-
- yield[
- 'Półka dębowa. Kolor: żółędziowy. Wymiary: 80 x 30 cm.',
- 'polka-debowa-kolor-zoledziowy-wymiary-80-x-30-cm',
- ];
-
- yield[
- 'ąęółńśżźć (ĄĘÓŁŃŚŻŹĆ)',
- 'aeolnszzc-aeolnszzc',
- ];
- }
-
- public function provideSizeToVerify()
- {
- yield[
- 'One number only',
- 200,
- ' x ',
- false,
- ];
-
- yield[
- 'One number only as string',
- '200',
- ' x ',
- false,
- ];
-
- yield[
- 'The " " as invalid separator',
- '200 100',
- ' x ',
- false,
- ];
-
- yield[
- 'The "|" as separator (invalid separator)',
- '200 | 100',
- ' x ',
- false,
- ];
-
- yield[
- 'The "|" as invalid separator and no spaces around separator',
- '200|100',
- ' x ',
- false,
- ];
-
- yield[
- 'The "X" as invalid separator',
- '200 X 100',
- ' x ',
- false,
- ];
-
- yield[
- 'Simple, valid size',
- '200 x 100',
- ' x ',
- true,
- ];
-
- yield[
- 'Too much spaces at the right of separator',
- '200 x 100',
- ' x ',
- true,
- ];
-
- yield[
- 'Too much spaces at the left of separator',
- '200 x 100',
- ' x ',
- true,
- ];
-
- yield[
- 'Too much spaces around separator',
- '200 x 100',
- ' x ',
- true,
- ];
-
- yield[
- 'Too much spaces before width',
- ' 200 x 100',
- ' x ',
- true,
- ];
-
- yield[
- 'Too much spaces after height',
- '200 x 100 ',
- ' x ',
- true,
- ];
-
- yield[
- 'Too much spaces before width and after height',
- ' 200 x 100 ',
- ' x ',
- true,
- ];
-
- yield[
- 'Too much spaces everywhere (1st)',
- ' 200 x 100 ',
- ' x ',
- true,
- ];
-
- yield[
- 'Too much spaces everywhere (2nd)',
- ' 200 x 100 ',
- ' x ',
- true,
- ];
-
- yield[
- 'Too much spaces everywhere (3rd)',
- ' 200 x 100 ',
- ' x ',
- true,
- ];
-
- yield[
- 'The " X " as custom separator',
- '200 X 100',
- ' X ',
- true,
- ];
-
- yield[
- 'The "|" as custom separator',
- '200|100',
- '|',
- true,
- ];
-
- yield[
- 'The " | " as custom separator',
- '200 | 100',
- ' | ',
- true,
- ];
-
- yield[
- 'The "::" as custom separator',
- '200::100',
- '::',
- true,
- ];
-
- yield[
- 'The " :: " as custom separator',
- '200 :: 100',
- ' :: ',
- true,
- ];
-
- yield[
- 'The "." as custom separator',
- '200.100',
- '.',
- true,
- ];
-
- yield[
- 'The " . " as custom separator',
- '200 . 100',
- ' . ',
- true,
- ];
-
- yield[
- 'The "/" as custom separator',
- '200/100',
- '/',
- true,
- ];
-
- yield[
- 'The " / " as custom separator',
- '200 / 100',
- ' / ',
- true,
- ];
-
- yield[
- 'The " : " as custom separator and too much spaces everywhere',
- ' 200 : 100 ',
- ' : ',
- true,
- ];
- }
-
/**
* {@inheritdoc}
*/
- protected function setUp()
+ protected function setUp(): void
{
parent::setUp();
@@ -2010,7 +2263,7 @@ class RegexTest extends BaseTestCase
/**
* {@inheritdoc}
*/
- protected function tearDown()
+ protected function tearDown(): void
{
parent::tearDown();
unset($this->simpleText, $this->camelCaseText);
diff --git a/tests/Utilities/Repository/Sortable.php b/tests/Utilities/Repository/Sortable.php
index fc877b6..728438f 100644
--- a/tests/Utilities/Repository/Sortable.php
+++ b/tests/Utilities/Repository/Sortable.php
@@ -14,6 +14,9 @@ namespace Meritoo\Test\Common\Utilities\Repository;
*
* @author Meritoo
* @copyright Meritoo
+ *
+ * @internal
+ * @coversNothing
*/
class Sortable
{
@@ -34,6 +37,16 @@ class Sortable
$this->position = $position;
}
+ /**
+ * Returns representation of object as string
+ *
+ * @return string
+ */
+ public function __toString()
+ {
+ return sprintf('%s (position: %d)', self::class, $this->getPosition());
+ }
+
/**
* Returns position used while sorting
*
@@ -53,14 +66,4 @@ class Sortable
{
$this->position = $position;
}
-
- /**
- * Returns representation of object as string
- *
- * @return string
- */
- public function __toString()
- {
- return sprintf('%s (position: %d)', self::class, $this->getPosition());
- }
}
diff --git a/tests/Utilities/RepositoryTest.php b/tests/Utilities/RepositoryTest.php
index 72d58a7..572b9ef 100644
--- a/tests/Utilities/RepositoryTest.php
+++ b/tests/Utilities/RepositoryTest.php
@@ -10,7 +10,6 @@ namespace Meritoo\Test\Common\Utilities;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\EntityRepository;
-use Doctrine\ORM\Query\Expr\OrderBy;
use Doctrine\ORM\QueryBuilder;
use Generator;
use Meritoo\Common\Test\Base\BaseTestCase;
@@ -23,59 +22,794 @@ use stdClass;
*
* @author Meritoo
* @copyright Meritoo
+ *
+ * @internal
+ * @covers \Meritoo\Common\Utilities\Repository
*/
class RepositoryTest extends BaseTestCase
{
+ /**
+ * Provides arrays with extreme position used to replenish positions of them
+ *
+ * @return Generator
+ */
+ public function provideArraysWithExtremePosition()
+ {
+ yield [
+ [
+ [
+ Repository::POSITION_KEY => 1,
+ ],
+ [],
+ [],
+ ],
+ true,
+ [
+ [
+ Repository::POSITION_KEY => 1,
+ ],
+ [
+ Repository::POSITION_KEY => 2,
+ ],
+ [
+ Repository::POSITION_KEY => 3,
+ ],
+ ],
+ ];
+
+ yield [
+ [
+ [],
+ [],
+ [
+ Repository::POSITION_KEY => 1,
+ ],
+ ],
+ true,
+ [
+ [
+ Repository::POSITION_KEY => 2,
+ ],
+ [
+ Repository::POSITION_KEY => 3,
+ ],
+ [
+ Repository::POSITION_KEY => 1,
+ ],
+ ],
+ ];
+
+ yield [
+ [
+ [
+ Repository::POSITION_KEY => 1,
+ ],
+ [],
+ [],
+ ],
+ false,
+ [
+ [
+ Repository::POSITION_KEY => 1,
+ ],
+ [
+ Repository::POSITION_KEY => 0,
+ ],
+ [
+ Repository::POSITION_KEY => -1,
+ ],
+ ],
+ ];
+
+ yield [
+ [
+ [],
+ [],
+ [
+ Repository::POSITION_KEY => 1,
+ ],
+ ],
+ false,
+ [
+ [
+ Repository::POSITION_KEY => 0,
+ ],
+ [
+ Repository::POSITION_KEY => -1,
+ ],
+ [
+ Repository::POSITION_KEY => 1,
+ ],
+ ],
+ ];
+ }
+
+ /**
+ * Provides arrays with extreme position used to get extreme position
+ *
+ * @return Generator
+ */
+ public function provideArraysWithExtremePositionToGetExtremePosition()
+ {
+ yield [
+ [
+ [
+ Repository::POSITION_KEY => 1,
+ ],
+ [],
+ [],
+ ],
+ true,
+ 1,
+ ];
+
+ yield [
+ [
+ [
+ Repository::POSITION_KEY => 1,
+ ],
+ [],
+ [],
+ ],
+ false,
+ 1,
+ ];
+
+ yield [
+ [
+ [],
+ [],
+ [
+ Repository::POSITION_KEY => 1,
+ ],
+ ],
+ true,
+ 1,
+ ];
+
+ yield [
+ [
+ [],
+ [],
+ [
+ Repository::POSITION_KEY => 1,
+ ],
+ ],
+ false,
+ 1,
+ ];
+
+ yield [
+ [
+ [
+ Repository::POSITION_KEY => 1,
+ ],
+ [],
+ [
+ Repository::POSITION_KEY => 2,
+ ],
+ [],
+ ],
+ true,
+ 2,
+ ];
+
+ yield [
+ [
+ [
+ Repository::POSITION_KEY => 1,
+ ],
+ [],
+ [
+ Repository::POSITION_KEY => 2,
+ ],
+ [],
+ ],
+ false,
+ 1,
+ ];
+ }
+
+ /**
+ * Provides arrays without extreme position used to replenish positions of them
+ *
+ * @return Generator
+ */
+ public function provideArraysWithoutExtremePosition()
+ {
+ yield [
+ [
+ [],
+ [],
+ ],
+ true,
+ [
+ [
+ Repository::POSITION_KEY => 1,
+ ],
+ [
+ Repository::POSITION_KEY => 2,
+ ],
+ ],
+ ];
+
+ yield [
+ [
+ [],
+ [],
+ ],
+ false,
+ [
+ [
+ Repository::POSITION_KEY => -1,
+ ],
+ [
+ Repository::POSITION_KEY => -2,
+ ],
+ ],
+ ];
+
+ yield [
+ [
+ [
+ 'lorem' => 'ipsum',
+ 'dolor',
+ 'sit' => 1,
+ ],
+ [
+ 'abc' => 'def',
+ 'ghi' => null,
+ 'jkl' => 10,
+ ],
+ ],
+ true,
+ [
+ [
+ 'lorem' => 'ipsum',
+ 'dolor',
+ 'sit' => 1,
+ Repository::POSITION_KEY => 1,
+ ],
+ [
+ 'abc' => 'def',
+ 'ghi' => null,
+ 'jkl' => 10,
+ Repository::POSITION_KEY => 2,
+ ],
+ ],
+ ];
+
+ yield [
+ [
+ [
+ 'lorem' => 'ipsum',
+ 'dolor',
+ 'sit' => 1,
+ ],
+ [
+ 'abc' => 'def',
+ 'ghi' => null,
+ 'jkl' => 10,
+ ],
+ ],
+ false,
+ [
+ [
+ 'lorem' => 'ipsum',
+ 'dolor',
+ 'sit' => 1,
+ Repository::POSITION_KEY => -1,
+ ],
+ [
+ 'abc' => 'def',
+ 'ghi' => null,
+ 'jkl' => 10,
+ Repository::POSITION_KEY => -2,
+ ],
+ ],
+ ];
+ }
+
+ /**
+ * Provides arrays without extreme position used to get extreme position
+ *
+ * @return Generator
+ */
+ public function provideArraysWithoutExtremePositionToGetExtremePosition()
+ {
+ yield [
+ [],
+ false,
+ null,
+ ];
+
+ yield [
+ [],
+ true,
+ null,
+ ];
+
+ yield [
+ [
+ [
+ 'lorem' => 'ipsum',
+ 'dolor',
+ 'sit' => 1,
+ ],
+ [
+ 'abc' => 'def',
+ 'ghi' => null,
+ 'jkl' => 10,
+ ],
+ ],
+ true,
+ null,
+ ];
+
+ yield [
+ [
+ [
+ 'lorem' => 'ipsum',
+ 'dolor',
+ 'sit' => 1,
+ ],
+ [
+ 'abc' => 'def',
+ 'ghi' => null,
+ 'jkl' => 10,
+ ],
+ ],
+ false,
+ null,
+ ];
+ }
+
+ /**
+ * Provides objects with extreme position used to replenish positions of them
+ *
+ * @return Generator
+ */
+ public function provideObjectsWithExtremePosition()
+ {
+ yield [
+ [
+ new Sortable(1),
+ new Sortable(),
+ new Sortable(),
+ ],
+ true,
+ [
+ new Sortable(1),
+ new Sortable(2),
+ new Sortable(3),
+ ],
+ ];
+
+ yield [
+ [
+ new Sortable(),
+ new Sortable(1),
+ new Sortable(),
+ ],
+ true,
+ [
+ new Sortable(2),
+ new Sortable(1),
+ new Sortable(3),
+ ],
+ ];
+
+ yield [
+ [
+ new Sortable(1),
+ new Sortable(),
+ new Sortable(),
+ ],
+ false,
+ [
+ new Sortable(1),
+ new Sortable(0),
+ new Sortable(-1),
+ ],
+ ];
+ }
+
+ /**
+ * Provides objects with extreme position used to get extreme position
+ *
+ * @return Generator
+ */
+ public function provideObjectsWithExtremePositionToGetExtremePosition()
+ {
+ yield [
+ [
+ new Sortable(1),
+ new Sortable(2),
+ new Sortable(3),
+ ],
+ true,
+ 3,
+ ];
+
+ yield [
+ [
+ new Sortable(1),
+ new Sortable(2),
+ new Sortable(3),
+ ],
+ false,
+ 1,
+ ];
+ }
+
+ /**
+ * Provides objects without extreme position used to replenish positions of them
+ *
+ * @return Generator
+ */
+ public function provideObjectsWithoutExtremePosition()
+ {
+ yield [
+ [
+ new Sortable(),
+ new Sortable(),
+ new Sortable(),
+ ],
+ true,
+ [
+ new Sortable(1),
+ new Sortable(2),
+ new Sortable(3),
+ ],
+ ];
+
+ yield [
+ [
+ new Sortable(),
+ new Sortable(),
+ new Sortable(),
+ ],
+ false,
+ [
+ new Sortable(-1),
+ new Sortable(-2),
+ new Sortable(-3),
+ ],
+ ];
+ }
+
+ /**
+ * Provides objects without extreme position used to get extreme position
+ *
+ * @return Generator
+ */
+ public function provideObjectsWithoutExtremePositionToGetExtremePosition()
+ {
+ yield [
+ [],
+ false,
+ null,
+ ];
+
+ yield [
+ [],
+ true,
+ null,
+ ];
+
+ yield [
+ [
+ new Sortable(),
+ new Sortable(),
+ new Sortable(),
+ ],
+ true,
+ null,
+ ];
+
+ yield [
+ [
+ new Sortable(),
+ new Sortable(),
+ new Sortable(),
+ ],
+ false,
+ null,
+ ];
+ }
+
+ /**
+ * Provide name of property, direction and expected ORDER BY clause used to get query builder
+ *
+ * @return Generator
+ */
+ public function providePropertyAndDirectionToGetEntityOrderedQueryBuilder()
+ {
+ yield [
+ null,
+ null,
+ '',
+ ];
+
+ yield [
+ '',
+ '',
+ '',
+ ];
+
+ yield [
+ 'first_name',
+ '',
+ 'qb.first_name ASC',
+ ];
+
+ yield [
+ 'first_name',
+ 'asc',
+ 'qb.first_name asc',
+ ];
+
+ yield [
+ 'first_name',
+ 'ASC',
+ 'qb.first_name ASC',
+ ];
+
+ yield [
+ 'first_name',
+ 'desc',
+ 'qb.first_name desc',
+ ];
+
+ yield [
+ 'first_name',
+ 'DESC',
+ 'qb.first_name DESC',
+ ];
+ }
+
+ public function provideSortedItems()
+ {
+ $sortable1 = new Sortable();
+ $sortable1->setPosition(1);
+
+ $sortable2 = new Sortable();
+ $sortable2->setPosition(2);
+
+ $sortable3 = new Sortable();
+ $sortable3->setPosition(309);
+
+ yield [
+ 'An array with 1 item only',
+ [
+ [
+ 'test 1',
+ 'position' => 1,
+ ],
+ ],
+ [
+ [
+ 'test 1',
+ 'position' => 1,
+ ],
+ ],
+ ];
+
+ yield [
+ 'An array with more than 1 item',
+ [
+ [
+ 'test 1',
+ 'position' => 1,
+ ],
+ [
+ 'test 2',
+ 'position' => 2,
+ ],
+ [
+ 'test 3',
+ 'position' => 309,
+ ],
+ ],
+ [
+ [
+ 'test 1',
+ 'position' => 1,
+ ],
+ [
+ 'test 2',
+ 'position' => 2,
+ ],
+ [
+ 'test 3',
+ 'position' => 309,
+ ],
+ ],
+ ];
+
+ yield [
+ '1 object only',
+ [
+ $sortable1,
+ ],
+ [
+ $sortable1,
+ ],
+ ];
+
+ yield [
+ 'More than 1 object',
+ [
+ $sortable1,
+ $sortable2,
+ $sortable3,
+ ],
+ [
+ $sortable1,
+ $sortable2,
+ $sortable3,
+ ],
+ ];
+ }
+
public function testConstructor()
{
static::assertHasNoConstructor(Repository::class);
}
- public function testReplenishPositionsWithoutItems()
+ /**
+ * @param string $property Name of property used by the ORDER BY clause
+ * @param string $direction Direction used by the ORDER BY clause ("ASC" or "DESC")
+ * @param string $expectedOrderBy Expected ORDER BY clause
+ *
+ * @dataProvider providePropertyAndDirectionToGetEntityOrderedQueryBuilder
+ */
+ public function testGetEntityOrderedQueryBuilder($property, $direction, $expectedOrderBy)
{
- $items = [];
- Repository::replenishPositions($items);
+ $entityManager = $this->createMock(EntityManagerInterface::class);
- static::assertSame([], $items);
+ $entityRepository = $this
+ ->getMockBuilder(EntityRepository::class)
+ ->disableOriginalConstructor()
+ ->setMethods([
+ 'createQueryBuilder',
+ ])
+ ->getMock();
+
+ $expectedQueryBuilder = new QueryBuilder($entityManager);
+ $expectedQueryBuilder->from('any_table_name', 'qb');
+
+ $entityRepository
+ ->expects(static::once())
+ ->method('createQueryBuilder')
+ ->willReturn($expectedQueryBuilder)
+ ;
+
+ $queryBuilder = Repository::getEntityOrderedQueryBuilder($entityRepository, $property, $direction);
+ $selectDQLPart = $queryBuilder->getDQLPart('select');
+ $whereDQLPart = $queryBuilder->getDQLPart('where');
+ $orderDQLPart = $queryBuilder->getDQLPart('orderBy');
+ $rootAliases = $queryBuilder->getRootAliases();
+
+ static::assertInstanceOf(QueryBuilder::class, $queryBuilder);
+ static::assertArrayHasKey(0, $rootAliases);
+ static::assertSame('qb', $rootAliases[0]);
+ static::assertSame([], $selectDQLPart);
+ static::assertNull($whereDQLPart);
+
+ if (empty($property)) {
+ static::assertSame([], $orderDQLPart);
+ } else {
+ /** @var OrderBy $orderBy */
+ $orderBy = $orderDQLPart[0];
+
+ static::assertSame([$expectedOrderBy], $orderBy->getParts());
+ }
}
- public function testReplenishPositionsUsingNotSortableObjects()
+ public function testGetEntityOrderedQueryBuilderUsingDefaults()
{
- $before = [
- new stdClass(),
- new stdClass(),
- new stdClass(),
- ];
+ $entityManager = $this->createMock(EntityManagerInterface::class);
- $after = [
- new stdClass(),
- new stdClass(),
- new stdClass(),
- ];
+ $entityRepository = $this
+ ->getMockBuilder(EntityRepository::class)
+ ->disableOriginalConstructor()
+ ->setMethods([
+ 'createQueryBuilder',
+ ])
+ ->getMock();
- /*
- * Using defaults
- */
- Repository::replenishPositions($before);
- static::assertEquals($before, $after);
+ $expectedQueryBuilder = new QueryBuilder($entityManager);
+ $expectedQueryBuilder->from('any_table_name', 'qb');
- /*
- * Place items at the top
- */
- Repository::replenishPositions($before, false);
- static::assertEquals($before, $after);
+ $entityRepository
+ ->expects(static::once())
+ ->method('createQueryBuilder')
+ ->willReturn($expectedQueryBuilder)
+ ;
- /*
- * Set positions even there is no extreme position (at the end)
- */
- Repository::replenishPositions($before, true, true);
- static::assertEquals($before, $after);
+ $queryBuilder = Repository::getEntityOrderedQueryBuilder($entityRepository);
+ $selectDQLPart = $queryBuilder->getDQLPart('select');
+ $whereDQLPart = $queryBuilder->getDQLPart('where');
+ $orderDQLPart = $queryBuilder->getDQLPart('orderBy');
+ $rootAliases = $queryBuilder->getRootAliases();
- /*
- * Set positions even there is no extreme position (at the top)
- */
- Repository::replenishPositions($before, false, true);
- static::assertEquals($before, $after);
+ /** @var OrderBy $orderBy */
+ $orderBy = $orderDQLPart[0];
+
+ static::assertInstanceOf(QueryBuilder::class, $queryBuilder);
+ static::assertArrayHasKey(0, $rootAliases);
+ static::assertSame('qb', $rootAliases[0]);
+ static::assertSame([], $selectDQLPart);
+ static::assertNull($whereDQLPart);
+ static::assertSame(['qb.name ASC'], $orderBy->getParts());
+ }
+
+ /**
+ * @param array $items Objects who have "getPosition()" and "setPosition()" methods or arrays
+ * @param bool $max If is set to true, maximum value is returned. Otherwise - minimum.
+ * @param int $expected Extreme position (max or min) of given items
+ *
+ * @dataProvider provideArraysWithExtremePositionToGetExtremePosition
+ */
+ public function testGetExtremePositionUsingArraysWithExtremePosition(array $items, $max, $expected)
+ {
+ static::assertSame($expected, Repository::getExtremePosition($items, $max));
+ }
+
+ /**
+ * @param array $items Objects who have "getPosition()" and "setPosition()" methods or arrays
+ * @param bool $max If is set to true, maximum value is returned. Otherwise - minimum.
+ * @param int $expected Extreme position (max or min) of given items
+ *
+ * @dataProvider provideArraysWithoutExtremePositionToGetExtremePosition
+ */
+ public function testGetExtremePositionUsingArraysWithoutExtremePosition(array $items, $max, $expected)
+ {
+ static::assertSame($expected, Repository::getExtremePosition($items, $max));
+ }
+
+ /**
+ * @param array $items Objects who have "getPosition()" and "setPosition()" methods or arrays
+ * @param bool $max If is set to true, maximum value is returned. Otherwise - minimum.
+ * @param int $expected Extreme position (max or min) of given items
+ *
+ * @dataProvider provideObjectsWithExtremePositionToGetExtremePosition
+ */
+ public function testGetExtremePositionUsingObjectsWithExtremePosition(array $items, $max, $expected)
+ {
+ static::assertSame($expected, Repository::getExtremePosition($items, $max));
+ }
+
+ /**
+ * @param array $items Objects who have "getPosition()" and "setPosition()" methods or arrays
+ * @param bool $max If is set to true, maximum value is returned. Otherwise - minimum.
+ * @param int $expected Extreme position (max or min) of given items
+ *
+ * @dataProvider provideObjectsWithoutExtremePositionToGetExtremePosition
+ */
+ public function testGetExtremePositionUsingObjectsWithoutExtremePosition(array $items, $max, $expected)
+ {
+ static::assertSame($expected, Repository::getExtremePosition($items, $max));
+ }
+
+ public function testGetExtremePositionWithoutItems()
+ {
+ static::assertNull(Repository::getExtremePosition([]));
+ static::assertNull(Repository::getExtremePosition([], false));
+ }
+
+ /**
+ * @param array $items Objects who have "getPosition()" and "setPosition()" methods or arrays
+ * @param bool $asLast If is set to true, items are placed at the end (default behaviour). Otherwise - at top.
+ * @param array $expected Items with replenished positions
+ *
+ * @dataProvider provideArraysWithExtremePosition
+ */
+ public function testReplenishPositionsUsingArraysWithExtremePositionForce(array $items, $asLast, array $expected)
+ {
+ Repository::replenishPositions($items, $asLast, true);
+ static::assertSame($expected, $items);
}
/**
@@ -104,17 +838,48 @@ class RepositoryTest extends BaseTestCase
static::assertSame($expected, $items);
}
+ public function testReplenishPositionsUsingNotSortableObjects()
+ {
+ $before = [
+ new stdClass(),
+ new stdClass(),
+ new stdClass(),
+ ];
+
+ $after = [
+ new stdClass(),
+ new stdClass(),
+ new stdClass(),
+ ];
+
+ // Using defaults
+ Repository::replenishPositions($before);
+ static::assertEquals($before, $after);
+
+ // Place items at the top
+ Repository::replenishPositions($before, false);
+ static::assertEquals($before, $after);
+
+ // Set positions even there is no extreme position (at the end)
+ Repository::replenishPositions($before, true, true);
+ static::assertEquals($before, $after);
+
+ // Set positions even there is no extreme position (at the top)
+ Repository::replenishPositions($before, false, true);
+ static::assertEquals($before, $after);
+ }
+
/**
* @param array $items Objects who have "getPosition()" and "setPosition()" methods or arrays
* @param bool $asLast If is set to true, items are placed at the end (default behaviour). Otherwise - at top.
* @param array $expected Items with replenished positions
*
- * @dataProvider provideArraysWithExtremePosition
+ * @dataProvider provideObjectsWithExtremePosition
*/
- public function testReplenishPositionsUsingArraysWithExtremePositionForce(array $items, $asLast, array $expected)
+ public function testReplenishPositionsUsingObjectsWithExtremePositionForce(array $items, $asLast, array $expected)
{
Repository::replenishPositions($items, $asLast, true);
- static::assertSame($expected, $items);
+ static::assertEquals($expected, $items);
}
/**
@@ -144,695 +909,23 @@ class RepositoryTest extends BaseTestCase
}
/**
- * @param array $items Objects who have "getPosition()" and "setPosition()" methods or arrays
- * @param bool $asLast If is set to true, items are placed at the end (default behaviour). Otherwise - at top.
- * @param array $expected Items with replenished positions
+ * @param string $description Description of test
+ * @param array $items Objects who have "getPosition()" and "setPosition()" methods or arrays
+ * @param array $expected Expected items with positions replenished
*
- * @dataProvider provideObjectsWithExtremePosition
+ * @dataProvider provideSortedItems
*/
- public function testReplenishPositionsUsingObjectsWithExtremePositionForce(array $items, $asLast, array $expected)
+ public function testReplenishPositionsUsingSortedItems(string $description, array $items, array $expected)
{
- Repository::replenishPositions($items, $asLast, true);
- static::assertEquals($expected, $items);
+ Repository::replenishPositions($items);
+ static::assertSame($expected, $items, $description);
}
- public function testGetExtremePositionWithoutItems()
+ public function testReplenishPositionsWithoutItems()
{
- static::assertNull(Repository::getExtremePosition([]));
- static::assertNull(Repository::getExtremePosition([], false));
- }
+ $items = [];
+ Repository::replenishPositions($items);
- /**
- * @param array $items Objects who have "getPosition()" and "setPosition()" methods or arrays
- * @param bool $max If is set to true, maximum value is returned. Otherwise - minimum.
- * @param int $expected Extreme position (max or min) of given items
- *
- * @dataProvider provideArraysWithoutExtremePositionToGetExtremePosition
- */
- public function testGetExtremePositionUsingArraysWithoutExtremePosition(array $items, $max, $expected)
- {
- static::assertSame($expected, Repository::getExtremePosition($items, $max));
- }
-
- /**
- * @param array $items Objects who have "getPosition()" and "setPosition()" methods or arrays
- * @param bool $max If is set to true, maximum value is returned. Otherwise - minimum.
- * @param int $expected Extreme position (max or min) of given items
- *
- * @dataProvider provideArraysWithExtremePositionToGetExtremePosition
- */
- public function testGetExtremePositionUsingArraysWithExtremePosition(array $items, $max, $expected)
- {
- static::assertSame($expected, Repository::getExtremePosition($items, $max));
- }
-
- /**
- * @param array $items Objects who have "getPosition()" and "setPosition()" methods or arrays
- * @param bool $max If is set to true, maximum value is returned. Otherwise - minimum.
- * @param int $expected Extreme position (max or min) of given items
- *
- * @dataProvider provideObjectsWithoutExtremePositionToGetExtremePosition
- */
- public function testGetExtremePositionUsingObjectsWithoutExtremePosition(array $items, $max, $expected)
- {
- static::assertSame($expected, Repository::getExtremePosition($items, $max));
- }
-
- /**
- * @param array $items Objects who have "getPosition()" and "setPosition()" methods or arrays
- * @param bool $max If is set to true, maximum value is returned. Otherwise - minimum.
- * @param int $expected Extreme position (max or min) of given items
- *
- * @dataProvider provideObjectsWithExtremePositionToGetExtremePosition
- */
- public function testGetExtremePositionUsingObjectsWithExtremePosition(array $items, $max, $expected)
- {
- static::assertSame($expected, Repository::getExtremePosition($items, $max));
- }
-
- public function testGetEntityOrderedQueryBuilderUsingDefaults()
- {
- $entityManager = $this->getMock(EntityManagerInterface::class);
-
- $entityRepository = $this
- ->getMockBuilder(EntityRepository::class)
- ->disableOriginalConstructor()
- ->setMethods([
- 'createQueryBuilder',
- ])
- ->getMock()
- ;
-
- $expectedQueryBuilder = new QueryBuilder($entityManager);
- $expectedQueryBuilder->from('any_table_name', 'qb');
-
- $entityRepository
- ->expects(static::once())
- ->method('createQueryBuilder')
- ->willReturn($expectedQueryBuilder)
- ;
-
- $queryBuilder = Repository::getEntityOrderedQueryBuilder($entityRepository);
- $selectDQLPart = $queryBuilder->getDQLPart('select');
- $whereDQLPart = $queryBuilder->getDQLPart('where');
- $orderDQLPart = $queryBuilder->getDQLPart('orderBy');
-
- /* @var OrderBy $orderBy */
- $orderBy = $orderDQLPart[0];
-
- static::assertInstanceOf(QueryBuilder::class, $queryBuilder);
- static::assertArraySubset(['qb'], $queryBuilder->getRootAliases());
- static::assertSame([], $selectDQLPart);
- static::assertNull($whereDQLPart);
- static::assertSame(['qb.name ASC'], $orderBy->getParts());
- }
-
- /**
- * @param string $property Name of property used by the ORDER BY clause
- * @param string $direction Direction used by the ORDER BY clause ("ASC" or "DESC")
- * @param string $expectedOrderBy Expected ORDER BY clause
- *
- * @dataProvider providePropertyAndDirectionToGetEntityOrderedQueryBuilder
- */
- public function testGetEntityOrderedQueryBuilder($property, $direction, $expectedOrderBy)
- {
- $entityManager = $this->getMock(EntityManagerInterface::class);
-
- $entityRepository = $this
- ->getMockBuilder(EntityRepository::class)
- ->disableOriginalConstructor()
- ->setMethods([
- 'createQueryBuilder',
- ])
- ->getMock()
- ;
-
- $expectedQueryBuilder = new QueryBuilder($entityManager);
- $expectedQueryBuilder->from('any_table_name', 'qb');
-
- $entityRepository
- ->expects(static::once())
- ->method('createQueryBuilder')
- ->willReturn($expectedQueryBuilder)
- ;
-
- $queryBuilder = Repository::getEntityOrderedQueryBuilder($entityRepository, $property, $direction);
- $selectDQLPart = $queryBuilder->getDQLPart('select');
- $whereDQLPart = $queryBuilder->getDQLPart('where');
- $orderDQLPart = $queryBuilder->getDQLPart('orderBy');
-
- static::assertInstanceOf(QueryBuilder::class, $queryBuilder);
- static::assertArraySubset(['qb'], $queryBuilder->getRootAliases());
- static::assertSame([], $selectDQLPart);
- static::assertNull($whereDQLPart);
-
- if (empty($property)) {
- static::assertSame([], $orderDQLPart);
- } else {
- /* @var OrderBy $orderBy */
- $orderBy = $orderDQLPart[0];
-
- static::assertSame([$expectedOrderBy], $orderBy->getParts());
- }
- }
-
- /**
- * Provides arrays without extreme position used to replenish positions of them
- *
- * @return Generator
- */
- public function provideArraysWithoutExtremePosition()
- {
- yield[
- [
- [],
- [],
- ],
- true,
- [
- [
- Repository::POSITION_KEY => 1,
- ],
- [
- Repository::POSITION_KEY => 2,
- ],
- ],
- ];
-
- yield[
- [
- [],
- [],
- ],
- false,
- [
- [
- Repository::POSITION_KEY => -1,
- ],
- [
- Repository::POSITION_KEY => -2,
- ],
- ],
- ];
-
- yield[
- [
- [
- 'lorem' => 'ipsum',
- 'dolor',
- 'sit' => 1,
- ],
- [
- 'abc' => 'def',
- 'ghi' => null,
- 'jkl' => 10,
- ],
- ],
- true,
- [
- [
- 'lorem' => 'ipsum',
- 'dolor',
- 'sit' => 1,
- Repository::POSITION_KEY => 1,
- ],
- [
- 'abc' => 'def',
- 'ghi' => null,
- 'jkl' => 10,
- Repository::POSITION_KEY => 2,
- ],
- ],
- ];
-
- yield[
- [
- [
- 'lorem' => 'ipsum',
- 'dolor',
- 'sit' => 1,
- ],
- [
- 'abc' => 'def',
- 'ghi' => null,
- 'jkl' => 10,
- ],
- ],
- false,
- [
- [
- 'lorem' => 'ipsum',
- 'dolor',
- 'sit' => 1,
- Repository::POSITION_KEY => -1,
- ],
- [
- 'abc' => 'def',
- 'ghi' => null,
- 'jkl' => 10,
- Repository::POSITION_KEY => -2,
- ],
- ],
- ];
- }
-
- /**
- * Provides arrays with extreme position used to replenish positions of them
- *
- * @return Generator
- */
- public function provideArraysWithExtremePosition()
- {
- yield[
- [
- [
- Repository::POSITION_KEY => 1,
- ],
- [],
- [],
- ],
- true,
- [
- [
- Repository::POSITION_KEY => 1,
- ],
- [
- Repository::POSITION_KEY => 2,
- ],
- [
- Repository::POSITION_KEY => 3,
- ],
- ],
- ];
-
- yield[
- [
- [],
- [],
- [
- Repository::POSITION_KEY => 1,
- ],
- ],
- true,
- [
- [
- Repository::POSITION_KEY => 2,
- ],
- [
- Repository::POSITION_KEY => 3,
- ],
- [
- Repository::POSITION_KEY => 1,
- ],
- ],
- ];
-
- yield[
- [
- [
- Repository::POSITION_KEY => 1,
- ],
- [],
- [],
- ],
- false,
- [
- [
- Repository::POSITION_KEY => 1,
- ],
- [
- Repository::POSITION_KEY => 0,
- ],
- [
- Repository::POSITION_KEY => -1,
- ],
- ],
- ];
-
- yield[
- [
- [],
- [],
- [
- Repository::POSITION_KEY => 1,
- ],
- ],
- false,
- [
- [
- Repository::POSITION_KEY => 0,
- ],
- [
- Repository::POSITION_KEY => -1,
- ],
- [
- Repository::POSITION_KEY => 1,
- ],
- ],
- ];
- }
-
- /**
- * Provides objects without extreme position used to replenish positions of them
- *
- * @return Generator
- */
- public function provideObjectsWithoutExtremePosition()
- {
- yield[
- [
- new Sortable(),
- new Sortable(),
- new Sortable(),
- ],
- true,
- [
- new Sortable(1),
- new Sortable(2),
- new Sortable(3),
- ],
- ];
-
- yield[
- [
- new Sortable(),
- new Sortable(),
- new Sortable(),
- ],
- false,
- [
- new Sortable(-1),
- new Sortable(-2),
- new Sortable(-3),
- ],
- ];
- }
-
- /**
- * Provides objects with extreme position used to replenish positions of them
- *
- * @return Generator
- */
- public function provideObjectsWithExtremePosition()
- {
- yield[
- [
- new Sortable(1),
- new Sortable(),
- new Sortable(),
- ],
- true,
- [
- new Sortable(1),
- new Sortable(2),
- new Sortable(3),
- ],
- ];
-
- yield[
- [
- new Sortable(),
- new Sortable(1),
- new Sortable(),
- ],
- true,
- [
- new Sortable(2),
- new Sortable(1),
- new Sortable(3),
- ],
- ];
-
- yield[
- [
- new Sortable(1),
- new Sortable(),
- new Sortable(),
- ],
- false,
- [
- new Sortable(1),
- new Sortable(0),
- new Sortable(-1),
- ],
- ];
- }
-
- /**
- * Provides arrays without extreme position used to get extreme position
- *
- * @return Generator
- */
- public function provideArraysWithoutExtremePositionToGetExtremePosition()
- {
- yield[
- [],
- false,
- null,
- ];
-
- yield[
- [],
- true,
- null,
- ];
-
- yield[
- [
- [
- 'lorem' => 'ipsum',
- 'dolor',
- 'sit' => 1,
- ],
- [
- 'abc' => 'def',
- 'ghi' => null,
- 'jkl' => 10,
- ],
- ],
- true,
- null,
- ];
-
- yield[
- [
- [
- 'lorem' => 'ipsum',
- 'dolor',
- 'sit' => 1,
- ],
- [
- 'abc' => 'def',
- 'ghi' => null,
- 'jkl' => 10,
- ],
- ],
- false,
- null,
- ];
- }
-
- /**
- * Provides arrays with extreme position used to get extreme position
- *
- * @return Generator
- */
- public function provideArraysWithExtremePositionToGetExtremePosition()
- {
- yield[
- [
- [
- Repository::POSITION_KEY => 1,
- ],
- [],
- [],
- ],
- true,
- 1,
- ];
-
- yield[
- [
- [
- Repository::POSITION_KEY => 1,
- ],
- [],
- [],
- ],
- false,
- 1,
- ];
-
- yield[
- [
- [],
- [],
- [
- Repository::POSITION_KEY => 1,
- ],
- ],
- true,
- 1,
- ];
-
- yield[
- [
- [],
- [],
- [
- Repository::POSITION_KEY => 1,
- ],
- ],
- false,
- 1,
- ];
-
- yield[
- [
- [
- Repository::POSITION_KEY => 1,
- ],
- [],
- [
- Repository::POSITION_KEY => 2,
- ],
- [],
- ],
- true,
- 2,
- ];
-
- yield[
- [
- [
- Repository::POSITION_KEY => 1,
- ],
- [],
- [
- Repository::POSITION_KEY => 2,
- ],
- [],
- ],
- false,
- 1,
- ];
- }
-
- /**
- * Provides objects without extreme position used to get extreme position
- *
- * @return Generator
- */
- public function provideObjectsWithoutExtremePositionToGetExtremePosition()
- {
- yield[
- [],
- false,
- null,
- ];
-
- yield[
- [],
- true,
- null,
- ];
-
- yield[
- [
- new Sortable(),
- new Sortable(),
- new Sortable(),
- ],
- true,
- null,
- ];
-
- yield[
- [
- new Sortable(),
- new Sortable(),
- new Sortable(),
- ],
- false,
- null,
- ];
- }
-
- /**
- * Provides objects with extreme position used to get extreme position
- *
- * @return Generator
- */
- public function provideObjectsWithExtremePositionToGetExtremePosition()
- {
- yield[
- [
- new Sortable(1),
- new Sortable(2),
- new Sortable(3),
- ],
- true,
- 3,
- ];
-
- yield[
- [
- new Sortable(1),
- new Sortable(2),
- new Sortable(3),
- ],
- false,
- 1,
- ];
- }
-
- /**
- * Provide name of property, direction and expected ORDER BY clause used to get query builder
- *
- * @return Generator
- */
- public function providePropertyAndDirectionToGetEntityOrderedQueryBuilder()
- {
- yield[
- null,
- null,
- '',
- ];
-
- yield[
- '',
- '',
- '',
- ];
-
- yield[
- 'first_name',
- '',
- 'qb.first_name ASC',
- ];
-
- yield[
- 'first_name',
- 'asc',
- 'qb.first_name asc',
- ];
-
- yield[
- 'first_name',
- 'ASC',
- 'qb.first_name ASC',
- ];
-
- yield[
- 'first_name',
- 'desc',
- 'qb.first_name desc',
- ];
-
- yield[
- 'first_name',
- 'DESC',
- 'qb.first_name DESC',
- ];
+ static::assertSame([], $items);
}
}
diff --git a/tests/Utilities/UriTest.php b/tests/Utilities/UriTest.php
index 20b1eaf..da660ff 100644
--- a/tests/Utilities/UriTest.php
+++ b/tests/Utilities/UriTest.php
@@ -17,12 +17,180 @@ use Meritoo\Common\Utilities\Uri;
*
* @author Meritoo
* @copyright Meritoo
+ *
+ * @internal
+ * @covers \Meritoo\Common\Utilities\Uri
*/
class UriTest extends BaseTestCase
{
- public function testConstructor()
+ /**
+ * Provides data used to build secured url
+ *
+ * @return Generator
+ */
+ public function provideDataForSecuredUrl()
{
- static::assertHasNoConstructor(Uri::class);
+ yield [
+ '',
+ '',
+ '',
+ '',
+ ];
+
+ yield [
+ '/',
+ '',
+ '',
+ 'http://lorem.com/',
+ ];
+
+ yield [
+ 'contact',
+ '',
+ '',
+ 'http://lorem.com/contact',
+ ];
+
+ yield [
+ 'contact',
+ 'john',
+ '',
+ 'http://lorem.com/contact',
+ ];
+
+ yield [
+ 'contact',
+ '',
+ 'pass123',
+ 'http://lorem.com/contact',
+ ];
+
+ yield [
+ 'contact',
+ 'john',
+ 'pass123',
+ 'http://john:pass123@lorem.com/contact',
+ ];
+ }
+
+ public function provideRootUrlAndUrlParts(): ?Generator
+ {
+ yield [
+ '',
+ '',
+ ];
+
+ yield [
+ '',
+ '',
+ '',
+ ];
+
+ yield [
+ 'http://my.example',
+ 'http://my.example',
+ '',
+ ];
+
+ yield [
+ 'http://my.example',
+ 'http://my.example',
+ '',
+ '',
+ ];
+
+ yield [
+ 'http://my.example//test/12/test/',
+ 'http://my.example',
+ '',
+ 'test',
+ '12/test',
+ '',
+ ];
+
+ yield [
+ 'http://my.example//test/12/test',
+ 'http://my.example',
+ '',
+ 'test/',
+ '12/test/',
+ ];
+
+ yield [
+ 'http://my.example/test/12/test/',
+ 'http://my.example',
+ '/test/',
+ '/12/test',
+ '',
+ ];
+ }
+
+ /**
+ * Provides url to replenish protocol
+ *
+ * @return Generator
+ */
+ public function provideUrlToReplenishProtocol()
+ {
+ yield [
+ 'http://test',
+ 'test',
+ '',
+ ];
+
+ yield [
+ 'ftp://lorem.ipsum',
+ 'lorem.ipsum',
+ 'ftp',
+ ];
+ }
+
+ /**
+ * Provides url used to verify if it's external, from another server / domain
+ *
+ * @return Generator
+ */
+ public function provideUrlToVerifyIfIsExternal()
+ {
+ yield [
+ '',
+ false,
+ ];
+
+ yield [
+ '/',
+ false,
+ ];
+
+ yield [
+ 'http://something.different/first-page',
+ true,
+ ];
+
+ yield [
+ 'something.different/first-page',
+ true,
+ ];
+
+ yield [
+ 'http://lorem.com',
+ false,
+ ];
+
+ yield [
+ 'http://lorem.com/contact',
+ false,
+ ];
+
+ yield [
+ 'lorem.com',
+ false,
+ ];
+
+ yield [
+ 'lorem.com/contact',
+ false,
+ ];
}
public function testAddProtocolToUrl()
@@ -42,52 +210,20 @@ class UriTest extends BaseTestCase
}
/**
- * @param mixed $url Empty value, e.g. ""
- * @dataProvider provideEmptyValue
- */
- public function testReplenishProtocolEmptyUrl($url)
- {
- self::assertEquals('', Uri::replenishProtocol($url));
- }
-
- /**
- * @param string $expected Expected result
- * @param string $url The url to check and replenish
- * @param string $protocol (optional) The protocol which is replenished. If is empty, protocol of current request
- * is used.
+ * @param string $expected
+ * @param string $rootUrl
+ * @param string ...$urlParts
*
- * @dataProvider provideUrlToReplenishProtocol
+ * @dataProvider provideRootUrlAndUrlParts
*/
- public function testReplenishProtocol($expected, $url, $protocol = '')
+ public function testBuildUrl(string $expected, string $rootUrl, string ...$urlParts): void
{
- self::assertSame($expected, Uri::replenishProtocol($url, $protocol));
+ static::assertSame($expected, Uri::buildUrl($rootUrl, ...$urlParts));
}
- public function testGetServerNameOrIpWithoutProtocol()
+ public function testConstructor()
{
- $_SERVER['HTTP_HOST'] = '';
- self::assertEquals('', Uri::getServerNameOrIp());
-
- $host = 'lorem.com';
- $_SERVER['HTTP_HOST'] = $host;
-
- self::assertEquals($host, Uri::getServerNameOrIp());
- }
-
- public function testGetServerNameOrIpWithProtocol()
- {
- $_SERVER['HTTP_HOST'] = '';
- $_SERVER['SERVER_PROTOCOL'] = '';
-
- self::assertEquals('', Uri::getServerNameOrIp(true));
-
- $host = 'lorem.com';
- $protocol = 'HTTP/1.1';
-
- $_SERVER['HTTP_HOST'] = $host;
- $_SERVER['SERVER_PROTOCOL'] = $protocol;
-
- self::assertEquals(sprintf('http://%s', $host), Uri::getServerNameOrIp(true));
+ static::assertHasNoConstructor(Uri::class);
}
public function testGetFullUriWithHost()
@@ -145,6 +281,49 @@ class UriTest extends BaseTestCase
self::assertEquals($refererUrl, Uri::getRefererUri());
}
+ /**
+ * @param string $url A path / url to some resource, e.g. page, image, css file
+ * @param string $user User name used to log in
+ * @param string $password User password used to log in
+ * @param string $expectedUrl Expected, secured url
+ *
+ * @dataProvider provideDataForSecuredUrl
+ */
+ public function testGetSecuredUrl($url, $user, $password, $expectedUrl)
+ {
+ $_SERVER['SERVER_PROTOCOL'] = 'HTTP/1.1';
+ $_SERVER['HTTP_HOST'] = 'lorem.com';
+
+ self::assertEquals($expectedUrl, Uri::getSecuredUrl($url, $user, $password));
+ }
+
+ public function testGetServerNameOrIpWithProtocol()
+ {
+ $_SERVER['HTTP_HOST'] = '';
+ $_SERVER['SERVER_PROTOCOL'] = '';
+
+ self::assertEquals('', Uri::getServerNameOrIp(true));
+
+ $host = 'lorem.com';
+ $protocol = 'HTTP/1.1';
+
+ $_SERVER['HTTP_HOST'] = $host;
+ $_SERVER['SERVER_PROTOCOL'] = $protocol;
+
+ self::assertEquals(sprintf('http://%s', $host), Uri::getServerNameOrIp(true));
+ }
+
+ public function testGetServerNameOrIpWithoutProtocol()
+ {
+ $_SERVER['HTTP_HOST'] = '';
+ self::assertEquals('', Uri::getServerNameOrIp());
+
+ $host = 'lorem.com';
+ $_SERVER['HTTP_HOST'] = $host;
+
+ self::assertEquals($host, Uri::getServerNameOrIp());
+ }
+
public function testGetUserAddressIp()
{
$_SERVER['REMOTE_ADDR'] = '';
@@ -156,58 +335,49 @@ class UriTest extends BaseTestCase
self::assertEquals($userAddressIp, Uri::getUserAddressIp());
}
+ public function testGetUserOperatingSystemName()
+ {
+ $_SERVER['HTTP_USER_AGENT'] = '';
+ self::assertEquals('', Uri::getUserOperatingSystemName());
+
+ $_SERVER['HTTP_USER_AGENT'] = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/600.2.5 (KHTML, like'
+ .' Gecko) Version/8.0.2 Safari/600.2.5';
+
+ self::assertEquals('Mac OS', Uri::getUserOperatingSystemName());
+ }
+
public function testGetUserWebBrowserInfo()
{
$_SERVER['HTTP_USER_AGENT'] = '';
self::assertEquals('', Uri::getUserWebBrowserInfo());
$browserInfo = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/600.2.5 (KHTML, like Gecko)'
- . ' Version/8.0.2 Safari/600.2.5';
+ .' Version/8.0.2 Safari/600.2.5';
$_SERVER['HTTP_USER_AGENT'] = $browserInfo;
self::assertEquals($browserInfo, Uri::getUserWebBrowserInfo());
}
- public function testGetUserWebBrowserNameWithoutVersion()
- {
- $_SERVER['HTTP_USER_AGENT'] = '';
- self::assertEquals('', Uri::getUserWebBrowserName());
-
- $_SERVER['HTTP_USER_AGENT'] = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/600.2.5 (KHTML, like'
- . ' Gecko) Version/8.0.2 Safari/600.2.5';
-
- self::assertEquals('Apple Safari', Uri::getUserWebBrowserName());
- }
-
public function testGetUserWebBrowserNameWithVersion()
{
$_SERVER['HTTP_USER_AGENT'] = '';
self::assertEquals('', Uri::getUserWebBrowserName(true));
$_SERVER['HTTP_USER_AGENT'] = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/600.2.5 (KHTML, like'
- . ' Gecko) Version/8.0.2 Safari/600.2.5';
+ .' Gecko) Version/8.0.2 Safari/600.2.5';
self::assertEquals('Apple Safari 600.2.5', Uri::getUserWebBrowserName(true));
}
- public function testGetUserOperatingSystemName()
+ public function testGetUserWebBrowserNameWithoutVersion()
{
$_SERVER['HTTP_USER_AGENT'] = '';
- self::assertEquals('', Uri::getUserOperatingSystemName());
+ self::assertEquals('', Uri::getUserWebBrowserName());
$_SERVER['HTTP_USER_AGENT'] = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/600.2.5 (KHTML, like'
- . ' Gecko) Version/8.0.2 Safari/600.2.5';
+ .' Gecko) Version/8.0.2 Safari/600.2.5';
- self::assertEquals('Mac OS', Uri::getUserOperatingSystemName());
- }
-
- public function testIsServerLocalhost()
- {
- $_SERVER['HTTP_HOST'] = '';
- self::assertFalse(Uri::isServerLocalhost());
-
- $_SERVER['HTTP_HOST'] = '127.0.0.1';
- self::assertTrue(Uri::isServerLocalhost());
+ self::assertEquals('Apple Safari', Uri::getUserWebBrowserName());
}
/**
@@ -227,137 +397,43 @@ class UriTest extends BaseTestCase
self::assertEquals($expected, Uri::isExternalUrl($url));
}
- /**
- * @param string $url A path / url to some resource, e.g. page, image, css file
- * @param string $user User name used to log in
- * @param string $password User password used to log in
- * @param string $expectedUrl Expected, secured url
- *
- * @dataProvider provideDataForSecuredUrl
- */
- public function testGetSecuredUrl($url, $user, $password, $expectedUrl)
+ public function testIsServerLocalhost()
{
+ $_SERVER['HTTP_HOST'] = '';
+ self::assertFalse(Uri::isServerLocalhost());
+
+ $_SERVER['HTTP_HOST'] = '127.0.0.1';
+ self::assertTrue(Uri::isServerLocalhost());
+ }
+
+ /**
+ * @param string $expected Expected result
+ * @param string $url The url to check and replenish
+ * @param string $protocol (optional) The protocol which is replenished. If is empty, protocol of current request
+ * is used.
+ *
+ * @dataProvider provideUrlToReplenishProtocol
+ */
+ public function testReplenishProtocol($expected, $url, $protocol = '')
+ {
+ /*
+ * Required to get protocol when it's not provided and to void test failure:
+ *
+ * Failed asserting that two strings are identical.
+ * Expected :'://test'
+ * Actual :'http://test'
+ */
$_SERVER['SERVER_PROTOCOL'] = 'HTTP/1.1';
- $_SERVER['HTTP_HOST'] = 'lorem.com';
- self::assertEquals($expectedUrl, Uri::getSecuredUrl($url, $user, $password));
+ self::assertSame($expected, Uri::replenishProtocol($url, $protocol));
}
/**
- * Provides url to replenish protocol
- *
- * @return Generator
+ * @param mixed $url Empty value, e.g. ""
+ * @dataProvider provideEmptyValue
*/
- public function provideUrlToReplenishProtocol()
+ public function testReplenishProtocolEmptyUrl($url)
{
- yield[
- '://test',
- 'test',
- '',
- ];
-
- yield[
- 'ftp://lorem.ipsum',
- 'lorem.ipsum',
- 'ftp',
- ];
- }
-
- /**
- * Provides url used to verify if it's external, from another server / domain
- *
- * @return Generator
- */
- public function provideUrlToVerifyIfIsExternal()
- {
- yield[
- '',
- false,
- ];
-
- yield[
- '/',
- false,
- ];
-
- yield[
- 'http://something.different/first-page',
- true,
- ];
-
- yield[
- 'something.different/first-page',
- true,
- ];
-
- yield[
- 'http://lorem.com',
- false,
- ];
-
- yield[
- 'http://lorem.com/contact',
- false,
- ];
-
- yield[
- 'lorem.com',
- false,
- ];
-
- yield[
- 'lorem.com/contact',
- false,
- ];
- }
-
- /**
- * Provides data used to build secured url
- *
- * @return Generator
- */
- public function provideDataForSecuredUrl()
- {
- yield[
- '',
- '',
- '',
- '',
- ];
-
- yield[
- '/',
- '',
- '',
- 'http://lorem.com/',
- ];
-
- yield[
- 'contact',
- '',
- '',
- 'http://lorem.com/contact',
- ];
-
- yield[
- 'contact',
- 'john',
- '',
- 'http://lorem.com/contact',
- ];
-
- yield[
- 'contact',
- '',
- 'pass123',
- 'http://lorem.com/contact',
- ];
-
- yield[
- 'contact',
- 'john',
- 'pass123',
- 'http://john:pass123@lorem.com/contact',
- ];
+ self::assertEquals('', Uri::replenishProtocol($url));
}
}
diff --git a/tests/Utilities/XmlTest.php b/tests/Utilities/XmlTest.php
index 494aabf..1683bc1 100644
--- a/tests/Utilities/XmlTest.php
+++ b/tests/Utilities/XmlTest.php
@@ -17,6 +17,9 @@ use SimpleXMLElement;
*
* @author Meritoo
* @copyright Meritoo
+ *
+ * @internal
+ * @covers \Meritoo\Common\Utilities\Xml
*/
class XmlTest extends BaseTestCase
{
@@ -30,29 +33,25 @@ class XmlTest extends BaseTestCase
public function testMergeNodes()
{
- /*
- * An empty XMLs
- */
+ // An empty XMLs
$element1 = new SimpleXMLElement('');
$element2 = new SimpleXMLElement('');
$merged = Xml::mergeNodes($element1, $element2);
- self::assertEquals('', (string)$merged);
+ self::assertEquals('', (string) $merged);
- /*
- * XMLs with data
- */
+ // XMLs with data
$element1 = new SimpleXMLElement($this->simpleXml);
$element2 = new SimpleXMLElement($this->advancedXml);
$merged = Xml::mergeNodes($element1, $element2);
- self::assertEquals('John', (string)$merged->author[0]->first_name);
+ self::assertEquals('John', (string) $merged->author[0]->first_name);
}
/**
* {@inheritdoc}
*/
- protected function setUp()
+ protected function setUp(): void
{
parent::setUp();
@@ -86,11 +85,10 @@ class XmlTest extends BaseTestCase
/**
* {@inheritdoc}
*/
- protected function tearDown()
+ protected function tearDown(): void
{
parent::tearDown();
- unset($this->simpleXml);
- unset($this->advancedXml);
+ unset($this->simpleXml, $this->advancedXml);
}
}
diff --git a/tests/ValueObject/AddressTest.php b/tests/ValueObject/AddressTest.php
index 5cd1899..63981e7 100644
--- a/tests/ValueObject/AddressTest.php
+++ b/tests/ValueObject/AddressTest.php
@@ -17,6 +17,9 @@ use Meritoo\Common\ValueObject\Address;
*
* @author Meritoo
* @copyright Meritoo
+ *
+ * @internal
+ * @covers \Meritoo\Common\ValueObject\Address
*/
class AddressTest extends BaseTestCase
{
@@ -45,13 +48,6 @@ class AddressTest extends BaseTestCase
);
}
- public function testGetFlatNumber()
- {
- static::assertSame('200', $this->address->getFlatNumber());
- static::assertSame('', $this->addressWithoutFlat->getFlatNumber());
- static::assertSame('300', $this->addressWithoutStreet->getFlatNumber());
- }
-
public function testGetBuildingNumber()
{
static::assertSame('10', $this->address->getBuildingNumber());
@@ -59,11 +55,18 @@ class AddressTest extends BaseTestCase
static::assertSame('1', $this->addressWithoutStreet->getBuildingNumber());
}
- public function testGetStreet()
+ public function testGetCity()
{
- static::assertSame('4th Avenue', $this->address->getStreet());
- static::assertSame('Green Street', $this->addressWithoutFlat->getStreet());
- static::assertSame('', $this->addressWithoutStreet->getStreet());
+ static::assertSame('New York', $this->address->getCity());
+ static::assertSame('San Francisco', $this->addressWithoutFlat->getCity());
+ static::assertSame('Saint Louis', $this->addressWithoutStreet->getCity());
+ }
+
+ public function testGetFlatNumber()
+ {
+ static::assertSame('200', $this->address->getFlatNumber());
+ static::assertSame('', $this->addressWithoutFlat->getFlatNumber());
+ static::assertSame('300', $this->addressWithoutStreet->getFlatNumber());
}
public function testGetFullStreet()
@@ -73,11 +76,11 @@ class AddressTest extends BaseTestCase
static::assertSame('', $this->addressWithoutStreet->getFullStreet());
}
- public function testGetCity()
+ public function testGetStreet()
{
- static::assertSame('New York', $this->address->getCity());
- static::assertSame('San Francisco', $this->addressWithoutFlat->getCity());
- static::assertSame('Saint Louis', $this->addressWithoutStreet->getCity());
+ static::assertSame('4th Avenue', $this->address->getStreet());
+ static::assertSame('Green Street', $this->addressWithoutFlat->getStreet());
+ static::assertSame('', $this->addressWithoutStreet->getStreet());
}
public function testGetZipCode()
@@ -89,12 +92,12 @@ class AddressTest extends BaseTestCase
public function testToString()
{
- static::assertSame('4th Avenue 10/200, 00123, New York', (string)$this->address);
- static::assertSame('Green Street 22, 00456, San Francisco', (string)$this->addressWithoutFlat);
- static::assertSame('00111, Saint Louis', (string)$this->addressWithoutStreet);
+ static::assertSame('4th Avenue 10/200, 00123, New York', (string) $this->address);
+ static::assertSame('Green Street 22, 00456, San Francisco', (string) $this->addressWithoutFlat);
+ static::assertSame('00111, Saint Louis', (string) $this->addressWithoutStreet);
}
- protected function setUp()
+ protected function setUp(): void
{
parent::setUp();
diff --git a/tests/ValueObject/BankAccountTest.php b/tests/ValueObject/BankAccountTest.php
index ac38dbc..52277be 100644
--- a/tests/ValueObject/BankAccountTest.php
+++ b/tests/ValueObject/BankAccountTest.php
@@ -17,6 +17,9 @@ use Meritoo\Common\ValueObject\BankAccount;
*
* @author Meritoo
* @copyright Meritoo
+ *
+ * @internal
+ * @covers \Meritoo\Common\ValueObject\BankAccount
*/
class BankAccountTest extends BaseTestCase
{
@@ -54,14 +57,14 @@ class BankAccountTest extends BaseTestCase
public function testToString()
{
- static::assertSame('', (string)$this->emptyBankAccount);
- static::assertSame('Bank of America, 1234567890', (string)$this->bankAccount);
+ static::assertSame('', (string) $this->emptyBankAccount);
+ static::assertSame('Bank of America, 1234567890', (string) $this->bankAccount);
}
/**
* {@inheritdoc}
*/
- protected function setUp()
+ protected function setUp(): void
{
parent::setUp();
diff --git a/tests/ValueObject/CompanyTest.php b/tests/ValueObject/CompanyTest.php
index 383b012..dcd66c7 100644
--- a/tests/ValueObject/CompanyTest.php
+++ b/tests/ValueObject/CompanyTest.php
@@ -19,6 +19,9 @@ use Meritoo\Common\ValueObject\Company;
*
* @author Meritoo
* @copyright Meritoo
+ *
+ * @internal
+ * @covers \Meritoo\Common\ValueObject\Company
*/
class CompanyTest extends BaseTestCase
{
@@ -42,12 +45,6 @@ class CompanyTest extends BaseTestCase
);
}
- public function testGetName()
- {
- static::assertSame('Test 1', $this->company->getName());
- static::assertSame('Test 2', $this->companyWithoutBankAccount->getName());
- }
-
public function testGetAddress()
{
static::assertEquals(
@@ -71,16 +68,22 @@ class CompanyTest extends BaseTestCase
static::assertNull($this->companyWithoutBankAccount->getBankAccount());
}
+ public function testGetName()
+ {
+ static::assertSame('Test 1', $this->company->getName());
+ static::assertSame('Test 2', $this->companyWithoutBankAccount->getName());
+ }
+
public function testToString()
{
- static::assertSame('Test 1, 4th Avenue 10/200, 00123, New York, Bank 1, 12345', (string)$this->company);
- static::assertSame('Test 2, Green Street 22, 00456, San Francisco', (string)$this->companyWithoutBankAccount);
+ static::assertSame('Test 1, 4th Avenue 10/200, 00123, New York, Bank 1, 12345', (string) $this->company);
+ static::assertSame('Test 2, Green Street 22, 00456, San Francisco', (string) $this->companyWithoutBankAccount);
}
/**
* {@inheritdoc}
*/
- protected function setUp()
+ protected function setUp(): void
{
parent::setUp();
diff --git a/tests/ValueObject/HumanTest.php b/tests/ValueObject/HumanTest.php
index 1a58e35..63e39d3 100644
--- a/tests/ValueObject/HumanTest.php
+++ b/tests/ValueObject/HumanTest.php
@@ -8,6 +8,7 @@
namespace Meritoo\Test\Common\ValueObject;
+use DateTime;
use Meritoo\Common\Test\Base\BaseTestCase;
use Meritoo\Common\Type\OopVisibilityType;
use Meritoo\Common\ValueObject\Human;
@@ -17,9 +18,39 @@ use Meritoo\Common\ValueObject\Human;
*
* @author Meritoo
* @copyright Meritoo
+ *
+ * @internal
+ * @covers \Meritoo\Common\ValueObject\Human
*/
class HumanTest extends BaseTestCase
{
+ public function provideHuman()
+ {
+ yield [
+ 'Without any data (an empty human)',
+ new Human('', ''),
+ '',
+ ];
+
+ yield [
+ 'With first and last name only',
+ new Human('John', 'Scott'),
+ 'John Scott',
+ ];
+
+ yield [
+ 'With first name, last name and email',
+ new Human('John', 'Scott', 'john@scott.com'),
+ 'John Scott ',
+ ];
+
+ yield [
+ 'With whole/complete data',
+ new Human('John', 'Scott', 'john@scott.com', new DateTime('2001-01-01')),
+ 'John Scott ',
+ ];
+ }
+
public function testConstructor()
{
static::assertConstructorVisibilityAndArguments(
@@ -30,52 +61,13 @@ class HumanTest extends BaseTestCase
);
}
- /**
- * @param string $description Description of test
- * @param Human $human Human to verify
- * @param string $expected Expected string
- *
- * @dataProvider provideHuman
- */
- public function testToString($description, Human $human, $expected)
- {
- static::assertSame($expected, (string)$human, $description);
- }
-
- public function testGetFirstName()
- {
- $empty = new Human('', '');
- static::assertSame('', $empty->getFirstName());
-
- $human = new Human('John', 'Scott');
- static::assertSame('John', $human->getFirstName());
- }
-
- public function testGetLastName()
- {
- $empty = new Human('', '');
- static::assertSame('', $empty->getLastName());
-
- $human = new Human('John', 'Scott');
- static::assertSame('Scott', $human->getLastName());
- }
-
public function testGetBirthDate()
{
$empty = new Human('', '');
static::assertNull($empty->getBirthDate());
- $human = new Human('John', 'Scott', '', new \DateTime('2001-01-01'));
- static::assertEquals(new \DateTime('2001-01-01'), $human->getBirthDate());
- }
-
- public function testGetFullName()
- {
- $empty = new Human('', '');
- static::assertSame('', $empty->getFullName());
-
- $human = new Human('John', 'Scott', '', new \DateTime('2001-01-01'));
- static::assertSame('John Scott', $human->getFullName());
+ $human = new Human('John', 'Scott', '', new DateTime('2001-01-01'));
+ static::assertEquals(new DateTime('2001-01-01'), $human->getBirthDate());
}
public function testGetEmail()
@@ -87,30 +79,42 @@ class HumanTest extends BaseTestCase
static::assertSame('john@scott.com', $human->getEmail());
}
- public function provideHuman()
+ public function testGetFirstName()
{
- yield[
- 'Without any data (an empty human)',
- new Human('', ''),
- '',
- ];
+ $empty = new Human('', '');
+ static::assertSame('', $empty->getFirstName());
- yield[
- 'With first and last name only',
- new Human('John', 'Scott'),
- 'John Scott',
- ];
+ $human = new Human('John', 'Scott');
+ static::assertSame('John', $human->getFirstName());
+ }
- yield[
- 'With first name, last name and email',
- new Human('John', 'Scott', 'john@scott.com'),
- 'John Scott ',
- ];
+ public function testGetFullName()
+ {
+ $empty = new Human('', '');
+ static::assertSame('', $empty->getFullName());
- yield[
- 'With whole/complete data',
- new Human('John', 'Scott', 'john@scott.com', new \DateTime('2001-01-01')),
- 'John Scott ',
- ];
+ $human = new Human('John', 'Scott', '', new DateTime('2001-01-01'));
+ static::assertSame('John Scott', $human->getFullName());
+ }
+
+ public function testGetLastName()
+ {
+ $empty = new Human('', '');
+ static::assertSame('', $empty->getLastName());
+
+ $human = new Human('John', 'Scott');
+ static::assertSame('Scott', $human->getLastName());
+ }
+
+ /**
+ * @param string $description Description of test
+ * @param Human $human Human to verify
+ * @param string $expected Expected string
+ *
+ * @dataProvider provideHuman
+ */
+ public function testToString($description, Human $human, $expected)
+ {
+ static::assertSame($expected, (string) $human, $description);
}
}
diff --git a/tests/ValueObject/SizeTest.php b/tests/ValueObject/SizeTest.php
index b3dbbbd..37044f2 100644
--- a/tests/ValueObject/SizeTest.php
+++ b/tests/ValueObject/SizeTest.php
@@ -8,6 +8,7 @@
namespace Meritoo\Test\Common\ValueObject;
+use Generator;
use Meritoo\Common\Exception\ValueObject\InvalidSizeDimensionsException;
use Meritoo\Common\Test\Base\BaseTestCase;
use Meritoo\Common\Type\OopVisibilityType;
@@ -18,9 +19,920 @@ use Meritoo\Common\ValueObject\Size;
*
* @author Meritoo
* @copyright Meritoo
+ *
+ * @internal
+ * @covers \Meritoo\Common\ValueObject\Size
*/
class SizeTest extends BaseTestCase
{
+ /**
+ * Provides invalid size (as an array)
+ *
+ * @return Generator
+ */
+ public function provideInvalidSizeAsArray()
+ {
+ yield [
+ [
+ 10,
+ -1,
+ ],
+ ];
+
+ yield [
+ [
+ -1,
+ 10,
+ ],
+ ];
+
+ yield [
+ [
+ -1,
+ -1,
+ ],
+ ];
+ }
+
+ public function provideSizeForConvertingToString()
+ {
+ yield [
+ 'Created using an empty array',
+ Size::fromArray([]),
+ '',
+ ];
+
+ yield [
+ 'Created using an empty string',
+ Size::fromString(''),
+ '',
+ ];
+
+ yield [
+ 'Created using an array with integers',
+ Size::fromArray([
+ 200,
+ 100,
+ ]),
+ '200 x 100',
+ ];
+
+ yield [
+ 'Created using an array with strings',
+ Size::fromArray([
+ '200',
+ '100',
+ ]),
+ '200 x 100',
+ ];
+
+ yield [
+ 'Created using simple string',
+ Size::fromString('200x100', '', 'x'),
+ '200x100',
+ ];
+
+ yield [
+ 'Created using string with too much spaces everywhere',
+ Size::fromString(' 200 x 100 '),
+ '200 x 100',
+ ];
+ }
+
+ public function provideSizeForFromArray()
+ {
+ yield [
+ 'An empty array',
+ [],
+ '',
+ null,
+ ];
+
+ yield [
+ 'One number only',
+ [
+ 200,
+ ],
+ '',
+ null,
+ ];
+
+ yield [
+ 'One number only as string',
+ [
+ '200',
+ ],
+ '',
+ null,
+ ];
+
+ yield [
+ '0 as dimensions',
+ [
+ 0,
+ 0,
+ ],
+ 'px',
+ Size::fromString('0 x 0'),
+ ];
+
+ yield [
+ 'Simple, valid size',
+ [
+ 200,
+ 100,
+ ],
+ 'px',
+ Size::fromString('200 x 100'),
+ ];
+
+ yield [
+ 'Simple, valid size (using strings)',
+ [
+ '200',
+ '100',
+ ],
+ 'mm',
+ Size::fromString('200 x 100', 'mm'),
+ ];
+ }
+
+ public function provideSizeForFromString()
+ {
+ yield [
+ 'One number only',
+ 200,
+ '',
+ ' x ',
+ null,
+ ];
+
+ yield [
+ 'One number only as string',
+ '200',
+ '',
+ ' x ',
+ null,
+ ];
+
+ yield [
+ 'The " " as invalid separator',
+ '200 100',
+ '',
+ ' x ',
+ null,
+ ];
+
+ yield [
+ 'The "|" as separator (invalid separator)',
+ '200 | 100',
+ '',
+ ' x ',
+ null,
+ ];
+
+ yield [
+ 'The "|" as invalid separator and no spaces around separator',
+ '200|100',
+ '',
+ ' x ',
+ null,
+ ];
+
+ yield [
+ 'The "X" as invalid separator',
+ '200 X 100',
+ '',
+ ' x ',
+ null,
+ ];
+
+ yield [
+ 'Simple, valid size',
+ '200 x 100',
+ 'px',
+ ' x ',
+ Size::fromArray([
+ 200,
+ 100,
+ ]),
+ ];
+
+ yield [
+ 'Simple, valid size using custom separator',
+ '200 X 100',
+ 'px',
+ ' X ',
+ Size::fromArray([
+ 200,
+ 100,
+ ])->setSeparator(' X '),
+ ];
+
+ yield [
+ 'Too much spaces at the right of separator',
+ '200 x 100',
+ 'px',
+ ' x ',
+ Size::fromArray([
+ 200,
+ 100,
+ ]),
+ ];
+
+ yield [
+ 'Too much spaces at the left of separator',
+ '200 x 100',
+ 'px',
+ ' x ',
+ Size::fromArray([
+ 200,
+ 100,
+ ]),
+ ];
+
+ yield [
+ 'Too much spaces around separator',
+ '200 x 100',
+ 'px',
+ ' x ',
+ Size::fromArray([
+ 200,
+ 100,
+ ]),
+ ];
+
+ yield [
+ 'Too much spaces before width (1st)',
+ ' 200 x 100',
+ 'px',
+ ' x ',
+ Size::fromArray([
+ 200,
+ 100,
+ ]),
+ ];
+
+ yield [
+ 'Too much spaces before width (2nd) and custom separator',
+ ' 200 X 100',
+ 'px',
+ ' X ',
+ Size::fromArray([
+ 200,
+ 100,
+ ])->setSeparator(' X '),
+ ];
+
+ yield [
+ 'Too much spaces after height (1st)',
+ '200 x 100 ',
+ 'px',
+ ' x ',
+ Size::fromArray([
+ 200,
+ 100,
+ ]),
+ ];
+
+ yield [
+ 'Too much spaces after height (2nd) and custom separator',
+ '200 X 100 ',
+ 'px',
+ ' X ',
+ Size::fromArray([
+ 200,
+ 100,
+ ])->setSeparator(' X '),
+ ];
+
+ yield [
+ 'Too much spaces before width and after height (1st)',
+ ' 200 x 100 ',
+ 'km',
+ ' x ',
+ Size::fromArray(
+ [
+ 200,
+ 100,
+ ],
+ 'km'
+ ),
+ ];
+
+ yield [
+ 'Too much spaces before width and after height (2nd) and custom separator',
+ ' 200 X 100 ',
+ 'px',
+ ' X ',
+ Size::fromArray([
+ 200,
+ 100,
+ ])->setSeparator(' X '),
+ ];
+
+ yield [
+ 'Too much spaces everywhere (1st)',
+ ' 200 x 100 ',
+ 'px',
+ ' x ',
+ Size::fromArray([
+ 200,
+ 100,
+ ]),
+ ];
+
+ yield [
+ 'Too much spaces everywhere (2nd) and custom separator',
+ ' 200 X 100 ',
+ 'px',
+ ' X ',
+ Size::fromArray([
+ 200,
+ 100,
+ ])->setSeparator(' X '),
+ ];
+
+ yield [
+ 'Too much spaces everywhere (3rd)',
+ ' 200 x 100 ',
+ 'px',
+ ' x ',
+ Size::fromArray([
+ 200,
+ 100,
+ ]),
+ ];
+
+ yield [
+ 'Too much spaces everywhere (4th) and custom separator',
+ ' 200 : 100 ',
+ 'px',
+ ' : ',
+ Size::fromArray([
+ 200,
+ 100,
+ ])->setSeparator(' : '),
+ ];
+
+ yield [
+ 'Too much spaces everywhere (5th)',
+ ' 200 x 100 ',
+ 'mm',
+ ' x ',
+ Size::fromArray(
+ [
+ 200,
+ 100,
+ ],
+ 'mm'
+ ),
+ ];
+ }
+
+ public function provideSizeForToArray()
+ {
+ yield [
+ 'Created using an array with integers',
+ Size::fromArray([
+ 200,
+ 100,
+ ]),
+ false,
+ [
+ 200,
+ 100,
+ ],
+ ];
+
+ yield [
+ 'Created using an array with integers (converting with unit)',
+ Size::fromArray([
+ 200,
+ 100,
+ ]),
+ true,
+ [
+ '200 px',
+ '100 px',
+ ],
+ ];
+
+ yield [
+ 'Created using an array with strings',
+ Size::fromArray([
+ '200',
+ '100',
+ ]),
+ false,
+ [
+ 200,
+ 100,
+ ],
+ ];
+
+ yield [
+ 'Created using an array with strings (converting with unit)',
+ Size::fromArray([
+ '200',
+ '100',
+ ]),
+ true,
+ [
+ '200 px',
+ '100 px',
+ ],
+ ];
+
+ yield [
+ 'Created using simple string',
+ Size::fromString('200 x 100'),
+ false,
+ [
+ 200,
+ 100,
+ ],
+ ];
+
+ yield [
+ 'Created using simple string and custom separator',
+ Size::fromString('200 X 100', '', ' X '),
+ false,
+ [
+ 200,
+ 100,
+ ],
+ ];
+
+ yield [
+ 'Created using simple string, custom separator and custom unit (with unit)',
+ Size::fromString('200 : 100', 'mm', ' : '),
+ true,
+ [
+ '200 mm',
+ '100 mm',
+ ],
+ ];
+
+ yield [
+ 'Created using simple string (converting with unit)',
+ Size::fromString('200 x 100'),
+ true,
+ [
+ '200 px',
+ '100 px',
+ ],
+ ];
+
+ yield [
+ 'Created using string with too much spaces everywhere',
+ Size::fromString(' 200 x 100 '),
+ false,
+ [
+ 200,
+ 100,
+ ],
+ ];
+
+ yield [
+ 'Created using string with too much spaces everywhere (converting with unit)',
+ Size::fromString(' 200 x 100 '),
+ true,
+ [
+ '200 px',
+ '100 px',
+ ],
+ ];
+ }
+
+ public function provideSizeForToString()
+ {
+ yield [
+ 'With unknown dimensions',
+ Size::fromArray([
+ null,
+ null,
+ ]),
+ false,
+ '0 x 0',
+ ];
+
+ yield [
+ 'With unknown dimensions (converting with unit)',
+ Size::fromArray([
+ null,
+ null,
+ ]),
+ true,
+ '0 px x 0 px',
+ ];
+
+ yield [
+ 'Created using an array with integers',
+ Size::fromArray([
+ 200,
+ 100,
+ ]),
+ false,
+ '200 x 100',
+ ];
+
+ yield [
+ 'Created using an array with integers (converting with unit)',
+ Size::fromArray([
+ 200,
+ 100,
+ ]),
+ true,
+ '200 px x 100 px',
+ ];
+
+ yield [
+ 'Created using an array with strings',
+ Size::fromArray([
+ '200',
+ '100',
+ ]),
+ false,
+ '200 x 100',
+ ];
+
+ yield [
+ 'Created using an array with strings (converting with unit)',
+ Size::fromArray([
+ '200',
+ '100',
+ ]),
+ true,
+ '200 px x 100 px',
+ ];
+
+ yield [
+ 'Created using simple string',
+ Size::fromString('200 x 100'),
+ false,
+ '200 x 100',
+ ];
+
+ yield [
+ 'Created using simple string',
+ Size::fromString('200 x 100'),
+ false,
+ '200 x 100',
+ ];
+
+ yield [
+ 'Created using simple string and custom separator',
+ Size::fromString('200 X 100', '', ' X '),
+ false,
+ '200 X 100',
+ ];
+
+ yield [
+ 'Created using simple string, custom separator and custom unit (with unit)',
+ Size::fromString('200 : 100', 'mm', ' : '),
+ true,
+ '200 mm : 100 mm',
+ ];
+
+ yield [
+ 'Created using simple string (converting with unit)',
+ Size::fromString('200 x 100'),
+ true,
+ '200 px x 100 px',
+ ];
+
+ yield [
+ 'Created using string with too much spaces everywhere',
+ Size::fromString(' 200 x 100 '),
+ false,
+ '200 x 100',
+ ];
+
+ yield [
+ 'Created using string with too much spaces everywhere (converting with unit)',
+ Size::fromString(' 200 x 100 '),
+ true,
+ '200 px x 100 px',
+ ];
+ }
+
+ public function provideSizeToGetHeight()
+ {
+ yield [
+ 'Created using an array with integers',
+ Size::fromArray([
+ 200,
+ 100,
+ ]),
+ false,
+ 100,
+ ];
+
+ yield [
+ 'Created using an array with integers (with unit)',
+ Size::fromArray([
+ 200,
+ 100,
+ ]),
+ true,
+ '100 px',
+ ];
+
+ yield [
+ 'Created using an array with strings',
+ Size::fromArray([
+ '200',
+ '100',
+ ]),
+ false,
+ 100,
+ ];
+
+ yield [
+ 'Created using an array with strings (with unit)',
+ Size::fromArray([
+ '200',
+ '100',
+ ]),
+ true,
+ '100 px',
+ ];
+
+ yield [
+ 'Created using simple string',
+ Size::fromString('200 x 100'),
+ false,
+ 100,
+ ];
+
+ yield [
+ 'Created using simple string (with unit)',
+ Size::fromString('200 x 100'),
+ true,
+ '100 px',
+ ];
+
+ yield [
+ 'Created using simple string and custom separator',
+ Size::fromString('200 X 100', '', ' X '),
+ false,
+ 100,
+ ];
+
+ yield [
+ 'Created using simple string, custom separator and custom unit (with unit)',
+ Size::fromString('200 : 100', 'mm', ' : '),
+ true,
+ '100 mm',
+ ];
+
+ yield [
+ 'Created using string with too much spaces everywhere',
+ Size::fromString(' 200 x 100 '),
+ false,
+ 100,
+ ];
+
+ yield [
+ 'Created using string with too much spaces everywhere (with unit)',
+ Size::fromString(' 200 x 100 '),
+ true,
+ '100 px',
+ ];
+ }
+
+ public function provideSizeToGetWidth()
+ {
+ yield [
+ 'Created using an array with integers',
+ Size::fromArray([
+ 200,
+ 100,
+ ]),
+ false,
+ 200,
+ ];
+
+ yield [
+ 'Created using an array with integers (with unit)',
+ Size::fromArray([
+ 200,
+ 100,
+ ]),
+ true,
+ '200 px',
+ ];
+
+ yield [
+ 'Created using an array with strings',
+ Size::fromArray([
+ '200',
+ '100',
+ ]),
+ false,
+ 200,
+ ];
+
+ yield [
+ 'Created using an array with strings (with unit)',
+ Size::fromArray([
+ '200',
+ '100',
+ ]),
+ true,
+ '200 px',
+ ];
+
+ yield [
+ 'Created using simple string',
+ Size::fromString('200 x 100'),
+ false,
+ 200,
+ ];
+
+ yield [
+ 'Created using simple string (with unit)',
+ Size::fromString('200 x 100'),
+ true,
+ '200 px',
+ ];
+
+ yield [
+ 'Created using simple string and custom separator',
+ Size::fromString('200 X 100', '', ' X '),
+ false,
+ 200,
+ ];
+
+ yield [
+ 'Created using simple string, custom separator and custom unit (with unit)',
+ Size::fromString('200 : 100', 'mm', ' : '),
+ true,
+ '200 mm',
+ ];
+
+ yield [
+ 'Created using string with too much spaces everywhere',
+ Size::fromString(' 200 x 100 '),
+ false,
+ 200,
+ ];
+
+ yield [
+ 'Created using string with too much spaces everywhere (with unit)',
+ Size::fromString(' 200 x 100 '),
+ true,
+ '200 px',
+ ];
+ }
+
+ public function provideSizeToSetHeight()
+ {
+ yield [
+ 'Null as height',
+ Size::fromArray([
+ 200,
+ 100,
+ ]),
+ null,
+ 0,
+ ];
+
+ yield [
+ 'An empty string',
+ Size::fromArray([
+ 200,
+ 100,
+ ]),
+ '',
+ 0,
+ ];
+
+ yield [
+ 'Negative value',
+ Size::fromArray([
+ 200,
+ 100,
+ ]),
+ -1,
+ -1,
+ ];
+
+ yield [
+ 'Negative value as string',
+ Size::fromArray([
+ 200,
+ 100,
+ ]),
+ '-1',
+ -1,
+ ];
+
+ yield [
+ '0 as height',
+ Size::fromArray([
+ 200,
+ 100,
+ ]),
+ 0,
+ 0,
+ ];
+
+ yield [
+ 'Positive value',
+ Size::fromArray([
+ 200,
+ 100,
+ ]),
+ 300,
+ 300,
+ ];
+
+ yield [
+ 'Positive value as string',
+ Size::fromArray([
+ 200,
+ 100,
+ ]),
+ '300',
+ 300,
+ ];
+ }
+
+ public function provideSizeToSetWidth()
+ {
+ yield [
+ 'Null as width',
+ Size::fromArray([
+ 200,
+ 100,
+ ]),
+ null,
+ 0,
+ ];
+
+ yield [
+ 'An empty string',
+ Size::fromArray([
+ 200,
+ 100,
+ ]),
+ '',
+ 0,
+ ];
+
+ yield [
+ 'Negative value',
+ Size::fromArray([
+ 200,
+ 100,
+ ]),
+ -1,
+ -1,
+ ];
+
+ yield [
+ 'Negative value as string',
+ Size::fromArray([
+ 200,
+ 100,
+ ]),
+ '-1',
+ -1,
+ ];
+
+ yield [
+ '0 as width',
+ Size::fromArray([
+ 200,
+ 100,
+ ]),
+ 0,
+ 0,
+ ];
+
+ yield [
+ 'Positive value',
+ Size::fromArray([
+ 200,
+ 100,
+ ]),
+ 300,
+ 300,
+ ];
+
+ yield [
+ 'Positive value as string',
+ Size::fromArray([
+ 200,
+ 100,
+ ]),
+ '300',
+ 300,
+ ];
+ }
+
public function testConstructor()
{
static::assertConstructorVisibilityAndArguments(
@@ -30,111 +942,6 @@ class SizeTest extends BaseTestCase
);
}
- /**
- * @param string $description Description of test
- * @param Size|null $size Size to convert
- * @param string $expected Expected result
- *
- * @dataProvider provideSizeForConvertingToString
- */
- public function test__toString($description, $size, $expected)
- {
- static::assertEquals($expected, (string)$size, $description);
- }
-
- public function testSetSeparator()
- {
- $size = Size::fromArray([
- 200,
- 100,
- ]);
-
- static::assertInstanceOf(Size::class, $size->setSeparator(' / '));
- static::assertSame('200 / 100', $size->toString());
- }
-
- /**
- * @param string $description Description of test
- * @param Size $size Size to get width
- * @param bool $withUnit If is set to true, width is returned with unit ("px"). Otherwise - without.
- * @param string|int $expected Expected width
- *
- * @dataProvider provideSizeToGetWidth
- */
- public function testGetWidth($description, Size $size, $withUnit, $expected)
- {
- static::assertSame($expected, $size->getWidth($withUnit), $description);
- }
-
- /**
- * @param string $description Description of test
- * @param Size $size Size to set width
- * @param int|string $width The width
- * @param string|int $expected Expected width
- *
- * @dataProvider provideSizeToSetWidth
- */
- public function testSetWidth($description, Size $size, $width, $expected)
- {
- $result = $size->setWidth($width);
-
- static::assertInstanceOf(Size::class, $result, $description);
- static::assertSame($expected, $size->getWidth(), $description);
- }
-
- /**
- * @param string $description Description of test
- * @param Size $size Size to get width
- * @param bool $withUnit If is set to true, width is returned with unit ("px"). Otherwise - without.
- * @param string|int $expected Expected width
- *
- * @dataProvider provideSizeToGetHeight
- */
- public function testGetHeight($description, Size $size, $withUnit, $expected)
- {
- static::assertSame($expected, $size->getHeight($withUnit), $description);
- }
-
- /**
- * @param string $description Description of test
- * @param Size $size Size to set height
- * @param int|string $height The height
- * @param string|int $expected Expected height
- *
- * @dataProvider provideSizeToSetHeight
- */
- public function testSetHeight($description, Size $size, $height, $expected)
- {
- $result = $size->setHeight($height);
-
- static::assertInstanceOf(Size::class, $result, $description);
- static::assertSame($expected, $size->getHeight(), $description);
- }
-
- /**
- * @param string $description Description of test
- * @param Size $size Size to convert
- * @param bool $withUnit If is set to true, width and height are returned with unit ("px"). Otherwise -
- * without.
- * @param string $expected Expected result
- *
- * @dataProvider provideSizeForToString
- */
- public function testToString($description, Size $size, $withUnit, $expected)
- {
- static::assertSame($expected, $size->toString($withUnit), $description);
- }
-
- /**
- * @param array $size Invalid size
- * @dataProvider provideInvalidSizeAsArray
- */
- public function testFromArrayUsingInvalidSizeAsArray(array $size)
- {
- $this->setExpectedException(InvalidSizeDimensionsException::class);
- Size::fromArray($size);
- }
-
/**
* @param string $description Description of test
* @param array $size The size represented as array
@@ -149,17 +956,13 @@ class SizeTest extends BaseTestCase
}
/**
- * @param string $description Description of test
- * @param Size $size Size to convert
- * @param bool $withUnit If is set to true, width and height are returned with unit ("px"). Otherwise -
- * without.
- * @param array $expected Expected result
- *
- * @dataProvider provideSizeForToArray
+ * @param array $size Invalid size
+ * @dataProvider provideInvalidSizeAsArray
*/
- public function testToArray($description, Size $size, $withUnit, array $expected)
+ public function testFromArrayUsingInvalidSizeAsArray(array $size)
{
- static::assertSame($expected, $size->toArray($withUnit), $description);
+ $this->expectException(InvalidSizeDimensionsException::class);
+ Size::fromArray($size);
}
/**
@@ -167,7 +970,7 @@ class SizeTest extends BaseTestCase
* @param string $size The size represented as string (width and height separated by "x")
* @param string $unit Unit used when width or height should be returned with unit
* @param string $separator Separator used to split width and height
- * @param Size|null $expected Expected result
+ * @param null|Size $expected Expected result
*
* @dataProvider provideSizeForFromString
*/
@@ -185,911 +988,112 @@ class SizeTest extends BaseTestCase
static::assertNull(Size::fromString($emptySize));
}
- public function provideSizeForConvertingToString()
+ /**
+ * @param string $description Description of test
+ * @param Size $size Size to get width
+ * @param bool $withUnit If is set to true, width is returned with unit ("px"). Otherwise - without.
+ * @param int|string $expected Expected width
+ *
+ * @dataProvider provideSizeToGetHeight
+ */
+ public function testGetHeight($description, Size $size, $withUnit, $expected)
{
- yield[
- 'Created using an empty array',
- Size::fromArray([]),
- '',
- ];
-
- yield[
- 'Created using an empty string',
- Size::fromString(''),
- '',
- ];
-
- yield[
- 'Created using an array with integers',
- Size::fromArray([
- 200,
- 100,
- ]),
- '200 x 100',
- ];
-
- yield[
- 'Created using an array with strings',
- Size::fromArray([
- '200',
- '100',
- ]),
- '200 x 100',
- ];
-
- yield[
- 'Created using simple string',
- Size::fromString('200x100', '', 'x'),
- '200x100',
- ];
-
- yield[
- 'Created using string with too much spaces everywhere',
- Size::fromString(' 200 x 100 '),
- '200 x 100',
- ];
+ static::assertSame($expected, $size->getHeight($withUnit), $description);
}
/**
- * Provides invalid size (as an array)
+ * @param string $description Description of test
+ * @param Size $size Size to get width
+ * @param bool $withUnit If is set to true, width is returned with unit ("px"). Otherwise - without.
+ * @param int|string $expected Expected width
*
- * @return \Generator
+ * @dataProvider provideSizeToGetWidth
*/
- public function provideInvalidSizeAsArray()
+ public function testGetWidth($description, Size $size, $withUnit, $expected)
{
- yield[
- [
- 10,
- -1,
- ],
- ];
-
- yield[
- [
- -1,
- 10,
- ],
- ];
-
- yield[
- [
- -1,
- -1,
- ],
- ];
+ static::assertSame($expected, $size->getWidth($withUnit), $description);
}
- public function provideSizeToGetWidth()
+ /**
+ * @param string $description Description of test
+ * @param Size $size Size to set height
+ * @param int|string $height The height
+ * @param int|string $expected Expected height
+ *
+ * @dataProvider provideSizeToSetHeight
+ */
+ public function testSetHeight($description, Size $size, $height, $expected)
{
- yield[
- 'Created using an array with integers',
- Size::fromArray([
- 200,
- 100,
- ]),
- false,
- 200,
- ];
+ $result = $size->setHeight($height);
- yield[
- 'Created using an array with integers (with unit)',
- Size::fromArray([
- 200,
- 100,
- ]),
- true,
- '200 px',
- ];
-
- yield[
- 'Created using an array with strings',
- Size::fromArray([
- '200',
- '100',
- ]),
- false,
- 200,
- ];
-
- yield[
- 'Created using an array with strings (with unit)',
- Size::fromArray([
- '200',
- '100',
- ]),
- true,
- '200 px',
- ];
-
- yield[
- 'Created using simple string',
- Size::fromString('200 x 100'),
- false,
- 200,
- ];
-
- yield[
- 'Created using simple string (with unit)',
- Size::fromString('200 x 100'),
- true,
- '200 px',
- ];
-
- yield[
- 'Created using simple string and custom separator',
- Size::fromString('200 X 100', '', ' X '),
- false,
- 200,
- ];
-
- yield[
- 'Created using simple string, custom separator and custom unit (with unit)',
- Size::fromString('200 : 100', 'mm', ' : '),
- true,
- '200 mm',
- ];
-
- yield[
- 'Created using string with too much spaces everywhere',
- Size::fromString(' 200 x 100 '),
- false,
- 200,
- ];
-
- yield[
- 'Created using string with too much spaces everywhere (with unit)',
- Size::fromString(' 200 x 100 '),
- true,
- '200 px',
- ];
+ static::assertInstanceOf(Size::class, $result, $description);
+ static::assertSame($expected, $size->getHeight(), $description);
}
- public function provideSizeToGetHeight()
+ public function testSetSeparator()
{
- yield[
- 'Created using an array with integers',
- Size::fromArray([
- 200,
- 100,
- ]),
- false,
+ $size = Size::fromArray([
+ 200,
100,
- ];
+ ]);
- yield[
- 'Created using an array with integers (with unit)',
- Size::fromArray([
- 200,
- 100,
- ]),
- true,
- '100 px',
- ];
-
- yield[
- 'Created using an array with strings',
- Size::fromArray([
- '200',
- '100',
- ]),
- false,
- 100,
- ];
-
- yield[
- 'Created using an array with strings (with unit)',
- Size::fromArray([
- '200',
- '100',
- ]),
- true,
- '100 px',
- ];
-
- yield[
- 'Created using simple string',
- Size::fromString('200 x 100'),
- false,
- 100,
- ];
-
- yield[
- 'Created using simple string (with unit)',
- Size::fromString('200 x 100'),
- true,
- '100 px',
- ];
-
- yield[
- 'Created using simple string and custom separator',
- Size::fromString('200 X 100', '', ' X '),
- false,
- 100,
- ];
-
- yield[
- 'Created using simple string, custom separator and custom unit (with unit)',
- Size::fromString('200 : 100', 'mm', ' : '),
- true,
- '100 mm',
- ];
-
- yield[
- 'Created using string with too much spaces everywhere',
- Size::fromString(' 200 x 100 '),
- false,
- 100,
- ];
-
- yield[
- 'Created using string with too much spaces everywhere (with unit)',
- Size::fromString(' 200 x 100 '),
- true,
- '100 px',
- ];
+ static::assertInstanceOf(Size::class, $size->setSeparator(' / '));
+ static::assertSame('200 / 100', $size->toString());
}
- public function provideSizeToSetWidth()
+ /**
+ * @param string $description Description of test
+ * @param Size $size Size to set width
+ * @param int|string $width The width
+ * @param int|string $expected Expected width
+ *
+ * @dataProvider provideSizeToSetWidth
+ */
+ public function testSetWidth($description, Size $size, $width, $expected)
{
- yield[
- 'Null as width',
- Size::fromArray([
- 200,
- 100,
- ]),
- null,
- 0,
- ];
+ $result = $size->setWidth($width);
- yield[
- 'An empty string',
- Size::fromArray([
- 200,
- 100,
- ]),
- '',
- 0,
- ];
-
- yield[
- 'Negative value',
- Size::fromArray([
- 200,
- 100,
- ]),
- -1,
- -1,
- ];
-
- yield[
- 'Negative value as string',
- Size::fromArray([
- 200,
- 100,
- ]),
- '-1',
- -1,
- ];
-
- yield[
- '0 as width',
- Size::fromArray([
- 200,
- 100,
- ]),
- 0,
- 0,
- ];
-
- yield[
- 'Positive value',
- Size::fromArray([
- 200,
- 100,
- ]),
- 300,
- 300,
- ];
-
- yield[
- 'Positive value as string',
- Size::fromArray([
- 200,
- 100,
- ]),
- '300',
- 300,
- ];
+ static::assertInstanceOf(Size::class, $result, $description);
+ static::assertSame($expected, $size->getWidth(), $description);
}
- public function provideSizeToSetHeight()
+ /**
+ * @param string $description Description of test
+ * @param Size $size Size to convert
+ * @param bool $withUnit If is set to true, width and height are returned with unit ("px"). Otherwise -
+ * without.
+ * @param array $expected Expected result
+ *
+ * @dataProvider provideSizeForToArray
+ */
+ public function testToArray($description, Size $size, $withUnit, array $expected)
{
- yield[
- 'Null as height',
- Size::fromArray([
- 200,
- 100,
- ]),
- null,
- 0,
- ];
-
- yield[
- 'An empty string',
- Size::fromArray([
- 200,
- 100,
- ]),
- '',
- 0,
- ];
-
- yield[
- 'Negative value',
- Size::fromArray([
- 200,
- 100,
- ]),
- -1,
- -1,
- ];
-
- yield[
- 'Negative value as string',
- Size::fromArray([
- 200,
- 100,
- ]),
- '-1',
- -1,
- ];
-
- yield[
- '0 as height',
- Size::fromArray([
- 200,
- 100,
- ]),
- 0,
- 0,
- ];
-
- yield[
- 'Positive value',
- Size::fromArray([
- 200,
- 100,
- ]),
- 300,
- 300,
- ];
-
- yield[
- 'Positive value as string',
- Size::fromArray([
- 200,
- 100,
- ]),
- '300',
- 300,
- ];
+ static::assertSame($expected, $size->toArray($withUnit), $description);
}
- public function provideSizeForToString()
+ /**
+ * @param string $description Description of test
+ * @param Size $size Size to convert
+ * @param bool $withUnit If is set to true, width and height are returned with unit ("px"). Otherwise -
+ * without.
+ * @param string $expected Expected result
+ *
+ * @dataProvider provideSizeForToString
+ */
+ public function testToString($description, Size $size, $withUnit, $expected)
{
- yield[
- 'With unknown dimensions',
- Size::fromArray([
- null,
- null,
- ]),
- false,
- '0 x 0',
- ];
-
- yield[
- 'With unknown dimensions (converting with unit)',
- Size::fromArray([
- null,
- null,
- ]),
- true,
- '0 px x 0 px',
- ];
-
- yield[
- 'Created using an array with integers',
- Size::fromArray([
- 200,
- 100,
- ]),
- false,
- '200 x 100',
- ];
-
- yield[
- 'Created using an array with integers (converting with unit)',
- Size::fromArray([
- 200,
- 100,
- ]),
- true,
- '200 px x 100 px',
- ];
-
- yield[
- 'Created using an array with strings',
- Size::fromArray([
- '200',
- '100',
- ]),
- false,
- '200 x 100',
- ];
-
- yield[
- 'Created using an array with strings (converting with unit)',
- Size::fromArray([
- '200',
- '100',
- ]),
- true,
- '200 px x 100 px',
- ];
-
- yield[
- 'Created using simple string',
- Size::fromString('200 x 100'),
- false,
- '200 x 100',
- ];
-
- yield[
- 'Created using simple string',
- Size::fromString('200 x 100'),
- false,
- '200 x 100',
- ];
-
- yield[
- 'Created using simple string and custom separator',
- Size::fromString('200 X 100', '', ' X '),
- false,
- '200 X 100',
- ];
-
- yield[
- 'Created using simple string, custom separator and custom unit (with unit)',
- Size::fromString('200 : 100', 'mm', ' : '),
- true,
- '200 mm : 100 mm',
- ];
-
- yield[
- 'Created using simple string (converting with unit)',
- Size::fromString('200 x 100'),
- true,
- '200 px x 100 px',
- ];
-
- yield[
- 'Created using string with too much spaces everywhere',
- Size::fromString(' 200 x 100 '),
- false,
- '200 x 100',
- ];
-
- yield[
- 'Created using string with too much spaces everywhere (converting with unit)',
- Size::fromString(' 200 x 100 '),
- true,
- '200 px x 100 px',
- ];
+ static::assertSame($expected, $size->toString($withUnit), $description);
}
- public function provideSizeForToArray()
+ /**
+ * @param string $description Description of test
+ * @param null|Size $size Size to convert
+ * @param string $expected Expected result
+ *
+ * @dataProvider provideSizeForConvertingToString
+ */
+ public function testToStringConverting($description, $size, $expected)
{
- yield[
- 'Created using an array with integers',
- Size::fromArray([
- 200,
- 100,
- ]),
- false,
- [
- 200,
- 100,
- ],
- ];
-
- yield[
- 'Created using an array with integers (converting with unit)',
- Size::fromArray([
- 200,
- 100,
- ]),
- true,
- [
- '200 px',
- '100 px',
- ],
- ];
-
- yield[
- 'Created using an array with strings',
- Size::fromArray([
- '200',
- '100',
- ]),
- false,
- [
- 200,
- 100,
- ],
- ];
-
- yield[
- 'Created using an array with strings (converting with unit)',
- Size::fromArray([
- '200',
- '100',
- ]),
- true,
- [
- '200 px',
- '100 px',
- ],
- ];
-
- yield[
- 'Created using simple string',
- Size::fromString('200 x 100'),
- false,
- [
- 200,
- 100,
- ],
- ];
-
- yield[
- 'Created using simple string and custom separator',
- Size::fromString('200 X 100', '', ' X '),
- false,
- [
- 200,
- 100,
- ],
- ];
-
- yield[
- 'Created using simple string, custom separator and custom unit (with unit)',
- Size::fromString('200 : 100', 'mm', ' : '),
- true,
- [
- '200 mm',
- '100 mm',
- ],
- ];
-
- yield[
- 'Created using simple string (converting with unit)',
- Size::fromString('200 x 100'),
- true,
- [
- '200 px',
- '100 px',
- ],
- ];
-
- yield[
- 'Created using string with too much spaces everywhere',
- Size::fromString(' 200 x 100 '),
- false,
- [
- 200,
- 100,
- ],
- ];
-
- yield[
- 'Created using string with too much spaces everywhere (converting with unit)',
- Size::fromString(' 200 x 100 '),
- true,
- [
- '200 px',
- '100 px',
- ],
- ];
- }
-
- public function provideSizeForFromString()
- {
- yield[
- 'One number only',
- 200,
- '',
- ' x ',
- null,
- ];
-
- yield[
- 'One number only as string',
- '200',
- '',
- ' x ',
- null,
- ];
-
- yield[
- 'The " " as invalid separator',
- '200 100',
- '',
- ' x ',
- null,
- ];
-
- yield[
- 'The "|" as separator (invalid separator)',
- '200 | 100',
- '',
- ' x ',
- null,
- ];
-
- yield[
- 'The "|" as invalid separator and no spaces around separator',
- '200|100',
- '',
- ' x ',
- null,
- ];
-
- yield[
- 'The "X" as invalid separator',
- '200 X 100',
- '',
- ' x ',
- null,
- ];
-
- yield[
- 'Simple, valid size',
- '200 x 100',
- 'px',
- ' x ',
- Size::fromArray([
- 200,
- 100,
- ]),
- ];
-
- yield[
- 'Simple, valid size using custom separator',
- '200 X 100',
- 'px',
- ' X ',
- Size::fromArray([
- 200,
- 100,
- ])->setSeparator(' X '),
- ];
-
- yield[
- 'Too much spaces at the right of separator',
- '200 x 100',
- 'px',
- ' x ',
- Size::fromArray([
- 200,
- 100,
- ]),
- ];
-
- yield[
- 'Too much spaces at the left of separator',
- '200 x 100',
- 'px',
- ' x ',
- Size::fromArray([
- 200,
- 100,
- ]),
- ];
-
- yield[
- 'Too much spaces around separator',
- '200 x 100',
- 'px',
- ' x ',
- Size::fromArray([
- 200,
- 100,
- ]),
- ];
-
- yield[
- 'Too much spaces before width (1st)',
- ' 200 x 100',
- 'px',
- ' x ',
- Size::fromArray([
- 200,
- 100,
- ]),
- ];
-
- yield[
- 'Too much spaces before width (2nd) and custom separator',
- ' 200 X 100',
- 'px',
- ' X ',
- Size::fromArray([
- 200,
- 100,
- ])->setSeparator(' X '),
- ];
-
- yield[
- 'Too much spaces after height (1st)',
- '200 x 100 ',
- 'px',
- ' x ',
- Size::fromArray([
- 200,
- 100,
- ]),
- ];
-
- yield[
- 'Too much spaces after height (2nd) and custom separator',
- '200 X 100 ',
- 'px',
- ' X ',
- Size::fromArray([
- 200,
- 100,
- ])->setSeparator(' X '),
- ];
-
- yield[
- 'Too much spaces before width and after height (1st)',
- ' 200 x 100 ',
- 'km',
- ' x ',
- Size::fromArray(
- [
- 200,
- 100,
- ],
- 'km'
- ),
- ];
-
- yield[
- 'Too much spaces before width and after height (2nd) and custom separator',
- ' 200 X 100 ',
- 'px',
- ' X ',
- Size::fromArray([
- 200,
- 100,
- ])->setSeparator(' X '),
- ];
-
- yield[
- 'Too much spaces everywhere (1st)',
- ' 200 x 100 ',
- 'px',
- ' x ',
- Size::fromArray([
- 200,
- 100,
- ]),
- ];
-
- yield[
- 'Too much spaces everywhere (2nd) and custom separator',
- ' 200 X 100 ',
- 'px',
- ' X ',
- Size::fromArray([
- 200,
- 100,
- ])->setSeparator(' X '),
- ];
-
- yield[
- 'Too much spaces everywhere (3rd)',
- ' 200 x 100 ',
- 'px',
- ' x ',
- Size::fromArray([
- 200,
- 100,
- ]),
- ];
-
- yield[
- 'Too much spaces everywhere (4th) and custom separator',
- ' 200 : 100 ',
- 'px',
- ' : ',
- Size::fromArray([
- 200,
- 100,
- ])->setSeparator(' : '),
- ];
-
- yield[
- 'Too much spaces everywhere (5th)',
- ' 200 x 100 ',
- 'mm',
- ' x ',
- Size::fromArray(
- [
- 200,
- 100,
- ],
- 'mm'
- ),
- ];
- }
-
- public function provideSizeForFromArray()
- {
- yield[
- 'An empty array',
- [],
- '',
- null,
- ];
-
- yield[
- 'One number only',
- [
- 200,
- ],
- '',
- null,
- ];
-
- yield[
- 'One number only as string',
- [
- '200',
- ],
- '',
- null,
- ];
-
- yield[
- '0 as dimensions',
- [
- 0,
- 0,
- ],
- 'px',
- Size::fromString('0 x 0'),
- ];
-
- yield[
- 'Simple, valid size',
- [
- 200,
- 100,
- ],
- 'px',
- Size::fromString('200 x 100'),
- ];
-
- yield[
- 'Simple, valid size (using strings)',
- [
- '200',
- '100',
- ],
- 'mm',
- Size::fromString('200 x 100', 'mm'),
- ];
+ static::assertEquals($expected, (string) $size, $description);
}
}
diff --git a/tests/ValueObject/TemplateTest.php b/tests/ValueObject/TemplateTest.php
new file mode 100644
index 0000000..8dc8f7c
--- /dev/null
+++ b/tests/ValueObject/TemplateTest.php
@@ -0,0 +1,272 @@
+
+ * @copyright Meritoo
+ *
+ * @internal
+ * @covers \Meritoo\Common\ValueObject\Template
+ */
+class TemplateTest extends BaseTestCase
+{
+ public function provideInvalidContent(): ?Generator
+ {
+ $template = 'Content of template \'%s\' is invalid. Did you use string with 1 placeholder at least?';
+
+ yield [
+ 'An empty string' => '',
+ sprintf($template, ''),
+ ];
+
+ yield [
+ 'Without placeholders' => 'test',
+ sprintf($template, 'test'),
+ ];
+
+ yield [
+ 'With starting tag only (invalid placeholder)' => 'This is %test',
+ sprintf($template, 'This is %test'),
+ ];
+
+ yield [
+ 'With ending tag only (invalid placeholder)' => 'This is test%',
+ sprintf($template, 'This is test%'),
+ ];
+ }
+
+ public function provideTemplateToFill(): ?Generator
+ {
+ yield [
+ 'Template with 1 placeholder',
+ new Template('%test%'),
+ [
+ 'test' => 123,
+ ],
+ '123',
+ ];
+
+ yield [
+ 'Template with 1 placeholder, but more values',
+ new Template('%test%'),
+ [
+ 'test' => 123,
+ 'anotherTest' => 456,
+ ],
+ '123',
+ ];
+
+ yield [
+ 'Template with 2 placeholders',
+ new Template('My name is %name% and I am %profession%'),
+ [
+ 'name' => 'Jane',
+ 'profession' => 'photographer',
+ ],
+ 'My name is Jane and I am photographer',
+ ];
+
+ yield [
+ 'Template with 2 placeholders, but more values',
+ new Template('My name is %name% and I am %profession%'),
+ [
+ 'name' => 'Jane',
+ 'test-test' => 123,
+ 'profession' => 'photographer',
+ 'anotherTest' => 456,
+ ],
+ 'My name is Jane and I am photographer',
+ ];
+
+ yield [
+ 'Template with 2 placeholders that contains space',
+ new Template('My name is %first name% %last name% and I live in %current location%'),
+ [
+ 'first name' => 'Jane',
+ 'last name' => 'Brown',
+ 'current location' => 'NY, USA',
+ ],
+ 'My name is Jane Brown and I live in NY, USA',
+ ];
+
+ yield [
+ 'Template with 2 placeholders that contains space, but more values',
+ new Template('My name is %first name% %last name% and I live in %current location%'),
+ [
+ 'first name' => 'Jane',
+ 'profession' => 'photographer',
+ 'last name' => 'Brown',
+ 'test-test' => 123,
+ 'anotherTest' => 456,
+ 'current location' => 'NY, USA',
+ ],
+ 'My name is Jane Brown and I live in NY, USA',
+ ];
+ }
+
+ public function provideTemplateToFillUsingIncorrectValues(): ?Generator
+ {
+ $template = 'Cannot fill template \'%s\', because of missing values for placeholder(s): %s. Did you provide all'
+ .' required values?';
+
+ yield [
+ new Template('%test%'),
+ [
+ 'something' => 123,
+ ],
+ sprintf(
+ $template,
+ '%test%',
+ 'test'
+ ),
+ ];
+
+ yield [
+ new Template('%test%'),
+ [],
+ sprintf(
+ $template,
+ '%test%',
+ 'test'
+ ),
+ ];
+
+ yield [
+ new Template('%test1% - %test2%'),
+ [
+ 'test1' => 123,
+ ],
+ sprintf(
+ $template,
+ '%test1% - %test2%',
+ 'test2'
+ ),
+ ];
+
+ yield [
+ new Template('%test1% - %test2%'),
+ [
+ 'test1' => 123,
+ 'test3' => 456,
+ ],
+ sprintf(
+ $template,
+ '%test1% - %test2%',
+ 'test2'
+ ),
+ ];
+
+ yield [
+ new Template('%test1% / %test2% / %test3%'),
+ [
+ 'test1' => 123,
+ ],
+ sprintf(
+ $template,
+ '%test1% / %test2% / %test3%',
+ 'test2, test3'
+ ),
+ ];
+ }
+
+ public function provideValidContent(): ?Generator
+ {
+ yield [
+ 'Template with 1 placeholder',
+ '%test%',
+ ];
+
+ yield [
+ 'Template with 2 placeholders',
+ 'My name is %name% and I am %profession%',
+ ];
+
+ yield [
+ 'Template with 2 placeholders that contains space',
+ 'My name is %first name% %last name% and I live in %current location%',
+ ];
+ }
+
+ public function testConstructor(): void
+ {
+ static::assertConstructorVisibilityAndArguments(
+ Template::class,
+ OopVisibilityType::IS_PUBLIC,
+ 1,
+ 1
+ );
+ }
+
+ /**
+ * @param string $description Description of test
+ * @param Template $template Template to fill
+ * @param array $values Pairs of key-value where: key - name of placeholder, value - value of the
+ * placeholder
+ * @param string $expected Expected result
+ *
+ * @dataProvider provideTemplateToFill
+ */
+ public function testFill(string $description, Template $template, array $values, string $expected): void
+ {
+ static::assertSame($expected, $template->fill($values), $description);
+ }
+
+ /**
+ * @param Template $template Template to fill
+ * @param array $values Pairs of key-value where: key - name of placeholder, value - value of the
+ * placeholder
+ * @param string $exceptionMessage Expected message of exception
+ *
+ * @dataProvider provideTemplateToFillUsingIncorrectValues
+ */
+ public function testFillUsingIncorrectValues(Template $template, array $values, string $exceptionMessage): void
+ {
+ $this->expectException(MissingPlaceholdersInValuesException::class);
+ $this->expectExceptionMessage($exceptionMessage);
+
+ $template->fill($values);
+ }
+
+ /**
+ * @param string $content Raw string with placeholders (content of the template)
+ * @param string $exceptionMessage Expected message of exception
+ *
+ * @dataProvider provideInvalidContent
+ */
+ public function testIsValidUsingInvalidContent(string $content, string $exceptionMessage): void
+ {
+ $this->expectException(InvalidContentException::class);
+ $this->expectExceptionMessage($exceptionMessage);
+
+ new Template($content);
+ }
+
+ /**
+ * @param string $description Description of test
+ * @param string $content Raw string with placeholders (content of the template)
+ *
+ * @dataProvider provideValidContent
+ */
+ public function testIsValidUsingValidContent(string $description, string $content): void
+ {
+ $template = new Template($content);
+ static::assertSame($content, Reflection::getPropertyValue($template, 'content', true), $description);
+ }
+}
diff --git a/tests/ValueObject/VersionTest.php b/tests/ValueObject/VersionTest.php
index fb0e783..210374f 100644
--- a/tests/ValueObject/VersionTest.php
+++ b/tests/ValueObject/VersionTest.php
@@ -19,14 +19,155 @@ use Meritoo\Common\ValueObject\Version;
*
* @author Meritoo
* @copyright Meritoo
+ *
+ * @internal
+ * @covers \Meritoo\Common\ValueObject\Version
*/
class VersionTest extends BaseTestCase
{
+ /**
+ * Provide version as array and expected instance of version
+ *
+ * @return Generator
+ */
+ public function provideAsArray()
+ {
+ yield [
+ [],
+ null,
+ ];
+
+ yield [
+ [
+ 1,
+ 0,
+ ],
+ null,
+ ];
+
+ yield [
+ [
+ 10,
+ ],
+ null,
+ ];
+
+ yield [
+ [
+ 0,
+ 0,
+ 0,
+ ],
+ new Version(0, 0, 0),
+ ];
+
+ yield [
+ [
+ 1,
+ 0,
+ 2,
+ ],
+ new Version(1, 0, 2),
+ ];
+
+ yield [
+ [
+ 10,
+ 5,
+ 41,
+ ],
+ new Version(10, 5, 41),
+ ];
+ }
+
+ /**
+ * Provide version as string and expected instance of version
+ *
+ * @return Generator
+ */
+ public function provideAsString()
+ {
+ yield [
+ '',
+ null,
+ ];
+
+ yield [
+ '1.0',
+ null,
+ ];
+
+ yield [
+ '10',
+ null,
+ ];
+
+ yield [
+ '0.0.0',
+ new Version(0, 0, 0),
+ ];
+
+ yield [
+ '1.0.2',
+ new Version(1, 0, 2),
+ ];
+
+ yield [
+ '10.5.41',
+ new Version(10, 5, 41),
+ ];
+ }
+
+ /**
+ * Provide instance of version and expected version converted to string
+ *
+ * @return Generator
+ */
+ public function provideConvertedToString()
+ {
+ yield [
+ new Version(0, 0, 0),
+ '0.0.0',
+ ];
+
+ yield [
+ new Version(1, 0, 2),
+ '1.0.2',
+ ];
+
+ yield [
+ new Version(10, 5, 41),
+ '10.5.41',
+ ];
+ }
+
public function testConstructor()
{
static::assertConstructorVisibilityAndArguments(Version::class, OopVisibilityType::IS_PUBLIC, 3, 3);
}
+ /**
+ * @param array $version The version
+ * @param Version $expected (optional) Expected version
+ *
+ * @dataProvider provideAsArray
+ */
+ public function testFromArray(array $version, Version $expected = null)
+ {
+ static::assertEquals($expected, Version::fromArray($version));
+ }
+
+ /**
+ * @param string $version The version
+ * @param Version $expected (optional) Expected version
+ *
+ * @dataProvider provideAsString
+ */
+ public function testFromString($version, Version $expected = null)
+ {
+ static::assertEquals($expected, Version::fromString($version));
+ }
+
public function testNewInstance()
{
$version = new Version(1, 0, 2);
@@ -45,144 +186,6 @@ class VersionTest extends BaseTestCase
*/
public function testToString(Version $version, $expected)
{
- static::assertSame($expected, (string)$version);
- }
-
- /**
- * @param string $version The version
- * @param Version $expected (optional) Expected version
- *
- * @dataProvider provideAsString
- */
- public function testFromString($version, Version $expected = null)
- {
- static::assertEquals($expected, Version::fromString($version));
- }
-
- /**
- * @param array $version The version
- * @param Version $expected (optional) Expected version
- *
- * @dataProvider provideAsArray
- */
- public function testFromArray(array $version, Version $expected = null)
- {
- static::assertEquals($expected, Version::fromArray($version));
- }
-
- /**
- * Provide instance of version and expected version converted to string
- *
- * @return Generator
- */
- public function provideConvertedToString()
- {
- yield[
- new Version(0, 0, 0),
- '0.0.0',
- ];
-
- yield[
- new Version(1, 0, 2),
- '1.0.2',
- ];
-
- yield[
- new Version(10, 5, 41),
- '10.5.41',
- ];
- }
-
- /**
- * Provide version as string and expected instance of version
- *
- * @return Generator
- */
- public function provideAsString()
- {
- yield[
- '',
- null,
- ];
-
- yield[
- '1.0',
- null,
- ];
-
- yield[
- '10',
- null,
- ];
-
- yield[
- '0.0.0',
- new Version(0, 0, 0),
- ];
-
- yield[
- '1.0.2',
- new Version(1, 0, 2),
- ];
-
- yield[
- '10.5.41',
- new Version(10, 5, 41),
- ];
- }
-
- /**
- * Provide version as array and expected instance of version
- *
- * @return Generator
- */
- public function provideAsArray()
- {
- yield[
- [],
- null,
- ];
-
- yield[
- [
- 1,
- 0,
- ],
- null,
- ];
-
- yield[
- [
- 10,
- ],
- null,
- ];
-
- yield[
- [
- 0,
- 0,
- 0,
- ],
- new Version(0, 0, 0),
- ];
-
- yield[
- [
- 1,
- 0,
- 2,
- ],
- new Version(1, 0, 2),
- ];
-
- yield[
- [
- 10,
- 5,
- 41,
- ],
- new Version(10, 5, 41),
- ];
+ static::assertSame($expected, (string) $version);
}
}