120 Commits

Author SHA1 Message Date
Meritoo
0bd1e1e158 Merge branch 'develop' 2018-07-29 16:01:31 +02:00
Meritoo
535ae65e5e Utilities > Reflection > setPropertyValue() method > sets value of given property 2018-07-29 16:00:13 +02:00
Meritoo
60d7b03cd7 Utilities > Reflection > refactoring 2018-07-29 15:34:33 +02:00
Meritoo
c20fa5941f Docker > improve performance 2018-07-28 21:01:07 +02:00
Meritoo
a448d592d2 Documentation > Value Objects 2018-07-02 21:24:20 +02:00
Meritoo
e53273fb32 Merge branch 'develop' 2018-07-02 20:20:52 +02:00
Meritoo
cc30ad8d9e Move version of this package to "VERSION" file (from "composer.json" file) 2018-07-02 20:19:29 +02:00
Meritoo
9f08a2aaaf ValueObject > class Version > represents version of software 2018-07-02 20:07:33 +02:00
Meritoo
b49605a26c TravisCI - fix "No output has been received in the last 10m0s" bug (build times out because no output was received) 2018-07-02 10:40:33 +02:00
Meritoo
8441c82356 TravisCI > run using PHP 7.2 too 2018-07-02 09:53:16 +02:00
Meritoo
55dde2e898 Merge branch 'develop' 2018-07-02 09:34:53 +02:00
Meritoo
a32e0c4cca Documentation > Exceptions 2018-07-02 09:31:07 +02:00
Meritoo
834b24f348 Exceptions > create instance of exception using static "create()" method (instead of constructor) 2018-07-02 08:54:24 +02:00
Meritoo
9342f0e87e Docker > rename "php-cli" service to "php" 2018-07-02 08:47:56 +02:00
Meritoo
72fd87e165 Composer > support/require PHP 5.6+ (instead of 5.5.9+) 2018-07-02 08:12:26 +02:00
Meritoo
64499b49d3 Update @author and @copyright in classes' descriptions 2018-07-01 21:07:47 +02:00
Meritoo
848adef015 Arrays > minor refactoring 2018-07-01 17:45:03 +02:00
Meritoo
1431fd9935 Composer > require ext-pcre 2018-07-01 17:37:51 +02:00
Meritoo
3bb7a182c2 Merge branch 'develop' 2018-06-22 08:26:10 +02:00
Meritoo
5c9436e4e2 Collection > add() method > treat empty string as not provided index (same as null) 2018-06-22 08:10:06 +02:00
Meritoo
1a649d35e1 Merge branch 'develop' 2018-06-18 09:37:27 +02:00
Meritoo
107480d01b StyleCI > disable & remove 2018-06-16 14:43:16 +02:00
Meritoo
f4c12661b4 StyleCI configuration > fix bug "The provided fixer 'concat_with_spaces' cannot be enabled at the same time as 'concat_without_spaces'" 2018-06-16 14:36:33 +02:00
Meritoo
fc7df571e2 StyleCI configuration > fix bug "The provided fixer 'binary_operator_spaces' cannot be enabled again because it was already enabled" 2018-06-16 14:34:00 +02:00
Meritoo
0f37edfc9b Coding standard > fix automatically 2018-06-16 14:31:04 +02:00
Meritoo
ae3e82e233 Documentation > Docker > add paragraph for PHP Coding Standards Fixer 2018-06-16 14:21:01 +02:00
Meritoo
c99a099c31 StyleCI & PHP Coding Standards Fixer > update configuration 2018-06-16 14:15:35 +02:00
Meritoo
c443ef22d7 .gitignore > PHP Coding Standards Fixer > ignore custom settings 2018-06-16 14:12:07 +02:00
Meritoo
be8b4a3498 Arrays > remove unnecessary code 2018-06-16 14:10:57 +02:00
Meritoo
b1ddc6d561 .env.dist > enter default values (for easier .env creation) 2018-06-16 10:04:14 +02:00
Meritoo
ffe34eb9cf StyleCI > update configuration 2018-06-15 23:06:47 +02:00
Meritoo
155c091a3e StyleCI > update configuration 2018-06-15 23:04:06 +02:00
Meritoo
0a3955026b Revert "StyleCI > update configuration"
This reverts commit f9fa5f5
2018-06-15 23:00:53 +02:00
Meritoo
f9fa5f5915 StyleCI > update configuration 2018-06-15 23:00:29 +02:00
Meritoo
43945a8721 Composer > do not require symfony/http-foundation package
Miscellaneous > remove getCurlResponseWithHeaders() method
2018-06-15 22:54:00 +02:00
Meritoo
e9da0cf351 Reorganize documentation & update Readme 2018-06-14 22:28:53 +02:00
Meritoo
4c534394d9 Docker > Dockerfile > add "WORKDIR" (instead of "working_dir" in docker-compose.yml) 2018-06-14 21:35:50 +02:00
Meritoo
3726a26e47 Reorganize documentation & update Readme 2018-06-14 21:35:14 +02:00
Meritoo
fb24bc2ff1 Docker > use project-related binaries globally 2018-06-14 11:50:45 +02:00
Meritoo
57a78d1299 Reorganize documentation & update Readme 2018-06-14 11:32:54 +02:00
Meritoo
696cff023c Add changelog 2018-06-14 11:32:25 +02:00
Meritoo
9197682cd2 Readme > update paragraphs with Composer, Docker & use 1st level headers 2018-06-14 09:55:44 +02:00
Meritoo
49638ff1c3 .gitignore > update sections' separators 2018-06-13 22:21:28 +02:00
Meritoo
abf0ebf7ec Tests > increase code coverage 2018-06-09 14:25:20 +02:00
Meritoo
2e60176d95 Docker > Dockerfile > make bash terminal wider (increase columns count) 2018-06-07 20:56:48 +02:00
Meritoo
c351ce887a Tests > implement PHPUnit (instead of Codeception) 2018-06-07 20:51:55 +02:00
Meritoo
8a6262a8c3 Phing > tests > update name of property with path (tests_framework.path > tests.framework.path) & ignore /build directory 2018-05-28 21:22:00 +02:00
Meritoo
3c83a8800e Start names of special directories without dot 2018-05-28 21:10:20 +02:00
Meritoo
233473d915 Tests > implement Codeception (instead of PHPUnit) 2018-05-28 17:53:25 +02:00
Meritoo
7382bce842 Phing > tests > do not verify if the "tests" directory exists 2018-05-28 17:05:12 +02:00
Meritoo
c5b42017d2 Phing > tests > do not create database (for code coverage) 2018-05-28 17:03:19 +02:00
Meritoo
bc54f734e2 Phing > update properties.dist > remove unnecessary properties and disabled code 2018-05-28 16:56:59 +02:00
Meritoo
0eb5343df0 Docker > name of containers > use custom suffix
Docker > the "composer" service
2018-05-28 15:03:52 +02:00
Meritoo
52e74c8b48 Tests > increase code coverage 2018-05-28 15:03:11 +02:00
Meritoo
96bdb6eb60 Improve coding standard 2018-05-06 17:21:55 +02:00
Meritoo
5be449a83d Docker > Dockerfile > fix bug when error messages are displayed in french instead of english language (example: "chmod(): Aucun fichier ou dossier de ce type") 2018-05-06 14:40:17 +02:00
Meritoo
132a0a00e7 Docker > Dockerfile > fix bug "pecl/xdebug requires PHP (version >= 7.0.0), installed version is 5.5.38" 2018-05-04 12:53:45 +02:00
Meritoo
6fd18111b4 TravisCI - fix "No output has been received in the last 10m0s" bug (build times out because no output was received) 2018-04-04 21:54:45 +02:00
Meritoo
26c63ecb5c TravisCI > composer > install hirak/prestissimo package globally 2018-04-04 21:40:44 +02:00
Meritoo
bedb6333b9 TravisCI > "composer install" command > increase verbosity to maximum 2018-04-04 21:21:51 +02:00
Meritoo
ec2b5742ec Revert "TravisCI - fix "No output has been received in the last 10m0s" bug (build times out because no output was received)"
This reverts commit ec2f3c6
2018-04-04 21:16:36 +02:00
Meritoo
ec2f3c6ead TravisCI - fix "No output has been received in the last 10m0s" bug (build times out because no output was received) 2018-04-04 08:57:08 +02:00
Meritoo
834c12f280 TravisCI - install locales before running tests - remove unnecessary command 2018-04-03 22:57:41 +02:00
Meritoo
122ff41dad TravisCI - install locales before running tests 2018-04-03 19:13:38 +02:00
Meritoo
180a8b8b5d TravisCI - install locales before running tests 2018-04-03 17:10:40 +02:00
Meritoo
499c603d54 TravisCI - install locales before running tests 2018-04-03 17:04:43 +02:00
Meritoo
1cbc87222f TravisCI - install locales before running tests 2018-04-03 16:58:54 +02:00
Meritoo
129b75ea93 Revert "TravisCI - install locales before running tests"
This reverts commit aae7609
2018-04-03 16:58:32 +02:00
Meritoo
aae7609c8c TravisCI - install locales before running tests 2018-04-03 16:55:12 +02:00
Meritoo
5578b051a7 Update PHPDoc and comments 2018-04-03 08:26:51 +02:00
Meritoo
f111174ed2 Tests - increase code coverage 2018-04-03 08:22:10 +02:00
Meritoo
ddbff1b557 Update PHPDoc and comments 2018-04-02 22:46:52 +02:00
Meritoo
8d1df9ced8 Tests - increase code coverage 2018-04-02 22:44:30 +02:00
Meritoo
b7d0b61094 tests > PHPUnit configuration > update 2018-03-30 21:15:42 +02:00
Meritoo
ad64d2e02a Docker - Dockerfile - minor update 2018-01-27 13:10:14 +01:00
Meritoo
470b8244ec Utilities - Locale - getLocale() method - returns locale for given category 2018-01-27 13:05:20 +01:00
Meritoo
af38c35a1b Utilities - Locale - setLocale() method - return result of setting new locale (instead of "true")
Tests - Locale - fix incorrectly prepared tests
2018-01-27 13:04:04 +01:00
Meritoo
1e3e1d454e Docker - Dockerfile - install "locales" package & generate popular locales
Required to run tests related to setlocale() function (and Meritoo\Common\Utilities\Locale class) properly
2018-01-27 12:59:55 +01:00
Meritoo
57b411b59f Tests - increase code coverage 2018-01-17 21:37:07 +01:00
Meritoo
8a4860088f Phing - Composer-related task - validate Composer 2018-01-14 21:19:06 +01:00
Meritoo
e9b8fb8852 Regex - isBinaryValue() method - returns information if given value is a binary value 2018-01-10 17:35:42 +01:00
Meritoo
780d4df17e Tests - increase code coverage 2017-12-26 14:37:17 +01:00
Meritoo
d801e675fc Exception - InvalidHtmlAttributesException - an exception used while html attributes are invalid 2017-12-24 00:03:23 +01:00
Meritoo
6753076937 Regex - isValidHtmlAttribute() & areValidHtmlAttributes() methods - returns information if given html attribute is valid & if given html attributes are valid 2017-12-23 23:08:49 +01:00
Meritoo
7f713e0c6e Docker - name of containers - use custom prefix 2017-12-22 10:44:07 +01:00
Meritoo
ebbed4825c Bundle - getBundleViewPath() method - return path using namespaced syntax 2017-12-21 23:45:01 +01:00
Meritoo
7d23ff59d1 Bundle - getBundleViewPath() method - verify name of bundle 2017-12-21 22:45:23 +01:00
Meritoo
0e4c33241e Tests - BundleTest - minor refactoring 2017-12-21 22:05:07 +01:00
Meritoo
66aefa2446 Regex - isValidBundleName() method - returns information if given name of bundle is valid 2017-12-21 21:47:45 +01:00
Meritoo
5aaf7cde72 Minor refactoring 2017-12-21 20:41:12 +01:00
Meritoo
8bb529b88d Docker - Dockerfile - minor refactoring 2017-12-02 13:23:26 +01:00
Meritoo
3588c00009 Docker - do not install "zip" package 2017-12-02 13:12:34 +01:00
Meritoo
78480ac853 .gitignore - ignore .env 2017-12-02 12:53:32 +01:00
Meritoo
8bcf006e02 Tests - increase code coverage 2017-11-05 19:35:13 +01:00
Meritoo
edc51aeee1 DatePeriod - change namespace (Meritoo\Common\Utilities -> Meritoo\Common\Type) & extend BaseType 2017-11-03 20:21:08 +01:00
Meritoo
6d4e422165 BaseTestCase & BaseTypeTestCase - add traits to use in other test cases (e.g. in Symfony's kernel-related test case) 2017-11-02 22:00:38 +01:00
Meritoo
6f441bb9ea Tests - BaseTestCaseTest - fix bug while there is a difference (split second) 2017-11-02 13:58:24 +01:00
Meritoo
73030d703b composer.json - bump version 2017-11-02 12:25:39 +01:00
Meritoo
36ddb326b9 Tests - increase code coverage 2017-10-31 21:27:42 +01:00
Meritoo
452a4ec458 Tests - BaseTestCase - rename method getFilePathToTests() -> getFilePathForTesting() 2017-10-31 21:26:39 +01:00
Meritoo
325fe6b141 Support PHP 5.5.9+ 2017-10-31 20:28:55 +01:00
Meritoo
a1c26b3812 Phing - tests - phpcodesniffer task - fix "This task requires the PHP_CodeSniffer package installed and available on the include path" bug
Details: https://github.com/phingofficial/phing/issues/716
2017-10-26 20:04:05 +02:00
Meritoo
67d93036cf Phing - update properties.dist file 2017-10-22 21:40:23 +02:00
Meritoo
9368616dfe composer.json - update versions of the "dev" packages 2017-10-22 20:09:02 +02:00
Meritoo
5ab68d3667 Tests - Docker - update Xdebug configuration
Required to fix problem "Connection with XDebug 2.5.1 was not established. Validate installation."
2017-10-22 17:55:49 +02:00
Meritoo
4613a63f02 Tests - Docker - install vim, add custom php.ini, add "vendor/bin" to the $PATH global variable 2017-10-20 00:03:38 +02:00
Meritoo
9dac5bd11c Tests - Docker - update name of image and container 2017-10-18 21:50:02 +02:00
Meritoo
12100db058 Tests - Docker - update port 2017-10-18 20:02:09 +02:00
Meritoo
f9ab0a6194 Tests - Docker - add required libraries, PHP extensions & optimize size of Docker's image 2017-10-18 17:01:13 +02:00
Meritoo
b824808cd4 Tests - use Docker (as environment guard) 2017-10-18 00:31:18 +02:00
Meritoo
71e1eeb81b Start names of special directories with dot
BaseTestCase - add setter for path of directory with data used by test cases
2017-10-17 20:49:13 +02:00
Meritoo
70c273750d .gitignore update 2017-10-10 20:09:40 +02:00
Meritoo
e5e39651f3 Tests - fix names of constructors' tests 2017-10-02 15:56:53 +02:00
Meritoo
4683970c87 composer.json - update versions of the "dev" packages & sort them 2017-10-02 14:06:57 +02:00
Meritoo
559466c0ce composer.json - move tests-related classes to "autoload-dev" section (used for development purposes only and avoid polluting the autoloader in production) 2017-09-29 09:19:03 +02:00
Meritoo
bfd69c1098 Minor fix of coding standard 2017-09-27 21:52:10 +02:00
Meritoo
45493b37b0 Remove composer.lock 2017-09-27 21:51:48 +02:00
Meritoo
37e7b14ae2 Minor fix of coding standard 2017-09-27 20:09:51 +02:00
Meritoo
a12aaf4bc0 Tests - increase code coverage 2017-09-27 17:08:39 +02:00
Meritoo
f9c480aa19 Reflection - getPropertyValue() method - verify if getter is accessible publicly 2017-09-27 17:00:25 +02:00
119 changed files with 7669 additions and 5707 deletions

15
.env.dist Normal file
View File

@@ -0,0 +1,15 @@
# -----------------------------------------------------------------------------
### Docker
# -----------------------------------------------------------------------------
#
# All containers
#
DOCKER_CONTAINER_OWNER=meritoo
DOCKER_CONTAINER_PROJECT=common-library
#
# PHP configuration:
# - timezone
#
TIMEZONE=Europe/Warsaw

69
.gitignore vendored
View File

@@ -1,44 +1,58 @@
# ---------------------------------------------------------------------------------------------------------------------- # ------------------------------------------------------------------------------
# Environment-related parameters
# ------------------------------------------------------------------------------
.env
# ------------------------------------------------------------------------------
### Vendors ### Vendors
# ---------------------------------------------------------------------------------------------------------------------- # ------------------------------------------------------------------------------
/vendor/ /vendor/
# ---------------------------------------------------------------------------------------------------------------------- # ------------------------------------------------------------------------------
### Composer ### Composer
# ---------------------------------------------------------------------------------------------------------------------- # ------------------------------------------------------------------------------
/composer.lock
/composer.phar /composer.phar
# ---------------------------------------------------------------------------------------------------------------------- # ------------------------------------------------------------------------------
### Phing ### Phing
# ---------------------------------------------------------------------------------------------------------------------- # ------------------------------------------------------------------------------
/phing/properties /phing/properties
# ---------------------------------------------------------------------------------------------------------------------- # ------------------------------------------------------------------------------
### PHPUnit ### PHPUnit
# ---------------------------------------------------------------------------------------------------------------------- # ------------------------------------------------------------------------------
/phpunit.xml /phpunit.xml
# ---------------------------------------------------------------------------------------------------------------------- # ------------------------------------------------------------------------------
### PHP Coding Standards Fixer generated files ### PHP Coding Standards Fixer
# ---------------------------------------------------------------------------------------------------------------------- # ------------------------------------------------------------------------------
/.php_cs
/.php_cs.cache /.php_cs.cache
# ---------------------------------------------------------------------------------------------------------------------- # -----------------------------------------------------------------------------
### Build files
# -----------------------------------------------------------------------------
/build/
# ------------------------------------------------------------------------------
### Generated databases ### Generated databases
# ---------------------------------------------------------------------------------------------------------------------- # ------------------------------------------------------------------------------
/data/tmp /data/tmp
*.sql *.sql
*.sqlite *.sqlite
# ---------------------------------------------------------------------------------------------------------------------- # ------------------------------------------------------------------------------
### Compiled source ### Compiled source
# ---------------------------------------------------------------------------------------------------------------------- # ------------------------------------------------------------------------------
*.com *.com
*.class *.class
*.dll *.dll
@@ -47,23 +61,22 @@
*.so *.so
# ---------------------------------------------------------------------------------------------------------------------- # ------------------------------------------------------------------------------
### Shell scripts ### Shell scripts
# ---------------------------------------------------------------------------------------------------------------------- # ------------------------------------------------------------------------------
/*.sh /*.sh
# ---------------------------------------------------------------------------------------------------------------------- # ------------------------------------------------------------------------------
### JetBrains ### JetBrains
# ---------------------------------------------------------------------------------------------------------------------- # ------------------------------------------------------------------------------
/.idea /.idea
# ---------------------------------------------------------------------------------------------------------------------- # ------------------------------------------------------------------------------
### NetBeans template ### NetBeans template
# ---------------------------------------------------------------------------------------------------------------------- # ------------------------------------------------------------------------------
nbproject/private/ nbproject/private/
build/
nbbuild/ nbbuild/
dist/ dist/
nbdist/ nbdist/
@@ -71,9 +84,9 @@ nbactions.xml
.nb-gradle/ .nb-gradle/
# ---------------------------------------------------------------------------------------------------------------------- # ------------------------------------------------------------------------------
### OSX template ### OSX template
# ---------------------------------------------------------------------------------------------------------------------- # ------------------------------------------------------------------------------
.DS_Store .DS_Store
.AppleDouble .AppleDouble
.LSOverride .LSOverride
@@ -100,9 +113,9 @@ Temporary Items
.apdisk .apdisk
# ---------------------------------------------------------------------------------------------------------------------- # ------------------------------------------------------------------------------
### Linux template ### Linux template
# ---------------------------------------------------------------------------------------------------------------------- # ------------------------------------------------------------------------------
*~ *~
# temporary files which can be created if a process still has a handle open of a deleted file # temporary files which can be created if a process still has a handle open of a deleted file
@@ -115,9 +128,9 @@ Temporary Items
.Trash-* .Trash-*
# ---------------------------------------------------------------------------------------------------------------------- # ------------------------------------------------------------------------------
### Windows template ### Windows template
# ---------------------------------------------------------------------------------------------------------------------- # ------------------------------------------------------------------------------
# Windows image file caches # Windows image file caches
Thumbs.db Thumbs.db
ehthumbs.db ehthumbs.db

View File

@@ -1,13 +1,6 @@
<?php <?php
$finder = PhpCsFixer\Finder::create() $finder = PhpCsFixer\Finder::create()
/*
* Do not verify:
* - all DependencyInjection/Configuration classes: the Configuration.php files
* - autoloader from /app directory: autoload.php
*/
->notPath('/DependencyInjection\/Configuration\.php/')
->notPath('/autoload\.php/')
->in([ ->in([
__DIR__ . '/src', __DIR__ . '/src',
__DIR__ . '/tests', __DIR__ . '/tests',
@@ -15,16 +8,20 @@ $finder = PhpCsFixer\Finder::create()
return PhpCsFixer\Config::create() return PhpCsFixer\Config::create()
->setRules([ ->setRules([
'@Symfony' => true, '@Symfony' => true,
'phpdoc_summary' => false, 'binary_operator_spaces' => [
'phpdoc_separation' => false,
'phpdoc_align' => false,
'cast_spaces' => false,
'binary_operator_spaces' => [
'align_double_arrow' => true, 'align_double_arrow' => true,
], ],
'concat_space' => [ 'blank_line_before_return' => false,
'cast_spaces' => false,
'concat_space' => [
'spacing' => 'one', 'spacing' => 'one',
], ],
'phpdoc_add_missing_param_annotation' => true,
'phpdoc_align' => false,
'phpdoc_order' => true,
'phpdoc_separation' => false,
'phpdoc_summary' => false,
'trim_array_spaces' => false,
]) ])
->setFinder($finder); ->setFinder($finder);

View File

@@ -1,8 +0,0 @@
preset: symfony
disabled:
- phpdoc_annotation_without_dot
- cast_spaces
- concat_without_spaces
- blank_line_before_return
- trim_array_spaces

View File

@@ -4,9 +4,14 @@ php:
- 5.6 - 5.6
- 7.0 - 7.0
- 7.1 - 7.1
- 7.2
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
install: install:
- composer install - travis_wait 30 composer install
script: script:
- php ./vendor/bin/phpunit - php ./vendor/bin/phpunit

43
CHANGELOG.md Normal file
View File

@@ -0,0 +1,43 @@
# Meritoo Common Library
Common and useful classes, methods, exceptions etc.
# 0.1.2
1. Documentation > Value Objects
2. Docker > improve performance
3. Utilities > Reflection > setPropertyValue() method > sets value of given property
# 0.1.1
1. TravisCI > run using PHP 7.2 too
2. ValueObject > class Version > represents version of software
3. Move version of this package to `VERSION` file (from `composer.json` file)
# 0.1.0
1. Composer > support/require PHP 5.6+ (instead of 5.5.9+)
2. Docker > rename `php-cli` service to `php`
3. Exceptions > create instance of exception using static `create()` method (instead of constructor)
4. Documentation > Exceptions
# 0.0.21
1. Composer > require ext-pcre
2. Arrays > minor refactoring
3. Update @author and @copyright in classes' descriptions
# 0.0.20
1. Collection > add() method > treat empty string as not provided index (same as null)
# 0.0.19
1. Add this changelog
2. Reorganize documentation & update [Readme](README.md)
3. Docker: use project-related binaries globally
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"
8. StyleCI > disable & remove

102
README.md
View File

@@ -1,105 +1,29 @@
# Meritoo Common Library # Meritoo Common Library
Common and useful classes, methods, exceptions etc. Common and useful classes, methods, exceptions etc.
[![Travis](https://img.shields.io/travis/rust-lang/rust.svg?style=flat-square)](https://travis-ci.org/meritoo/common-library) [![Packagist](https://img.shields.io/packagist/v/meritoo/common-library.svg?style=flat-square)](https://packagist.org/packages/meritoo/common-library) [![StyleCI](https://styleci.io/repos/101790028/shield?branch=master)](https://styleci.io/repos/101790028) [![license](https://img.shields.io/github/license/meritoo/common-library.svg?style=flat-square)](https://github.com/meritoo/common-library) [![GitHub commits](https://img.shields.io/github/commits-since/meritoo/common-library/0.0.1.svg?style=flat-square)](https://github.com/meritoo/common-library) [![Coverage Status](https://coveralls.io/repos/github/meritoo/common-library/badge.svg?branch=master)](https://coveralls.io/github/meritoo/common-library?branch=master) [![Travis](https://img.shields.io/travis/rust-lang/rust.svg?style=flat-square)](https://travis-ci.org/meritoo/common-library) [![Packagist](https://img.shields.io/packagist/v/meritoo/common-library.svg?style=flat-square)](https://packagist.org/packages/meritoo/common-library) [![license](https://img.shields.io/github/license/meritoo/common-library.svg?style=flat-square)](https://github.com/meritoo/common-library) [![GitHub commits](https://img.shields.io/github/commits-since/meritoo/common-library/0.0.1.svg?style=flat-square)](https://github.com/meritoo/common-library) [![Coverage Status](https://coveralls.io/repos/github/meritoo/common-library/badge.svg?branch=master)](https://coveralls.io/github/meritoo/common-library?branch=master)
## Installation # Installation
Run [Composer](https://getcomposer.org) to install this package in your project: Run [Composer](https://getcomposer.org) to install this package in your project:
```bash ```bash
$ composer require meritoo/common-library composer require meritoo/common-library
``` ```
> How to install Composer: https://getcomposer.org/download > [How to install Composer?](https://getcomposer.org/download)
## Static methods # Usage
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: 1. [Base test case (with common methods and data providers)](docs/Base-test-case.md)
2. [Collection of elements](docs/Collection-of-elements.md)
3. [Exceptions](docs/Static-methods.md)
4. [Static methods](docs/Static-methods.md)
5. [Value Objects](docs/Value-Objects.md)
```php # Development
use Meritoo\Common\Utilities\Arrays;
$firstElement = Arrays::getFirstElement(['lorem', 'ipsum']); More information [you can find here](docs/Development.md)
var_dump($firstElement); // string(5) "lorem"
```
## 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:
```php
class DateTest extends BaseTestCase
{
/**
* @param mixed $value Empty value, e.g. ""
* @dataProvider provideEmptyValue
*/
public function testGetDateTimeEmptyValue($value)
{
self::assertFalse(Date::getDateTime($value));
}
(...)
}
```
or in `Meritoo\Common\Test\Utilities\MimeTypesTest` class:
```php
class MimeTypesTest extends BaseTestCase
{
(...)
/**
* @param bool $mimeType The mime type, e.g. "video/mpeg"
* @dataProvider provideBooleanValue
*/
public function testGetExtensionBooleanMimeType($mimeType)
{
self::assertEquals('', MimeTypes::getExtension($mimeType));
}
(...)
}
```
## 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)
```
Enjoy! Enjoy!

1
VERSION Normal file
View File

@@ -0,0 +1 @@
0.1.2

View File

@@ -4,10 +4,10 @@
<if> <if>
<available file="phing/properties" property="custom.properties.available"/> <available file="phing/properties" property="custom.properties.available"/>
<then> <then>
<property file="phing/properties" /> <property file="phing/properties"/>
</then> </then>
<else> <else>
<property file="phing/properties.dist" /> <property file="phing/properties.dist"/>
</else> </else>
</if> </if>
@@ -18,18 +18,18 @@
<!-- Build app --> <!-- Build app -->
<target name="build:app" description="Prepares app to build and tests"> <target name="build:app" description="Prepares app to build and tests">
<phing phingfile="phing/app.xml" haltonfailure="true" /> <phing phingfile="phing/app.xml" haltonfailure="true"/>
</target> </target>
<!-- Build tests --> <!-- Build tests -->
<target name="build:tests" description="Runs all tests, checks and creates docs"> <target name="build:tests" description="Runs all tests, checks and creates docs">
<phing phingfile="phing/tests.xml" haltonfailure="true" /> <phing phingfile="phing/tests.xml" haltonfailure="true"/>
<!-- <!--
Conditional running of tests. Conditional running of tests.
Disabled, because not required. Disabled, because not required.
Krzysztof Niziol <krzysztof.niziol@meritoo.pl> Meritoo <github@meritoo.pl>
2017-02-22 2017-02-22
<if> <if>

View File

@@ -2,7 +2,6 @@
"name": "meritoo/common-library", "name": "meritoo/common-library",
"description": "Useful classes, methods, extensions etc.", "description": "Useful classes, methods, extensions etc.",
"license": "MIT", "license": "MIT",
"version": "0.0.12",
"authors": [ "authors": [
{ {
"name": "Meritoo.pl", "name": "Meritoo.pl",
@@ -11,24 +10,31 @@
} }
], ],
"require": { "require": {
"php": ">=5.6.0", "php": ">=5.6",
"ext-pcre": "*",
"doctrine/orm": "^2.5", "doctrine/orm": "^2.5",
"gedmo/doctrine-extensions": "^2.4", "gedmo/doctrine-extensions": "^2.4"
"symfony/http-foundation": "^3.3"
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": "^5.7", "friendsofphp/php-cs-fixer": "^2.2",
"squizlabs/php_codesniffer": "^2.9",
"phpmd/phpmd": "^2.6",
"sebastian/phpcpd": "^3.0",
"pdepend/pdepend": "^2.5", "pdepend/pdepend": "^2.5",
"phploc/phploc": "^4.0", "phploc/phploc": "^2.1",
"friendsofphp/php-cs-fixer": "^2.6" "phpmd/phpmd": "^2.6",
"phpunit/phpunit": "^4.8",
"sebastian/phpcpd": "^2.0",
"squizlabs/php_codesniffer": "^2.9"
}, },
"autoload": { "autoload": {
"psr-4": { "psr-4": {
"Meritoo\\Common\\": "src/Meritoo/Common/", "Meritoo\\Common\\": "src/"
"Meritoo\\Common\\Test\\": "tests/Meritoo/Common/Test/"
} }
},
"autoload-dev": {
"psr-4": {
"Meritoo\\Common\\Test\\": "tests/"
}
},
"config": {
"sort-packages": true
} }
} }

3494
composer.lock generated

File diff suppressed because it is too large Load Diff

20
docker-compose.yml Normal file
View File

@@ -0,0 +1,20 @@
version: '3'
services:
php:
image: ${DOCKER_CONTAINER_OWNER}/${DOCKER_CONTAINER_PROJECT}-php
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}
volumes:
- .:/project:cached
composer:
image: ${DOCKER_CONTAINER_OWNER}/${DOCKER_CONTAINER_PROJECT}-php
container_name: ${DOCKER_CONTAINER_OWNER}-${DOCKER_CONTAINER_PROJECT}-composer
entrypoint: composer
volumes:
- .:/project:cached

131
docker/config/Dockerfile Normal file
View File

@@ -0,0 +1,131 @@
FROM php:5.6-cli
MAINTAINER Meritoo <github@meritoo.pl>
#
# 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') === \
'544e09ee996cdf60ece3804abc52599c22b1f40f4323403c44d44fdfdd586475ca9813a858088ffbc1f233e9b180f061') { echo \
'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;" \
&& php composer-setup.php --install-dir=/usr/local/bin --filename=composer \
&& php -r "unlink('composer-setup.php');" \
&& composer global require \
--no-plugins \
--no-scripts \
--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

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

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

6
docker/config/xdebug.ini Normal file
View File

@@ -0,0 +1,6 @@
[xdebug]
zend_extension=xdebug.so
xdebug.remote_enable=1
xdebug.remote_port=9001
xdebug.remote_host=10.254.254.254

53
docs/Base-test-case.md Normal file
View File

@@ -0,0 +1,53 @@
# Meritoo Common Library
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:
```php
class DateTest extends BaseTestCase
{
/**
* @param mixed $value Empty value, e.g. ""
* @dataProvider provideEmptyValue
*/
public function testGetDateTimeEmptyValue($value)
{
self::assertFalse(Date::getDateTime($value));
}
(...)
}
```
or in `Meritoo\Common\Test\Utilities\MimeTypesTest` class:
```php
class MimeTypesTest extends BaseTestCase
{
(...)
/**
* @param bool $mimeType The mime type, e.g. "video/mpeg"
* @dataProvider provideBooleanValue
*/
public function testGetExtensionBooleanMimeType($mimeType)
{
self::assertEquals('', MimeTypes::getExtension($mimeType));
}
(...)
}
```
# 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)
5. [Value Objects](Value-Objects.md)
[&lsaquo; Back to `Readme`](../README.md)

View File

@@ -0,0 +1,51 @@
# 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)
5. [Value Objects](Value-Objects.md)
[&lsaquo; Back to `Readme`](../README.md)

119
docs/Development.md Normal file
View File

@@ -0,0 +1,119 @@
# Meritoo Common Library
Development-related information
# Requirements
* [Docker](https://www.docker.com)
* Your favourite IDE :)
# Getting started
1. Build, create and start Docker's containers by running command:
```bash
docker-compose up -d
```
2. Install packages by running command:
```bash
docker-compose run composer install
```
> [What is Docker?](https://www.docker.com/what-docker)
# Composer
Available as `composer` service. You can run any Composer's command using the `composer` service:
```bash
docker-compose run composer <command>
```
Examples below.
##### Install packages
```bash
docker-compose run composer install
```
##### Update packages
```bash
docker-compose run composer update
```
##### Add package
```bash
docker-compose run composer require <vendor>/<package>
```
##### Remove package
```bash
docker-compose run composer remove <vendor>/<package>
```
# Coding Standards Fixer
Fix coding standard by running command:
```bash
docker-compose exec php php-cs-fixer fix
```
Omit cache and run the Fixer from scratch by running command:
```bash
docker-compose exec php rm .php_cs.cache && docker-compose exec php php-cs-fixer fix
```
> [Want more?](https://cs.sensiolabs.org)
# Tests
### Prerequisites
Install required packages by running command: `docker-compose run composer install`.
### Running tests
#### Simply & quick, without code coverage
Tests are running using Docker and `php` service defined in `docker-compose.yml`. Example:
```bash
docker-compose exec php phpunit --no-coverage
```
You can also run them in container. In this case you have to run 2 commands:
1. Enter container:
```bash
docker-compose exec php bash
```
2. Run tests:
```bash
phpunit --no-coverage
```
#### With code coverage
```bash
docker-compose exec php phpunit
```
# Other
Rebuild project and run tests by running command:
```bash
docker-compose exec php phing
```
[&lsaquo; Back to `Readme`](../README.md)

62
docs/Exceptions.md Normal file
View File

@@ -0,0 +1,62 @@
# Meritoo Common Library
Common and useful classes, methods, exceptions etc.
# Exceptions
### 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:
```php
use Meritoo\Common\Exception\Bundle\IncorrectBundleNameException;
throw IncorrectBundleNameException::create('RisusIpsum');
```
### Base exception for unknown type of something
##### 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.
##### 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.
##### Example
```php
<?php
namespace Your\Package\Exception\Type;
use Meritoo\Common\Exception\Base\UnknownTypeException;
use Your\Package\Type\SimpleType;
class UnknownSimpleTypeException extends UnknownTypeException
{
/**
* Creates exception
*
* @param string $unknownType Unknown and simple type
* @return UnknownSimpleTypeException
*/
public static function createException($unknownType)
{
/* @var UnknownSimpleTypeException $exception */
$exception = parent::create($unknownType, new SimpleType(), 'my simple type of something');
return $exception;
}
}
```
# 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)
5. [Value Objects](Value-Objects.md)
[&lsaquo; Back to `Readme`](../README.md)

24
docs/Static-methods.md Normal file
View File

@@ -0,0 +1,24 @@
# Meritoo Common Library
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:
```php
use Meritoo\Common\Utilities\Arrays;
$firstElement = Arrays::getFirstElement(['lorem', 'ipsum']);
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)
5. [Value Objects](Value-Objects.md)
[&lsaquo; Back to `Readme`](../README.md)

53
docs/Value-Objects.md Normal file
View File

@@ -0,0 +1,53 @@
# Meritoo Common Library
Common and useful classes, methods, exceptions etc.
# Value Objects
Located in `Meritoo\Common\ValueObject` namespace.
### Version
##### Namespace
`Meritoo\Common\ValueObject\Version`
##### Info
Represents version of software. Contains 3 properties:
1. `$majorPart` - the "major" part of version
2. `$minorPart` - the "minor" part of version
3. `$patchPart` - the "patch" part of version
##### New instance
New instance can be created using:
1. Constructor:
```php
new Version(1, 0, 2);
```
2. Static methods:
1. `fromArray()` - creates new instance using given version as array
```php
Version::fromArray([1, 0, 2]);
```
2. `fromString()` - creates new instance using given version as string:
```php
Version::fromString('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)
5. [**Value Objects**](Value-Objects.md)
[&lsaquo; Back to `Readme`](../README.md)

View File

@@ -4,10 +4,10 @@
<if> <if>
<available file="phing/properties" property="custom.properties.available"/> <available file="phing/properties" property="custom.properties.available"/>
<then> <then>
<property file="phing/properties" /> <property file="phing/properties"/>
</then> </then>
<else> <else>
<property file="phing/properties.dist" /> <property file="phing/properties.dist"/>
</else> </else>
</if> </if>
@@ -21,9 +21,9 @@
depends="app:composer, app:vendors, app:checkout" depends="app:composer, app:vendors, app:checkout"
description="Prepares app to build." /> description="Prepares app to build." />
<!-- Check / update composer --> <!-- Updates Composer and validates composer.* files -->
<target name="app:composer" description="Checks / updates composer"> <target name="app:composer" description="Updates Composer and validates composer.* files">
<echo msg="Checking / updating composer..." /> <echo msg="Updating Composer and validating composer.* files..." />
<if> <if>
<available file="composer.phar" /> <available file="composer.phar" />
@@ -42,7 +42,14 @@
</if> </if>
</else> </else>
</if> </if>
<!-- Update Composer -->
<composer command="selfupdate" /> <composer command="selfupdate" />
<!-- Validate Composer -->
<composer command="validate">
<arg line="--no-check-all --strict" />
</composer>
</target> </target>
<!-- Project Install/update vendors --> <!-- Project Install/update vendors -->
@@ -68,6 +75,8 @@
<then> <then>
<composer php="${composer.php}" composer="${composer.path}" command="install"> <composer php="${composer.php}" composer="${composer.path}" command="install">
<arg value="--optimize-autoloader" /> <arg value="--optimize-autoloader" />
<arg value="--prefer-dist" />
<arg value="--classmap-authoritative" />
</composer> </composer>
</then> </then>
<else> <else>

View File

@@ -28,7 +28,13 @@ assets.installWithSymlink = true
# Clear cache with the "warmup" option # Clear cache with the "warmup" option
# #
cache.clearWithWarmup = true # The cache:clear command should always be called with the --no-warmup option. Warmup should be done via the cache:warmup command.
# https://github.com/symfony/symfony/blob/master/UPGRADE-3.3.md#frameworkbundle
#
# Meritoo <github@meritoo.pl>
# 2017-06-06
#
cache.clearWithWarmup = false
# -------------------------------------------------------------------------------- # --------------------------------------------------------------------------------
# Composer # Composer
@@ -75,7 +81,7 @@ dir.reports.coverage = ${dir.reports}/phpunit_coverage
# Disabled, because unnecessary right now # Disabled, because unnecessary right now
# phpdocumentor/phpdocumentor cannot be installed via Composer # phpdocumentor/phpdocumentor cannot be installed via Composer
# #
# Krzysztof Niziol <krzysztof.niziol@meritoo.pl> # Meritoo <github@meritoo.pl>
# 2017-02-22 # 2017-02-22
# #
#dir.docs = ${dir.build}/docs #dir.docs = ${dir.build}/docs
@@ -85,40 +91,15 @@ dir.reports.coverage = ${dir.reports}/phpunit_coverage
# Data directories # Data directories
# -------------------------------------------------------------------------------- # --------------------------------------------------------------------------------
dir.data.tests = ${dir.data}/tests
dir.data.temporary = ${dir.data}/tmp dir.data.temporary = ${dir.data}/tmp
# -------------------------------------------------------------------------------- # --------------------------------------------------------------------------------
# Testing # Testing
# -------------------------------------------------------------------------------- # --------------------------------------------------------------------------------
# Test database path # Path of the framework used to run unit tests
# #
tests.database = ${dir.data.temporary}/database.sqlite tests.framework.path = ./vendor/bin/phpunit --verbose --no-coverage --testdox
#
# Disabled, because unnecessary right now
# PHPUnit is installed and loaded by Composer
#
# Krzysztof Niziol <krzysztof.niziol@meritoo.pl>
# 2017-02-22
#
# Run PHPUnit using exec task instead of phpunitTask
#phpunit.useExec = false
#
# Disabled, because unnecessary right now
# We want generate code coverage always
#
# Krzysztof Niziol <krzysztof.niziol@meritoo.pl>
# 2017-02-22
#
# Collect coverage data during tests
#phpunit.withCoverage = true
# Path of the PHPUnit (https://phpunit.de)
#
phpUnit.path = ./vendor/bin/phpunit
# Path of the PHP Coding Standards Fixer (http://cs.sensiolabs.org) # Path of the PHP Coding Standards Fixer (http://cs.sensiolabs.org)
# #

View File

@@ -4,7 +4,7 @@
The AutoloaderTask is required to load binaries installed by Composer. The AutoloaderTask is required to load binaries installed by Composer.
The "autoloaderpath" attribute of this task is not required, because it's default value is: vendor/autoload.php. The "autoloaderpath" attribute of this task is not required, because it's default value is: vendor/autoload.php.
Krzysztof Niziol <krzysztof.niziol@meritoo.pl> Meritoo <github@meritoo.pl>
2017-02-23 2017-02-23
--> -->
<autoloader /> <autoloader />
@@ -13,10 +13,10 @@
<if> <if>
<available file="phing/properties" property="custom.properties.available"/> <available file="phing/properties" property="custom.properties.available"/>
<then> <then>
<property file="phing/properties" /> <property file="phing/properties"/>
</then> </then>
<else> <else>
<property file="phing/properties.dist" /> <property file="phing/properties.dist"/>
</else> </else>
</if> </if>
@@ -48,7 +48,7 @@
a) phpdocumentor/phpdocumentor v2.9.0 requires symfony/validator ~2.2 a) phpdocumentor/phpdocumentor v2.9.0 requires symfony/validator ~2.2
b) symfony/validator ~2.2 causes to remove symfony/symfony 3.* b) symfony/validator ~2.2 causes to remove symfony/symfony 3.*
Krzysztof Niziol <krzysztof.niziol@meritoo.pl> Meritoo <github@meritoo.pl>
2017-02-22 2017-02-22
--> -->
@@ -73,7 +73,7 @@
a) phpdocumentor/phpdocumentor v2.9.0 requires symfony/validator ~2.2 a) phpdocumentor/phpdocumentor v2.9.0 requires symfony/validator ~2.2
b) symfony/validator ~2.2 causes to remove symfony/symfony 3.* b) symfony/validator ~2.2 causes to remove symfony/symfony 3.*
Krzysztof Niziol <krzysztof.niziol@meritoo.pl> Meritoo <github@meritoo.pl>
2017-02-22 2017-02-22
--> -->
<!--<target name="build:doc"--> <!--<target name="build:doc"-->
@@ -87,7 +87,7 @@
<!-- Test target --> <!-- Test target -->
<target name="build:test" <target name="build:test"
depends="test:phpunit" depends="test:unit"
description="Executes all tests" /> description="Executes all tests" />
<!-- Project build clean --> <!-- Project build clean -->
@@ -103,8 +103,8 @@
<!--<mkdir dir="${dir.docs}" />--> <!--<mkdir dir="${dir.docs}" />-->
<!--<mkdir dir="${dir.docs.phpdoc2}" />--> <!--<mkdir dir="${dir.docs.phpdoc2}" />-->
<mkdir dir="${dir.reports}" /> <mkdir dir="${dir.reports}" />
<mkdir dir="${dir.reports.coverage}" />
<mkdir dir="${dir.reports.pdepend}" /> <mkdir dir="${dir.reports.pdepend}" />
<mkdir dir="${dir.reports.coverage}"/>
</target> </target>
<!-- PHPDocumentor2 API documentation target --> <!-- PHPDocumentor2 API documentation target -->
@@ -113,7 +113,7 @@
a) phpdocumentor/phpdocumentor v2.9.0 requires symfony/validator ~2.2 a) phpdocumentor/phpdocumentor v2.9.0 requires symfony/validator ~2.2
b) symfony/validator ~2.2 causes to remove symfony/symfony 3.* b) symfony/validator ~2.2 causes to remove symfony/symfony 3.*
Krzysztof Niziol <krzysztof.niziol@meritoo.pl> Meritoo <github@meritoo.pl>
2017-02-22 2017-02-22
<target name="doc:phpdoc2" description="Generates API documentations"> <target name="doc:phpdoc2" description="Generates API documentations">
@@ -142,7 +142,7 @@
via Composer the Symfony2 standard is not included / available in this package. In this case the PHP Coding via Composer the Symfony2 standard is not included / available in this package. In this case the PHP Coding
Standards Fixer (http://cs.sensiolabs.org) is used. Standards Fixer (http://cs.sensiolabs.org) is used.
Krzysztof Niziol <krzysztof.niziol@meritoo.pl> Meritoo <github@meritoo.pl>
2017-02-22 2017-02-22
--> -->
<target name="check:cs" description="Checks coding standard"> <target name="check:cs" description="Checks coding standard">
@@ -166,7 +166,7 @@
<!-- <!--
Previous / old version Previous / old version
Krzysztof Niziol <krzysztof.niziol@meritoo.pl> Meritoo <github@meritoo.pl>
2017-02-22 2017-02-22
<exec command="phpcpd \-\-log-pmd=${dir.reports}/pmd-cpd.xml ${dir.src}" /> <exec command="phpcpd \-\-log-pmd=${dir.reports}/pmd-cpd.xml ${dir.src}" />
@@ -204,7 +204,7 @@
<!-- <!--
Previous / old version Previous / old version
Krzysztof Niziol <krzysztof.niziol@meritoo.pl> Meritoo <github@meritoo.pl>
2017-02-22 2017-02-22
<exec command="phploc \-\-log-csv=${dir.reports}/phploc.csv ${dir.src}" /> <exec command="phploc \-\-log-csv=${dir.reports}/phploc.csv ${dir.src}" />
@@ -212,94 +212,9 @@
</target> </target>
<!-- Unit tests --> <!-- Unit tests -->
<target name="test:phpunit" description="Executes PHPUnit tests"> <target name="test:unit" description="Executes unit tests">
<!-- Check test database -->
<if>
<not>
<available file="${dir.data.tests}" type="dir" property="dir.data.tests.available" />
</not>
<then>
<mkdir dir="${dir.data.tests}" />
</then>
</if>
<if>
<not>
<available file="${tests.database}" property="tests.database.available" />
</not>
<then>
<touch file="${tests.database}" />
</then>
</if>
<echo msg="Running unit tests..." /> <echo msg="Running unit tests..." />
<coverage-setup database="${dir.reports.coverage}/coverage.db"> <exec command="${tests.framework.path}" passthru="true"/>
<fileset refid="sourcecode" />
</coverage-setup>
<exec command="${phpUnit.path} --verbose --configuration ${project.basedir}/phpunit.xml.dist" passthru="true" />
<!--
I have to use ExecTask to run PHPUnit instead of PHPUnitTask, because tests are not running if PHPUnitTask is
used (don't know why):
Total tests run: 0, Failures: 0, Errors: 0, Incomplete: 0, Skipped: 0
Krzysztof Niziol <krzysztof.niziol@meritoo.pl>
2017-02-23
<phpunit configuration="${project.basedir}/phpunit.xml.dist" printsummary="true">
<formatter type="xml" todir="${dir.reports}" outfile="phpunit.xml" />
<formatter type="plain" todir="${dir.reports}" outfile="phpunit.txt" />
<formatter type="clover" todir="${dir.reports.coverage}" />
<formatter type="summary" todir="${dir.reports}" outfile="phpunit_summary.txt" />
</phpunit>
-->
<!--
Previous / old version
Krzysztof Niziol <krzysztof.niziol@meritoo.pl>
2017-02-22
<if>
<istrue value="${phpunit.useExec}" />
<then>
<if>
<istrue value="${phpunit.withCoverage}" />
<then>
<echo message="Running tests with code coverage..." />
<exec command="phpunit \-\-log-junit ${dir.reports}/phpunit.xml \-\-coverage-clover ${dir.reports.coverage}/clover-coverage.xml \-\-coverage-crap4j ${dir.reports.coverage}/crap4j-coverage.xml \-\-coverage-html ${dir.reports.coverage}/ -c ${project.basedir} \-\-colors" passthru="true" checkreturn="true" />
</then>
<else>
<echo message="Running tests without code coverage..." />
<exec command="phpunit \-\-log-junit ${dir.reports}/phpunit.xml -c ${project.basedir} \-\-colors" passthru="true" checkreturn="true" />
</else>
</if>
</then>
<else>
<if>
<istrue value="${phpunit.withCoverage}" />
<then>
<echo message="Running tests with code coverage..." />
<coverage-setup database="${dir.reports.coverage}/coverage.db">
<fileset refid="sourcecode" />
</coverage-setup>
<phpunit printsummary="true" codecoverage="true">
<formatter type="xml" todir="${dir.reports}" outfile="phpunit.xml" />
<formatter type="plain" todir="${dir.reports}" outfile="phpunit.txt" />
<formatter type="clover" todir="${dir.reports.coverage}" />
<formatter type="summary" todir="${dir.reports}" outfile="phpunit_summary.txt" />
</phpunit>
</then>
<else>
<echo message="Running tests without code coverage..." />
<phpunit printsummary="true">
<formatter todir="${dir.reports}" type="xml" outfile="phpunit.xml" />
<batchtest>
<fileset refid="tests" />
</batchtest>
</phpunit>
</else>
</if>
</else>
</if>
-->
</target> </target>
<!-- Checkout and finalization --> <!-- Checkout and finalization -->

View File

@@ -1,16 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false" <phpunit
backupStaticAttributes="false" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
colors="true" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/4.8/phpunit.xsd"
convertErrorsToExceptions="true" backupGlobals="true"
convertNoticesToExceptions="true" backupStaticAttributes="false"
convertWarningsToExceptions="true" bootstrap="./vendor/autoload.php"
processIsolation="false" cacheTokens="false"
stopOnFailure="false" colors="true"
syntaxCheck="true" convertErrorsToExceptions="true"
bootstrap="./vendor/autoload.php" convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
forceCoversAnnotation="false"
mapTestClassNameToCoveredClassName="false"
processIsolation="false"
stopOnError="false"
stopOnFailure="false"
stopOnIncomplete="false"
stopOnSkipped="false"
stopOnRisky="false"
testSuiteLoaderClass="PHPUnit_Runner_StandardTestSuiteLoader"
timeoutForSmallTests="1"
timeoutForMediumTests="10"
timeoutForLargeTests="60"
verbose="true"
> >
<php>
<ini name="error_reporting" value="-1"/>
</php>
<testsuites> <testsuites>
<testsuite name="Meritoo Package - Main Test Suite"> <testsuite name="Meritoo Package - Main Test Suite">
<directory>./tests/</directory> <directory>./tests/</directory>
@@ -30,6 +48,6 @@
</groups> </groups>
<logging> <logging>
<log type="coverage-html" target="./build/logs/phpunit_coverage/html" /> <log type="coverage-html" target="./build/logs/phpunit_coverage/html"/>
</logging> </logging>
</phpunit> </phpunit>

View File

@@ -18,8 +18,8 @@ use Meritoo\Common\Utilities\Arrays;
* Collection of elements. * Collection of elements.
* It's a set of some elements, e.g. objects. * It's a set of some elements, e.g. objects.
* *
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl> * @author Meritoo <github@meritoo.pl>
* @copyright Meritoo.pl * @copyright Meritoo <http://www.meritoo.pl>
*/ */
class Collection implements Countable, ArrayAccess, IteratorAggregate class Collection implements Countable, ArrayAccess, IteratorAggregate
{ {
@@ -109,7 +109,7 @@ class Collection implements Countable, ArrayAccess, IteratorAggregate
*/ */
public function add($element, $index = null) public function add($element, $index = null)
{ {
if (null === $index) { if (null === $index || '' === $index) {
$this->elements[] = $element; $this->elements[] = $element;
} else { } else {
$this->elements[$index] = $element; $this->elements[$index] = $element;

View File

@@ -15,27 +15,28 @@ use Meritoo\Common\Utilities\Arrays;
/** /**
* An exception used while type of something is unknown * An exception used while type of something is unknown
* *
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl> * @author Meritoo <github@meritoo.pl>
* @copyright Meritoo.pl * @copyright Meritoo <http://www.meritoo.pl>
*/ */
abstract class UnknownTypeException extends Exception abstract class UnknownTypeException extends Exception
{ {
/** /**
* Class constructor * Creates exception
* *
* @param string|int $unknownType The unknown type of something (value of constant) * @param string|int $unknownType The unknown type of something (value of constant)
* @param BaseType $typeInstance An instance of class that contains type of the something * @param BaseType $typeInstance An instance of class that contains type of the something
* @param string $typeName Name of the something * @param string $typeName Name of the something
* @return UnknownTypeException
*/ */
public function __construct($unknownType, BaseType $typeInstance, $typeName) public static function create($unknownType, BaseType $typeInstance, $typeName)
{ {
$allTypes = $typeInstance->getAll();
$types = Arrays::values2string($allTypes, '', ', ');
$template = 'The \'%s\' type of %s is unknown. Probably doesn\'t exist or there is a typo. You should use one' $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, '', ', ');
$message = sprintf(sprintf($template, $unknownType, $typeName, $types)); $message = sprintf(sprintf($template, $unknownType, $typeName, $types));
parent::__construct($message);
return new static($message);
} }
} }

View File

@@ -0,0 +1,36 @@
<?php
/**
* (c) Meritoo.pl, http://www.meritoo.pl
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Meritoo\Common\Exception\Bundle;
use Exception;
/**
* An exception used while name of bundle is incorrect
*
* @author Meritoo <github@meritoo.pl>
* @copyright Meritoo <http://www.meritoo.pl>
*/
class IncorrectBundleNameException extends Exception
{
/**
* Creates exception
*
* @param string $bundleName Incorrect name of bundle
* @return IncorrectBundleNameException
*/
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?';
$message = sprintf($template, $bundleName);
return new static($message);
}
}

View File

@@ -11,21 +11,22 @@ namespace Meritoo\Common\Exception\File;
/** /**
* An exception used while file with given path is empty (has no content) * An exception used while file with given path is empty (has no content)
* *
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl> * @author Meritoo <github@meritoo.pl>
* @copyright Meritoo.pl * @copyright Meritoo <http://www.meritoo.pl>
*/ */
class EmptyFileException extends \Exception class EmptyFileException extends \Exception
{ {
/** /**
* Class constructor * Creates exception
* *
* @param string $emptyFilePath Path of the empty file * @param string $emptyFilePath Path of the empty file
* @return EmptyFileException
*/ */
public function __construct($emptyFilePath) public static function create($emptyFilePath)
{ {
$template = 'File with path \'%s\' is empty (has no content). Did you provide path of proper file?'; $template = 'File with path \'%s\' is empty (has no content). Did you provide path of proper file?';
$message = sprintf($template, $emptyFilePath); $message = sprintf($template, $emptyFilePath);
parent::__construct($message); return new static($message);
} }
} }

View File

@@ -11,16 +11,16 @@ namespace Meritoo\Common\Exception\File;
/** /**
* An exception used while path of given file is empty * An exception used while path of given file is empty
* *
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl> * @author Meritoo <github@meritoo.pl>
* @copyright Meritoo.pl * @copyright Meritoo <http://www.meritoo.pl>
*/ */
class EmptyFilePathException extends \Exception class EmptyFilePathException extends \Exception
{ {
/** /**
* Class constructor * Creates exception
*/ */
public function __construct() public static function create()
{ {
parent::__construct('Path of the file is empty. Did you provide path of proper file?'); return new static('Path of the file is empty. Did you provide path of proper file?');
} }
} }

View File

@@ -11,21 +11,22 @@ namespace Meritoo\Common\Exception\File;
/** /**
* An exception used while file with given path does not exist * An exception used while file with given path does not exist
* *
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl> * @author Meritoo <github@meritoo.pl>
* @copyright Meritoo.pl * @copyright Meritoo <http://www.meritoo.pl>
*/ */
class NotExistingFileException extends \Exception class NotExistingFileException extends \Exception
{ {
/** /**
* Class constructor * Creates exception
* *
* @param string $notExistingFilePath Path of not existing (or not readable) file * @param string $notExistingFilePath Path of not existing (or not readable) file
* @return NotExistingFileException
*/ */
public function __construct($notExistingFilePath) public static function create($notExistingFilePath)
{ {
$template = 'File with path \'%s\' does not exist (or is not readable). Did you provide path of proper file?'; $template = 'File with path \'%s\' does not exist (or is not readable). Did you provide path of proper file?';
$message = sprintf($template, $notExistingFilePath); $message = sprintf($template, $notExistingFilePath);
parent::__construct($message); return new static($message);
} }
} }

View File

@@ -13,18 +13,19 @@ use Exception;
/** /**
* An exception used while method cannot be called, because is disabled * An exception used while method cannot be called, because is disabled
* *
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl> * @author Meritoo <github@meritoo.pl>
* @copyright Meritoo.pl * @copyright Meritoo <http://www.meritoo.pl>
*/ */
class DisabledMethodException extends Exception class DisabledMethodException extends Exception
{ {
/** /**
* Class constructor * Creates exception
* *
* @param string $disabledMethod Name of the disabled method * @param string $disabledMethod Name of the disabled method
* @param string $alternativeMethod (optional) Name of the alternative method * @param string $alternativeMethod (optional) Name of the alternative method
* @return DisabledMethodException
*/ */
public function __construct($disabledMethod, $alternativeMethod = '') public static function create($disabledMethod, $alternativeMethod = '')
{ {
$template = 'Method %s() cannot be called, because is disabled.'; $template = 'Method %s() cannot be called, because is disabled.';
@@ -33,6 +34,7 @@ class DisabledMethodException extends Exception
} }
$message = sprintf($template, $disabledMethod, $alternativeMethod); $message = sprintf($template, $disabledMethod, $alternativeMethod);
parent::__construct($message);
return new static($message);
} }
} }

View File

@@ -13,20 +13,21 @@ use Exception;
/** /**
* An exception used while name of class or trait cannot be resolved * An exception used while name of class or trait cannot be resolved
* *
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl> * @author Meritoo <github@meritoo.pl>
* @copyright Meritoo.pl * @copyright Meritoo <http://www.meritoo.pl>
*/ */
class CannotResolveClassNameException extends Exception class CannotResolveClassNameException extends Exception
{ {
/** /**
* Class constructor * Creates exception
* *
* @param array|object|string $source Source of the class's / trait's name. It can be an array of objects, * @param array|object|string $source Source of the class's / trait's name. It can be an array of objects,
* namespaces, object or namespace. * namespaces, object or namespace.
* @param bool $forClass (optional) If is set to true, message of this exception for class is * @param bool $forClass (optional) If is set to true, message of this exception for class is
* prepared. Otherwise - for trait. * prepared. Otherwise - for trait.
* @return CannotResolveClassNameException
*/ */
public function __construct($source, $forClass = true) public static function create($source, $forClass = true)
{ {
$forWho = 'trait'; $forWho = 'trait';
$value = ''; $value = '';
@@ -42,6 +43,6 @@ class CannotResolveClassNameException extends Exception
$template = 'Name of %s from given \'%s\'%s cannot be resolved. Is there everything ok?'; $template = 'Name of %s from given \'%s\'%s cannot be resolved. Is there everything ok?';
$message = sprintf($template, $forWho, gettype($source), $value); $message = sprintf($template, $forWho, gettype($source), $value);
parent::__construct($message); return new static($message);
} }
} }

View File

@@ -14,18 +14,19 @@ use Meritoo\Common\Utilities\Reflection;
/** /**
* An exception used while given class has no child classes * An exception used while given class has no child classes
* *
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl> * @author Meritoo <github@meritoo.pl>
* @copyright Meritoo.pl * @copyright Meritoo <http://www.meritoo.pl>
*/ */
class MissingChildClassesException extends Exception class MissingChildClassesException extends Exception
{ {
/** /**
* Class constructor * Creates exception
* *
* @param array|object|string $parentClass Class that hasn't child classes, but it should. An array of objects, * @param array|object|string $parentClass Class that hasn't child classes, but it should. An array of objects,
* strings, object or string. * strings, object or string.
* @return MissingChildClassesException
*/ */
public function __construct($parentClass) public static function create($parentClass)
{ {
$template = 'The \'%s\' class requires one child class at least who will extend her (maybe is an abstract' $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?';
@@ -33,6 +34,6 @@ class MissingChildClassesException extends Exception
$parentClassName = Reflection::getClassName($parentClass); $parentClassName = Reflection::getClassName($parentClass);
$message = sprintf($template, $parentClassName); $message = sprintf($template, $parentClassName);
parent::__construct($message); return new static($message);
} }
} }

View File

@@ -0,0 +1,33 @@
<?php
/**
* (c) Meritoo.pl, http://www.meritoo.pl
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Meritoo\Common\Exception\Reflection;
/**
* An exception used while property does not exist in instance of class
*
* @author Meritoo <github@meritoo.pl>
* @copyright Meritoo <http://www.meritoo.pl>
*/
class NotExistingPropertyException extends \Exception
{
/**
* Creates exception
*
* @param mixed $object Object that should contains given property
* @param string $property Name of the property
* @return NotExistingPropertyException
*/
public static function create($object, $property)
{
$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));
return new static($message);
}
}

View File

@@ -14,19 +14,20 @@ use Meritoo\Common\Utilities\Reflection;
/** /**
* An exception used while given class has more than one child class * An exception used while given class has more than one child class
* *
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl> * @author Meritoo <github@meritoo.pl>
* @copyright Meritoo.pl * @copyright Meritoo <http://www.meritoo.pl>
*/ */
class TooManyChildClassesException extends Exception class TooManyChildClassesException extends Exception
{ {
/** /**
* Class constructor * Creates exception
* *
* @param array|object|string $parentClass Class that has more than one child class, but it shouldn't. An array * @param array|object|string $parentClass Class that has more than one child class, but it shouldn't. An array
* of objects, strings, object or string. * of objects, strings, object or string.
* @param array $childClasses Child classes * @param array $childClasses Child classes
* @return TooManyChildClassesException
*/ */
public function __construct($parentClass, array $childClasses) public static function create($parentClass, array $childClasses)
{ {
$template = "The '%s' class requires one child class at most who will extend her, but more than one child" $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?";
@@ -34,6 +35,6 @@ class TooManyChildClassesException extends Exception
$parentClassName = Reflection::getClassName($parentClass); $parentClassName = Reflection::getClassName($parentClass);
$message = sprintf($template, $parentClassName, implode("\n- ", $childClasses), $parentClassName); $message = sprintf($template, $parentClassName, implode("\n- ", $childClasses), $parentClassName);
parent::__construct($message); return new static($message);
} }
} }

View File

@@ -11,22 +11,24 @@ namespace Meritoo\Common\Exception\Regex;
/** /**
* An exception used while length of given hexadecimal value of color is incorrect * An exception used while length of given hexadecimal value of color is incorrect
* *
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl> * @author Meritoo <github@meritoo.pl>
* @copyright Meritoo.pl * @copyright Meritoo <http://www.meritoo.pl>
*/ */
class IncorrectColorHexLengthException extends \Exception class IncorrectColorHexLengthException extends \Exception
{ {
/** /**
* Class constructor * Creates exception
* *
* @param string $color Incorrect hexadecimal value of color * @param string $color Incorrect hexadecimal value of color
* @return IncorrectColorHexLengthException
*/ */
public function __construct($color) 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.' $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)); $message = sprintf($template, $color, strlen($color));
parent::__construct($message);
return new static($message);
} }
} }

View File

@@ -11,19 +11,21 @@ namespace Meritoo\Common\Exception\Regex;
/** /**
* An exception used while given hexadecimal value of color is invalid * An exception used while given hexadecimal value of color is invalid
* *
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl> * @author Meritoo <github@meritoo.pl>
* @copyright Meritoo.pl * @copyright Meritoo <http://www.meritoo.pl>
*/ */
class InvalidColorHexValueException extends \Exception class InvalidColorHexValueException extends \Exception
{ {
/** /**
* Class constructor * Creates exception
* *
* @param string $color Invalid hexadecimal value of color * @param string $color Invalid hexadecimal value of color
* @return InvalidColorHexValueException
*/ */
public function __construct($color) public static function create($color)
{ {
$message = sprintf('Hexadecimal value of color \'%s\' is invalid. Is there everything ok?', $color); $message = sprintf('Hexadecimal value of color \'%s\' is invalid. Is there everything ok?', $color);
parent::__construct($message);
return new static($message);
} }
} }

View File

@@ -0,0 +1,31 @@
<?php
/**
* (c) Meritoo.pl, http://www.meritoo.pl
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Meritoo\Common\Exception\Regex;
/**
* An exception used while html attributes are invalid
*
* @author Meritoo <github@meritoo.pl>
* @copyright Meritoo <http://www.meritoo.pl>
*/
class InvalidHtmlAttributesException extends \Exception
{
/**
* Creates exception
*
* @param string $htmlAttributes Invalid html attributes
* @return InvalidHtmlAttributesException
*/
public static function create($htmlAttributes)
{
$message = sprintf('HTML attributes \'%s\' are invalid. Is there everything ok?', $htmlAttributes);
return new static($message);
}
}

View File

@@ -0,0 +1,31 @@
<?php
/**
* (c) Meritoo.pl, http://www.meritoo.pl
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Meritoo\Common\Exception\Regex;
/**
* An exception used while url is invalid
*
* @author Meritoo <github@meritoo.pl>
* @copyright Meritoo <http://www.meritoo.pl>
*/
class InvalidUrlException extends \Exception
{
/**
* Creates exception
*
* @param string $url Invalid url
* @return InvalidUrlException
*/
public static function create($url)
{
$message = sprintf('Url \'%s\' is invalid. Is there everything ok?', $url);
return new static($message);
}
}

View File

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

View File

@@ -0,0 +1,35 @@
<?php
/**
* (c) Meritoo.pl, http://www.meritoo.pl
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Meritoo\Common\Exception\Type;
use Meritoo\Common\Exception\Base\UnknownTypeException;
use Meritoo\Common\Type\OopVisibilityType;
/**
* An exception used while the visibility of a property, a method or (as of PHP 7.1.0) a constant is unknown
*
* @author Meritoo <github@meritoo.pl>
* @copyright Meritoo <http://www.meritoo.pl>
*/
class UnknownOopVisibilityTypeException extends UnknownTypeException
{
/**
* Creates exception
*
* @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)
{
/* @var UnknownOopVisibilityTypeException $exception */
$exception = parent::create($unknownType, new OopVisibilityType(), 'OOP-related visibility');
return $exception;
}
}

View File

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

View File

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

View File

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

View File

@@ -1,46 +0,0 @@
<?php
/**
* (c) Meritoo.pl, http://www.meritoo.pl
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Meritoo\Common\Utilities;
/**
* Useful methods for bundle
*
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl>
* @copyright Meritoo.pl
*/
class Bundle
{
/**
* Returns path to view / template of given bundle
*
* @param string $viewPath Path of the view / template, e.g. "MyDirectory/my-template"
* @param string $bundleName Name of the bundle, e.g. "MyExtraBundle"
* @param string $extension (optional) Extension of the view / template
* @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
*/
if (empty($viewPath) || empty($bundleName) || empty($extension)) {
return null;
}
/*
* Path of the view / template doesn't end with given extension?
*/
if (!Regex::endsWith($viewPath, $extension)) {
$viewPath = sprintf('%s.%s', $viewPath, $extension);
}
return sprintf('%s:%s', $bundleName, $viewPath);
}
}

View File

@@ -1,109 +0,0 @@
<?php
/**
* (c) Meritoo.pl, http://www.meritoo.pl
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Meritoo\Common\Utilities;
use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\QueryBuilder;
/**
* Useful methods for repository
*
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl>
* @copyright Meritoo.pl
*/
class Repository
{
/**
* Replenishes positions of given items
*
* @param array $items The items
* @param bool $asLast (optional) If is set to true, items are placed at the end. Otherwise - at the top.
* @param bool $force (optional) If is set to true, positions are set even there is no extreme position.
* Otherwise - if extreme position is not found (is null) replenishment is stopped / skipped.
*/
public static function replenishPositions($items, $asLast = true, $force = false)
{
$position = self::getExtremePosition($items, $asLast);
if (null === $position && $force) {
$position = 0;
}
if (null !== $position && !empty($items)) {
foreach ($items as $item) {
if (method_exists($item, 'getPosition')) {
if (null === $item->getPosition()) {
if ($asLast) {
++$position;
} else {
--$position;
}
if (method_exists($item, 'setPosition')) {
$item->setPosition($position);
}
}
}
}
}
}
/**
* Returns extreme position (max or min) of given items
*
* @param array $items The items
* @param bool $max (optional) If is set to true, maximum value is returned. Otherwise - minimum.
* @return int
*/
public static function getExtremePosition($items, $max = true)
{
$extreme = null;
if (!empty($items)) {
foreach ($items as $item) {
if (Reflection::hasMethod($item, 'getPosition')) {
$position = $item->getPosition();
if ($max) {
if ($position > $extreme) {
$extreme = $position;
}
} else {
if ($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';
return $repository
->createQueryBuilder($alias)
->orderBy(sprintf('%s.%s', $alias, $property), $direction);
}
}

View File

@@ -0,0 +1,23 @@
<?php
/**
* (c) Meritoo.pl, http://www.meritoo.pl
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Meritoo\Common\Test\Base;
use Meritoo\Common\Traits\Test\Base\BaseTestCaseTrait;
use PHPUnit\Framework\TestCase;
/**
* Base test case with common methods and data providers
*
* @author Meritoo <github@meritoo.pl>
* @copyright Meritoo <http://www.meritoo.pl>
*/
abstract class BaseTestCase extends TestCase
{
use BaseTestCaseTrait;
}

View File

@@ -0,0 +1,22 @@
<?php
/**
* (c) Meritoo.pl, http://www.meritoo.pl
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Meritoo\Common\Test\Base;
use Meritoo\Common\Traits\Test\Base\BaseTypeTestCaseTrait;
/**
* Base test case for the type of something
*
* @author Meritoo <github@meritoo.pl>
* @copyright Meritoo <http://www.meritoo.pl>
*/
abstract class BaseTypeTestCase extends BaseTestCase
{
use BaseTypeTestCaseTrait;
}

View File

@@ -6,25 +6,34 @@
* file that was distributed with this source code. * file that was distributed with this source code.
*/ */
namespace Meritoo\Common\Test\Base; namespace Meritoo\Common\Traits\Test\Base;
use DateTime; use DateTime;
use Generator; use Generator;
use Meritoo\Common\Exception\Type\UnknownOopVisibilityTypeException; use Meritoo\Common\Exception\Type\UnknownOopVisibilityTypeException;
use Meritoo\Common\Type\OopVisibilityType; use Meritoo\Common\Type\OopVisibilityType;
use Meritoo\Common\Utilities\Miscellaneous; use Meritoo\Common\Utilities\Miscellaneous;
use PHPUnit\Framework\TestCase;
use ReflectionClass; use ReflectionClass;
use ReflectionException;
use ReflectionMethod; use ReflectionMethod;
use stdClass;
/** /**
* Base test case with common methods and data providers * BaseTestCaseTrait
* Created on 2017-11-02
* *
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl> * @author Meritoo <github@meritoo.pl>
* @copyright Meritoo.pl * @copyright Meritoo <http://www.meritoo.pl>
*/ */
abstract class BaseTestCase extends TestCase trait BaseTestCaseTrait
{ {
/**
* Path of directory with data used by test cases
*
* @var string
*/
private static $testsDataDirPath = 'data/tests';
/** /**
* Provides an empty value * Provides an empty value
* *
@@ -96,6 +105,26 @@ abstract class BaseTestCase extends TestCase
yield['surprise/me/one/more/time.txt']; yield['surprise/me/one/more/time.txt'];
} }
/**
* Provides non scalar value, e.g. [] or null
*
* @return Generator
*/
public function provideNonScalarValue()
{
yield[
[],
];
yield[
null,
];
yield[
new stdClass(),
];
}
/** /**
* Returns path of file used by tests. * Returns path of file used by tests.
* It should be placed in /data/tests directory of this project. * It should be placed in /data/tests directory of this project.
@@ -104,13 +133,13 @@ abstract class BaseTestCase extends TestCase
* @param string $directoryPath (optional) Path of directory containing the file * @param string $directoryPath (optional) Path of directory containing the file
* @return string * @return string
*/ */
public function getFilePathToTests($fileName, $directoryPath = '') public function getFilePathForTesting($fileName, $directoryPath = '')
{ {
$rootPath = Miscellaneous::getProjectRootPath(); $rootPath = Miscellaneous::getProjectRootPath();
$paths = [ $paths = [
$rootPath, $rootPath,
'data/tests', self::$testsDataDirPath,
$directoryPath, $directoryPath,
$fileName, $fileName,
]; ];
@@ -130,6 +159,7 @@ abstract class BaseTestCase extends TestCase
* @param int $requiredArgumentsCount (optional) Expected count/amount of required arguments * @param int $requiredArgumentsCount (optional) Expected count/amount of required arguments
* of the verified method * of the verified method
* @throws UnknownOopVisibilityTypeException * @throws UnknownOopVisibilityTypeException
* @throws ReflectionException
* *
* Attention. 2nd argument, the $method, may be: * Attention. 2nd argument, the $method, may be:
* - string - name of the method * - string - name of the method
@@ -186,6 +216,7 @@ abstract class BaseTestCase extends TestCase
* @param int $argumentsCount (optional) Expected count/amount of arguments of the verified method * @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 * @param int $requiredArgumentsCount (optional) Expected count/amount of required arguments of the verified
* method * method
* @throws ReflectionException
* @throws UnknownOopVisibilityTypeException * @throws UnknownOopVisibilityTypeException
*/ */
protected static function assertConstructorVisibilityAndArguments( protected static function assertConstructorVisibilityAndArguments(
@@ -200,13 +231,14 @@ abstract class BaseTestCase extends TestCase
$reflection = new ReflectionClass($classNamespace); $reflection = new ReflectionClass($classNamespace);
$method = $reflection->getConstructor(); $method = $reflection->getConstructor();
return static::assertMethodVisibilityAndArguments($classNamespace, $method, $visibilityType, $argumentsCount, $requiredArgumentsCount); static::assertMethodVisibilityAndArguments($classNamespace, $method, $visibilityType, $argumentsCount, $requiredArgumentsCount);
} }
/** /**
* Asserts that class with given namespace has no constructor * Asserts that class with given namespace has no constructor
* *
* @param string $classNamespace Namespace of class that contains constructor to verify * @param string $classNamespace Namespace of class that contains constructor to verify
* @throws ReflectionException
*/ */
protected static function assertHasNoConstructor($classNamespace) protected static function assertHasNoConstructor($classNamespace)
{ {
@@ -218,4 +250,14 @@ abstract class BaseTestCase extends TestCase
static::assertNull($constructor); static::assertNull($constructor);
} }
/**
* Sets path of directory with data used by test cases
*
* @param string $testsDataDirPath Path of directory with data used by test cases
*/
protected static function setTestsDataDirPath($testsDataDirPath)
{
static::$testsDataDirPath = $testsDataDirPath;
}
} }

View File

@@ -1,17 +1,23 @@
<?php <?php
namespace Meritoo\Common\Test\Base; /**
* (c) Meritoo.pl, http://www.meritoo.pl
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Meritoo\Common\Traits\Test\Base;
use Generator; use Generator;
use Meritoo\Common\Type\Base\BaseType; use Meritoo\Common\Type\Base\BaseType;
/** /**
* Base test case for the type of something * Trait for the base test case for the type of something
* *
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl> * @author Meritoo <github@meritoo.pl>
* @copyright Meritoo.pl * @copyright Meritoo <http://www.meritoo.pl>
*/ */
abstract class BaseTypeTestCase extends BaseTestCase trait BaseTypeTestCaseTrait
{ {
/** /**
* Verifies availability of all types * Verifies availability of all types

View File

@@ -14,8 +14,8 @@ use Meritoo\Common\Utilities\Reflection;
* Base / abstract type of something, e.g. type of button, order, date etc. * Base / abstract type of something, e.g. type of button, order, date etc.
* Child class should contain constants - each of them represent one type. * Child class should contain constants - each of them represent one type.
* *
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl> * @author Meritoo <github@meritoo.pl>
* @copyright Meritoo.pl * @copyright Meritoo <http://www.meritoo.pl>
*/ */
abstract class BaseType abstract class BaseType
{ {

View File

@@ -13,8 +13,8 @@ use Meritoo\Common\Type\Base\BaseType;
/** /**
* Type of date part, e.g. "year" * Type of date part, e.g. "year"
* *
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl> * @author Meritoo <github@meritoo.pl>
* @copyright Meritoo.pl * @copyright Meritoo <http://www.meritoo.pl>
*/ */
class DatePartType extends BaseType class DatePartType extends BaseType
{ {

View File

@@ -6,18 +6,20 @@
* file that was distributed with this source code. * file that was distributed with this source code.
*/ */
namespace Meritoo\Common\Utilities; namespace Meritoo\Common\Type;
use DateTime; use DateTime;
use Meritoo\Common\Type\Base\BaseType;
use Meritoo\Common\Utilities\Date;
/** /**
* A date's period. * A date's period.
* Contains start and end date of the period. * Contains start and end date of the period.
* *
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl> * @author Meritoo <github@meritoo.pl>
* @copyright Meritoo.pl * @copyright Meritoo <http://www.meritoo.pl>
*/ */
class DatePeriod class DatePeriod extends BaseType
{ {
/** /**
* The period constant: last month * The period constant: last month
@@ -108,17 +110,6 @@ class DatePeriod
$this->endDate = $endDate; $this->endDate = $endDate;
} }
/**
* Returns information if given period is correct
*
* @param int $period The period to verify
* @return bool
*/
public static function isCorrectPeriod($period)
{
return in_array($period, Reflection::getConstants(__CLASS__));
}
/** /**
* Returns formatted one of the period's date: start date or end date * Returns formatted one of the period's date: start date or end date
* *

View File

@@ -7,8 +7,8 @@ use Meritoo\Common\Type\Base\BaseType;
/** /**
* The visibility of a property, a method or (as of PHP 7.1.0) a constant * The visibility of a property, a method or (as of PHP 7.1.0) a constant
* *
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl> * @author Meritoo <github@meritoo.pl>
* @copyright Meritoo.pl * @copyright Meritoo <http://www.meritoo.pl>
* *
* @see http://php.net/manual/en/language.oop5.visibility.php * @see http://php.net/manual/en/language.oop5.visibility.php
*/ */

View File

@@ -11,8 +11,8 @@ namespace Meritoo\Common\Utilities;
/** /**
* Useful arrays methods * Useful arrays methods
* *
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl> * @author Meritoo <github@meritoo.pl>
* @copyright Meritoo.pl * @copyright Meritoo <http://www.meritoo.pl>
*/ */
class Arrays class Arrays
{ {
@@ -48,23 +48,6 @@ class Arrays
if (is_array($value)) { if (is_array($value)) {
$effect .= self::values2string($value, $arrayColumnKey, $separator); $effect .= self::values2string($value, $arrayColumnKey, $separator);
/*
* Previous version. Doesn't work with array containing arrays, e.g.:
* array(
* 1 => array(
* 'item1',
* 'item2'
* ),
* 2 => array(
* 'item3',
* 'item4'
* )
* )
*
if(isset($value[$arrayColumnKey])){
$effect .= $value[$arrayColumnKey];
}
*/
} else { } else {
if (empty($arrayColumnKey)) { if (empty($arrayColumnKey)) {
$effect .= $value; $effect .= $value;
@@ -530,6 +513,10 @@ class Arrays
*/ */
public static function removeElement(array $array, $item) 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)) { if (empty($array) || !in_array($item, $array)) {
return false; return false;
} }
@@ -626,6 +613,10 @@ class Arrays
*/ */
public static function setKeysAsValues(array $array, $ignoreDuplicatedValues = true) public static function setKeysAsValues(array $array, $ignoreDuplicatedValues = true)
{ {
/*
* No elements?
* Nothing to do
*/
if (empty($array)) { if (empty($array)) {
return []; return [];
} }
@@ -682,7 +673,7 @@ class Arrays
return null; return null;
} }
$effect = $array; $effect = &$array;
ksort($effect, $sortFlags); ksort($effect, $sortFlags);
foreach ($effect as &$value) { foreach ($effect as &$value) {
@@ -831,60 +822,66 @@ class Arrays
*/ */
public static function getLastElementsPaths(array $array, $separator = '.', $parentPath = '', $stopIfMatchedBy = '') public static function getLastElementsPaths(array $array, $separator = '.', $parentPath = '', $stopIfMatchedBy = '')
{ {
/*
* No elements?
* Nothing to do
*/
if (empty($array)) {
return [];
}
if (!empty($stopIfMatchedBy)) {
$stopIfMatchedBy = self::makeArray($stopIfMatchedBy);
}
$paths = []; $paths = [];
if (!empty($array)) { foreach ($array as $key => $value) {
if (!empty($stopIfMatchedBy)) { $path = $key;
$stopIfMatchedBy = self::makeArray($stopIfMatchedBy); $stopRecursion = false;
/*
* If the path of parent element is delivered,
* I have to use it and build longer path
*/
if (!empty($parentPath)) {
$pathTemplate = '%s%s%s';
$path = sprintf($pathTemplate, $parentPath, $separator, $key);
} }
foreach ($array as $key => $value) { /*
$path = $key; * Check if the key or current path matches one of patterns at which the process should be stopped,
$stopRecursion = false; * the recursive not used. It means that I have to pass current value and stop processing of the
* array (don't go to the next step).
*/
if (!empty($stopIfMatchedBy)) {
foreach ($stopIfMatchedBy as $rawPattern) {
$pattern = sprintf('|%s|', $rawPattern);
/* if (preg_match($pattern, $key) || preg_match($pattern, $path)) {
* If the path of parent element is delivered, $stopRecursion = true;
* I have to use it and build longer path break;
*/
if (!empty($parentPath)) {
$pathTemplate = '%s%s%s';
$path = sprintf($pathTemplate, $parentPath, $separator, $key);
}
/*
* Check if the key or current path matches one of patterns at which the process should be stopped,
* the recursive not used. It means that I have to pass current value and stop processing of the
* array (don't go to the next step).
*/
if (!empty($stopIfMatchedBy)) {
foreach ($stopIfMatchedBy as $rawPattern) {
$pattern = sprintf('|%s|', $rawPattern);
if (preg_match($pattern, $key) || preg_match($pattern, $path)) {
$stopRecursion = true;
break;
}
} }
} }
}
/* /*
* The value is passed to the returned array if: * The value is passed to the returned array if:
* - it's not an array * - it's not an array
* or * or
* - the process is stopped, recursive is not used * - the process is stopped, recursive is not used
*/ */
if (!is_array($value) || (is_array($value) && empty($value)) || $stopRecursion) { if (!is_array($value) || (is_array($value) && empty($value)) || $stopRecursion) {
$paths[$path] = $value; $paths[$path] = $value;
continue; continue;
} }
/* /*
* Let's iterate through the next level, using recursive * Let's iterate through the next level, using recursive
*/ */
if (is_array($value)) { if (is_array($value)) {
$recursivePaths = self::getLastElementsPaths($value, $separator, $path, $stopIfMatchedBy); $recursivePaths = self::getLastElementsPaths($value, $separator, $path, $stopIfMatchedBy);
$paths += $recursivePaths; $paths += $recursivePaths;
}
} }
} }
@@ -1083,6 +1080,10 @@ class Arrays
*/ */
public static function getAllValuesOfKey(array $array, $key) public static function getAllValuesOfKey(array $array, $key)
{ {
/*
* No elements?
* Nothing to do
*/
if (empty($array)) { if (empty($array)) {
return null; return null;
} }

89
src/Utilities/Bundle.php Normal file
View File

@@ -0,0 +1,89 @@
<?php
/**
* (c) Meritoo.pl, http://www.meritoo.pl
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Meritoo\Common\Utilities;
use Meritoo\Common\Exception\Bundle\IncorrectBundleNameException;
/**
* Useful methods for bundle
*
* @author Meritoo <github@meritoo.pl>
* @copyright Meritoo <http://www.meritoo.pl>
*/
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 $bundleName Full name of the bundle, e.g. "MyExtraBundle"
* @param string $extension (optional) Extension of the view / template (default: "html.twig")
* @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
*/
if (empty($viewPath) || empty($bundleName) || empty($extension)) {
return null;
}
/*
* 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?
*/
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);
return sprintf('@%s/%s', $shortBundleName, $viewPath);
}
/**
* Returns short name of bundle (without "Bundle")
*
* @param string $fullBundleName Full name of the bundle, e.g. "MyExtraBundle"
* @throws IncorrectBundleNameException
* @return string|null
*/
public static function getShortBundleName($fullBundleName)
{
/*
* Given name of bundle is invalid?
*/
if (!Regex::isValidBundleName($fullBundleName)) {
if (!is_string($fullBundleName)) {
$fullBundleName = gettype($fullBundleName);
}
throw new IncorrectBundleNameException($fullBundleName);
}
$matches = [];
$pattern = Regex::getBundleNamePattern();
preg_match($pattern, $fullBundleName, $matches);
return $matches[1];
}
}

View File

@@ -13,8 +13,8 @@ use stdClass;
/** /**
* Useful Composer-related methods (only static functions) * Useful Composer-related methods (only static functions)
* *
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl> * @author Meritoo <github@meritoo.pl>
* @copyright Meritoo.pl * @copyright Meritoo <http://www.meritoo.pl>
*/ */
class Composer class Composer
{ {

View File

@@ -10,14 +10,16 @@ namespace Meritoo\Common\Utilities;
use DateInterval; use DateInterval;
use DateTime; use DateTime;
use Meritoo\Common\Exception\Date\UnknownDatePartTypeException; use Exception;
use Meritoo\Common\Exception\Type\UnknownDatePartTypeException;
use Meritoo\Common\Type\DatePartType; use Meritoo\Common\Type\DatePartType;
use Meritoo\Common\Type\DatePeriod;
/** /**
* Useful date methods * Useful date methods
* *
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl> * @author Meritoo <github@meritoo.pl>
* @copyright Meritoo.pl * @copyright Meritoo <http://www.meritoo.pl>
*/ */
class Date class Date
{ {
@@ -66,97 +68,106 @@ class Date
* The dates are returned in an array with indexes 'start' and 'end'. * The dates are returned in an array with indexes 'start' and 'end'.
* *
* @param int $period The period, type of period. One of DatePeriod class constants, e.g. DatePeriod::LAST_WEEK. * @param int $period The period, type of period. One of DatePeriod class constants, e.g. DatePeriod::LAST_WEEK.
* @return DatePeriod * @throws Exception
* @return null|DatePeriod
*/ */
public static function getDatesForPeriod($period) public static function getDatesForPeriod($period)
{ {
$datePeriod = null; /*
* Type of period is incorrect?
if (DatePeriod::isCorrectPeriod($period)) { * Nothing to do
$dateStart = null; */
$dateEnd = null; if (!(new DatePeriod())->isCorrectType($period)) {
return null;
switch ($period) {
case DatePeriod::LAST_WEEK:
$thisWeekStart = new DateTime('this week');
$dateStart = clone $thisWeekStart;
$dateEnd = clone $thisWeekStart;
$dateStart->sub(new DateInterval('P7D'));
$dateEnd->sub(new DateInterval('P1D'));
break;
case DatePeriod::THIS_WEEK:
$dateStart = new DateTime('this week');
$dateEnd = clone $dateStart;
$dateEnd->add(new DateInterval('P6D'));
break;
case DatePeriod::NEXT_WEEK:
$dateStart = new DateTime('this week');
$dateStart->add(new DateInterval('P7D'));
$dateEnd = clone $dateStart;
$dateEnd->add(new DateInterval('P6D'));
break;
case DatePeriod::LAST_MONTH:
$dateStart = new DateTime('first day of last month');
$dateEnd = new DateTime('last day of last month');
break;
case DatePeriod::THIS_MONTH:
$lastMonth = self::getDatesForPeriod(DatePeriod::LAST_MONTH);
$nextMonth = self::getDatesForPeriod(DatePeriod::NEXT_MONTH);
$dateStart = $lastMonth->getEndDate();
$dateStart->add(new DateInterval('P1D'));
$dateEnd = $nextMonth->getStartDate();
$dateEnd->sub(new DateInterval('P1D'));
break;
case DatePeriod::NEXT_MONTH:
$dateStart = new DateTime('first day of next month');
$dateEnd = new DateTime('last day of next month');
break;
case DatePeriod::LAST_YEAR:
case DatePeriod::THIS_YEAR:
case DatePeriod::NEXT_YEAR:
$dateStart = new DateTime();
$dateEnd = new DateTime();
if (DatePeriod::LAST_YEAR == $period || DatePeriod::NEXT_YEAR == $period) {
$yearDifference = 1;
if (DatePeriod::LAST_YEAR == $period) {
$yearDifference *= -1;
}
$modifyString = sprintf('%s year', $yearDifference);
$dateStart->modify($modifyString);
$dateEnd->modify($modifyString);
}
$year = $dateStart->format('Y');
$dateStart->setDate($year, 1, 1);
$dateEnd->setDate($year, 12, 31);
break;
}
if (null !== $dateStart && null !== $dateEnd) {
$dateStart->setTime(0, 0, 0);
$dateEnd->setTime(23, 59, 59);
$datePeriod = new DatePeriod($dateStart, $dateEnd);
}
} }
return $datePeriod; $dateStart = null;
$dateEnd = null;
switch ($period) {
case DatePeriod::LAST_WEEK:
$thisWeekStart = new DateTime('this week');
$dateStart = clone $thisWeekStart;
$dateEnd = clone $thisWeekStart;
$dateStart->sub(new DateInterval('P7D'));
$dateEnd->sub(new DateInterval('P1D'));
break;
case DatePeriod::THIS_WEEK:
$dateStart = new DateTime('this week');
$dateEnd = clone $dateStart;
$dateEnd->add(new DateInterval('P6D'));
break;
case DatePeriod::NEXT_WEEK:
$dateStart = new DateTime('this week');
$dateStart->add(new DateInterval('P7D'));
$dateEnd = clone $dateStart;
$dateEnd->add(new DateInterval('P6D'));
break;
case DatePeriod::LAST_MONTH:
$dateStart = new DateTime('first day of last month');
$dateEnd = new DateTime('last day of last month');
break;
case DatePeriod::THIS_MONTH:
$lastMonth = self::getDatesForPeriod(DatePeriod::LAST_MONTH);
$nextMonth = self::getDatesForPeriod(DatePeriod::NEXT_MONTH);
$dateStart = $lastMonth->getEndDate();
$dateStart->add(new DateInterval('P1D'));
$dateEnd = $nextMonth->getStartDate();
$dateEnd->sub(new DateInterval('P1D'));
break;
case DatePeriod::NEXT_MONTH:
$dateStart = new DateTime('first day of next month');
$dateEnd = new DateTime('last day of next month');
break;
case DatePeriod::LAST_YEAR:
case DatePeriod::THIS_YEAR:
case DatePeriod::NEXT_YEAR:
$dateStart = new DateTime();
$dateEnd = new DateTime();
if (DatePeriod::LAST_YEAR == $period || DatePeriod::NEXT_YEAR == $period) {
$yearDifference = 1;
if (DatePeriod::LAST_YEAR == $period) {
$yearDifference *= -1;
}
$modifyString = sprintf('%s year', $yearDifference);
$dateStart->modify($modifyString);
$dateEnd->modify($modifyString);
}
$year = $dateStart->format('Y');
$dateStart->setDate($year, 1, 1);
$dateEnd->setDate($year, 12, 31);
break;
}
/*
* Start or end date is unknown?
* Nothing to do
*/
if (null === $dateStart || null === $dateEnd) {
return null;
}
$dateStart->setTime(0, 0, 0);
$dateEnd->setTime(23, 59, 59);
return new DatePeriod($dateStart, $dateEnd);
} }
/** /**
@@ -209,6 +220,7 @@ class Date
/** /**
* Returns current day of week * Returns current day of week
* *
* @throws UnknownDatePartTypeException
* @return int * @return int
*/ */
public static function getCurrentDayOfWeek() public static function getCurrentDayOfWeek()
@@ -230,8 +242,8 @@ class Date
* @param int $month The month value * @param int $month The month value
* @param int $day The day value * @param int $day The day value
* *
* @return int
* @throws UnknownDatePartTypeException * @throws UnknownDatePartTypeException
* @return int
*/ */
public static function getDayOfWeek($year, $month, $day) public static function getDayOfWeek($year, $month, $day)
{ {
@@ -243,21 +255,21 @@ class Date
* Oops, incorrect year * Oops, incorrect year
*/ */
if ($year <= 0) { if ($year <= 0) {
throw new UnknownDatePartTypeException(DatePartType::YEAR, $year); throw UnknownDatePartTypeException::createException(DatePartType::YEAR, $year);
} }
/* /*
* Oops, incorrect month * Oops, incorrect month
*/ */
if ($month < 1 || $month > 12) { if ($month < 1 || $month > 12) {
throw new UnknownDatePartTypeException(DatePartType::MONTH, $month); throw UnknownDatePartTypeException::createException(DatePartType::MONTH, $month);
} }
/* /*
* Oops, incorrect day * Oops, incorrect day
*/ */
if ($day < 1 || $day > 31) { if ($day < 1 || $day > 31) {
throw new UnknownDatePartTypeException(DatePartType::DAY, $day); throw UnknownDatePartTypeException::createException(DatePartType::DAY, $day);
} }
if ($month < 3) { if ($month < 3) {
@@ -475,6 +487,7 @@ class Date
* @param string $intervalTemplate (optional) Template used to build date interval. It should contain "%d" as the * @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. * placeholder which is replaced with a number that represents each iteration.
* Default: interval for days. * Default: interval for days.
* @throws Exception
* @return array * @return array
*/ */
public static function getDatesCollection(DateTime $startDate, $datesCount, $intervalTemplate = 'P%dD') public static function getDatesCollection(DateTime $startDate, $datesCount, $intervalTemplate = 'P%dD')
@@ -520,6 +533,7 @@ class Date
* @param int $end (optional) End of random partition * @param int $end (optional) End of random partition
* @param string $intervalTemplate (optional) Template used to build date interval. The placeholder is replaced * @param string $intervalTemplate (optional) Template used to build date interval. The placeholder is replaced
* with next, iterated value. * with next, iterated value.
* @throws Exception
* @return DateTime * @return DateTime
*/ */
public static function getRandomDate(DateTime $startDate = null, $start = 1, $end = 100, $intervalTemplate = 'P%sD') public static function getRandomDate(DateTime $startDate = null, $start = 1, $end = 100, $intervalTemplate = 'P%sD')

View File

@@ -13,8 +13,8 @@ use Generator;
/** /**
* Useful methods for the Generator class (only static functions) * Useful methods for the Generator class (only static functions)
* *
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl> * @author Meritoo <github@meritoo.pl>
* @copyright Meritoo.pl * @copyright Meritoo <http://www.meritoo.pl>
*/ */
class GeneratorUtility class GeneratorUtility
{ {

View File

@@ -11,8 +11,8 @@ namespace Meritoo\Common\Utilities;
/** /**
* Useful locale methods * Useful locale methods
* *
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl> * @author Meritoo <github@meritoo.pl>
* @copyright Meritoo.pl * @copyright Meritoo <http://www.meritoo.pl>
*/ */
class Locale class Locale
{ {
@@ -23,7 +23,7 @@ class Locale
* setting. It's the same constant as required by setlocale() function. * 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 $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" * @param string $countryCode (optional) Country code, in ISO 3166-1 alpha-2 format, e.g. "FR"
* @return bool * @return false|string
* *
* Available categories (values of $category argument): * Available categories (values of $category argument):
* - LC_ALL for all of the below * - LC_ALL for all of the below
@@ -57,9 +57,29 @@ class Locale
} }
$localeLongForm = self::getLongForm($languageCode, $countryCode); $localeLongForm = self::getLongForm($languageCode, $countryCode);
setlocale($category, $localeLongForm);
return true; return setlocale($category, $localeLongForm);
}
/**
* Returns locale for given category
*
* @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.
* @return 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 getLocale($category)
{
return setlocale($category, '0');
} }
/** /**

View File

@@ -11,8 +11,8 @@ namespace Meritoo\Common\Utilities;
/** /**
* Useful methods for mime types of files * Useful methods for mime types of files
* *
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl> * @author Meritoo <github@meritoo.pl>
* @copyright Meritoo.pl * @copyright Meritoo <http://www.meritoo.pl>
*/ */
class MimeTypes class MimeTypes
{ {
@@ -759,9 +759,8 @@ class MimeTypes
* Returns mime type of given file * Returns mime type of given file
* *
* @param string $filePath Path of the file to check * @param string $filePath Path of the file to check
* @return string
*
* @throws \RuntimeException * @throws \RuntimeException
* @return string
*/ */
public static function getMimeType($filePath) public static function getMimeType($filePath)
{ {

View File

@@ -9,14 +9,15 @@
namespace Meritoo\Common\Utilities; namespace Meritoo\Common\Utilities;
use Gedmo\Sluggable\Util\Urlizer; use Gedmo\Sluggable\Util\Urlizer;
use Symfony\Component\HttpFoundation\Cookie; use Meritoo\Common\Exception\Regex\IncorrectColorHexLengthException;
use Meritoo\Common\Exception\Regex\InvalidColorHexValueException;
use Transliterator; use Transliterator;
/** /**
* Miscellaneous methods (only static functions) * Miscellaneous methods (only static functions)
* *
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl> * @author Meritoo <github@meritoo.pl>
* @copyright Meritoo.pl * @copyright Meritoo <http://www.meritoo.pl>
*/ */
class Miscellaneous class Miscellaneous
{ {
@@ -626,10 +627,10 @@ class Miscellaneous
* Breaks long text * Breaks long text
* *
* @param string $text The text to check and break * @param string $text The text to check and break
* @param int $perLine (optional) Characters count per line * @param int $perLine (optional) Characters count per line. Default: 100.
* @param string $separator (optional) Separator that is placed beetwen lines * @param string $separator (optional) Separator that is placed between lines. Default: "<br>".
* @param string $encoding (optional) Character encoding. Used by mb_substr(). * @param string $encoding (optional) Character encoding. Used by mb_substr(). Default: "UTF-8".
* @param int $proportionalAberration (optional) Proportional aberration for chars (percent value) * @param int $proportionalAberration (optional) Proportional aberration for chars (percent value). Default: 20.
* @return string * @return string
*/ */
public static function breakLongText( public static function breakLongText(
@@ -716,15 +717,23 @@ class Miscellaneous
* *
* @param string $directoryPath Directory path * @param string $directoryPath Directory path
* @param bool $contentOnly (optional) If is set to true, only content of the directory is removed, not * @param bool $contentOnly (optional) If is set to true, only content of the directory is removed, not
* directory. Otherwise - directory is removed too. * directory itself. Otherwise - directory is removed too (default behaviour).
* @return bool * @return bool|null
*/ */
public static function removeDirectory($directoryPath, $contentOnly = false) public static function removeDirectory($directoryPath, $contentOnly = false)
{ {
/*
* Directory does not exist?
* Nothing to do
*/
if (!file_exists($directoryPath)) { if (!file_exists($directoryPath)) {
return true; return null;
} }
/*
* It's not a directory?
* Let's treat it like file
*/
if (!is_dir($directoryPath)) { if (!is_dir($directoryPath)) {
return unlink($directoryPath); return unlink($directoryPath);
} }
@@ -739,6 +748,9 @@ class Miscellaneous
} }
} }
/*
* Directory should be removed too?
*/
if (!$contentOnly) { if (!$contentOnly) {
return rmdir($directoryPath); return rmdir($directoryPath);
} }
@@ -1192,138 +1204,6 @@ class Miscellaneous
return $value; return $value;
} }
/**
* Returns a CURL response with parsed HTTP headers as array with "headers", "cookies" and "content" keys
*
* The headers and cookies are parsed and returned as an array, and an array of Cookie objects. Returned array looks
* like this example:
* <code>
* [
* 'headers' => [
* 'Content-Type' => 'text/html; charset=UTF-8',
* ...
* ],
* 'cookies' => [
* new Symfony\Component\HttpFoundation\Cookie(),
* new Symfony\Component\HttpFoundation\Cookie(),
* ...
* ],
* 'content' => '<html>...</html>'
* ]
* </code>
*
* If you want to attach HTTP headers into response content by CURL you need to set "CURLOPT_HEADER" option
* to "true". To read exact length of HTTP headers from CURL you can use "curl_getinfo()" function
* and read "CURLINFO_HEADER_SIZE" option.
*
* @param string $response the full content of response, including HTTP headers
* @param int $headerSize The length of HTTP headers in content
* @return array
*/
public static function getCurlResponseWithHeaders($response, $headerSize)
{
$headerContent = mb_substr($response, 0, $headerSize);
$content = mb_substr($response, $headerSize);
$headers = [];
$cookies = [];
/*
* Let's transform headers content into two arrays: headers and cookies
*/
foreach (explode("\r\n", $headerContent) as $i => $line) {
/*
* First line is only HTTP status and is unneeded so skip it
*/
if (0 === $i) {
continue;
}
if (Regex::contains($line, ':')) {
list($key, $value) = explode(': ', $line);
/*
* If the header is a "set-cookie" let's save it to "cookies" array
*/
if ('Set-Cookie' === $key) {
$cookieParameters = explode(';', $value);
$name = '';
$value = '';
$expire = 0;
$path = '/';
$domain = null;
$secure = false;
$httpOnly = true;
foreach ($cookieParameters as $j => $parameter) {
$param = explode('=', $parameter);
/*
* First parameter will be always a cookie name and it's value. It is not needed to run
* further actions for them, so save the values and move to next parameter.
*/
if (0 === $j) {
$name = trim($param[0]);
$value = trim($param[1]);
continue;
}
/*
* Now there would be the rest of cookie parameters, names of params are sent different way so
* I need to lowercase the names and remove unneeded spaces.
*/
$paramName = mb_strtolower(trim($param[0]));
$paramValue = true;
/*
* Some parameters don't have value e.g. "secure", but the value for them if they're specified
* is "true". Otherwise - just read a value for parameter if exists.
*/
if (array_key_exists(1, $param)) {
$paramValue = trim($param[1]);
}
switch ($paramName) {
case 'expires':
$expire = $paramValue;
break;
case 'path':
$path = $paramValue;
break;
case 'domain':
$domain = $paramValue;
break;
case 'secure':
$secure = $paramValue;
break;
case 'httponly':
$httpOnly = $paramValue;
break;
}
}
/*
* Create new Cookie object and add it to "cookies" array.
* I must skip to next header as cookies shouldn't be saved in "headers" array.
*/
$cookies[] = new Cookie($name, $value, $expire, $path, $domain, $secure, $httpOnly);
continue;
}
/*
* Save response header which is not a cookie
*/
$headers[$key] = $value;
}
}
return [
'headers' => $headers,
'cookies' => $cookies,
'content' => $content,
];
}
/** /**
* Adds missing the "0" characters to given number until given length is reached * Adds missing the "0" characters to given number until given length is reached
* *
@@ -1432,6 +1312,8 @@ class Miscellaneous
* Returns inverted value of color for given color * 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" * @param string $color Hexadecimal value of color to invert (with or without hash), e.g. "dd244c" or "#22a5fe"
* @throws IncorrectColorHexLengthException
* @throws InvalidColorHexValueException
* @return string * @return string
*/ */
public static function getInvertedColor($color) public static function getInvertedColor($color)

View File

@@ -10,6 +10,7 @@ namespace Meritoo\Common\Utilities;
use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\EntityManager; use Doctrine\ORM\EntityManager;
use Doctrine\ORM\OptimisticLockException;
use Doctrine\ORM\Query\Expr\Join; use Doctrine\ORM\Query\Expr\Join;
use Doctrine\ORM\Query\Parameter; use Doctrine\ORM\Query\Parameter;
use Doctrine\ORM\QueryBuilder; use Doctrine\ORM\QueryBuilder;
@@ -17,8 +18,8 @@ use Doctrine\ORM\QueryBuilder;
/** /**
* Useful methods for query builder (the Doctrine's QueryBuilder class) * Useful methods for query builder (the Doctrine's QueryBuilder class)
* *
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl> * @author Meritoo <github@meritoo.pl>
* @copyright Meritoo.pl * @copyright Meritoo <http://www.meritoo.pl>
*/ */
class QueryBuilderUtility class QueryBuilderUtility
{ {
@@ -33,6 +34,10 @@ class QueryBuilderUtility
{ {
$aliases = $queryBuilder->getRootAliases(); $aliases = $queryBuilder->getRootAliases();
/*
* No aliases?
* Nothing to do
*/
if (empty($aliases)) { if (empty($aliases)) {
return null; return null;
} }
@@ -42,7 +47,8 @@ class QueryBuilderUtility
/** /**
* Returns alias of given property joined in given query builder * Returns alias of given property joined in given query builder
* If the join does not exist, null is returned. *
* If there are no joins or the join does not exist, null is returned.
* It's also information if given property is already joined in given query builder. * It's also information if given property is already joined in given query builder.
* *
* @param QueryBuilder $queryBuilder The query builder to verify * @param QueryBuilder $queryBuilder The query builder to verify
@@ -53,6 +59,10 @@ class QueryBuilderUtility
{ {
$joins = $queryBuilder->getDQLPart('join'); $joins = $queryBuilder->getDQLPart('join');
/*
* No joins?
* Nothing to do
*/
if (empty($joins)) { if (empty($joins)) {
return null; return null;
} }
@@ -99,33 +109,43 @@ class QueryBuilderUtility
*/ */
public static function setCriteria(QueryBuilder $queryBuilder, array $criteria = [], $alias = '') public static function setCriteria(QueryBuilder $queryBuilder, array $criteria = [], $alias = '')
{ {
if (!empty($criteria)) { /*
if (empty($alias)) { * No criteria used in WHERE clause?
$alias = self::getRootAlias($queryBuilder); * Nothing to do
} */
if (empty($criteria)) {
return $queryBuilder;
}
foreach ($criteria as $column => $value) { /*
$compareOperator = '='; * No alias provided?
* Let's use root alias
*/
if (empty($alias)) {
$alias = self::getRootAlias($queryBuilder);
}
if (is_array($value) && !empty($value)) { foreach ($criteria as $column => $value) {
if (2 == count($value)) { $compareOperator = '=';
$compareOperator = $value[1];
}
$value = $value[0]; if (is_array($value) && !empty($value)) {
if (2 == count($value)) {
$compareOperator = $value[1];
} }
$predicate = sprintf('%s.%s %s :%s', $alias, $column, $compareOperator, $column); $value = $value[0];
if (null === $value) {
$predicate = $queryBuilder->expr()->isNull(sprintf('%s.%s', $alias, $column));
unset($criteria[$column]);
} else {
$queryBuilder->setParameter($column, $value);
}
$queryBuilder = $queryBuilder->andWhere($predicate);
} }
$predicate = sprintf('%s.%s %s :%s', $alias, $column, $compareOperator, $column);
if (null === $value) {
$predicate = $queryBuilder->expr()->isNull(sprintf('%s.%s', $alias, $column));
unset($criteria[$column]);
} else {
$queryBuilder->setParameter($column, $value);
}
$queryBuilder = $queryBuilder->andWhere($predicate);
} }
return $queryBuilder; return $queryBuilder;
@@ -136,14 +156,15 @@ class QueryBuilderUtility
* *
* @param EntityManager $entityManager The entity manager * @param EntityManager $entityManager The entity manager
* @param array|ArrayCollection $entities The entities to delete * @param array|ArrayCollection $entities The entities to delete
* @param bool $flushDeleted (optional) If is set to true, flushes the deleted objects. * @param bool $flushDeleted (optional) If is set to true, flushes the deleted objects (default
* Otherwise - not. * behaviour). Otherwise - not.
* @throws OptimisticLockException
* @return bool * @return bool
*/ */
public static function deleteEntities(EntityManager $entityManager, $entities, $flushDeleted = true) public static function deleteEntities(EntityManager $entityManager, $entities, $flushDeleted = true)
{ {
/* /*
* No entities found? * No entities provided?
* Nothing to do * Nothing to do
*/ */
if (empty($entities)) { if (empty($entities)) {
@@ -169,24 +190,30 @@ class QueryBuilderUtility
* Attention. Existing parameters will be overridden. * Attention. Existing parameters will be overridden.
* *
* @param QueryBuilder $queryBuilder The query builder * @param QueryBuilder $queryBuilder The query builder
* @param array|ArrayCollection $parameters Parameters to add. Collection of instances of * @param array|ArrayCollection $parameters Parameters to add. Collection of Doctrine\ORM\Query\Parameter
* Doctrine\ORM\Query\Parameter class or an array with key-value pairs. * instances or an array with key-value pairs.
* @return QueryBuilder * @return QueryBuilder
*/ */
public static function addParameters(QueryBuilder $queryBuilder, $parameters) public static function addParameters(QueryBuilder $queryBuilder, $parameters)
{ {
if (!empty($parameters)) { /*
foreach ($parameters as $key => $parameter) { * No parameters?
$name = $key; * Nothing to do
$value = $parameter; */
if (empty($parameters)) {
return $queryBuilder;
}
if ($parameter instanceof Parameter) { foreach ($parameters as $key => $parameter) {
$name = $parameter->getName(); $name = $key;
$value = $parameter->getValue(); $value = $parameter;
}
$queryBuilder->setParameter($name, $value); if ($parameter instanceof Parameter) {
$name = $parameter->getName();
$value = $parameter->getValue();
} }
$queryBuilder->setParameter($name, $value);
} }
return $queryBuilder; return $queryBuilder;

View File

@@ -8,23 +8,19 @@
namespace Meritoo\Common\Utilities; namespace Meritoo\Common\Utilities;
use Doctrine\Common\Collections\Collection;
use Doctrine\Common\Util\ClassUtils; use Doctrine\Common\Util\ClassUtils;
use Doctrine\Common\Util\Inflector; use Doctrine\Common\Util\Inflector;
use Meritoo\Common\Collection\Collection;
use Meritoo\Common\Exception\Reflection\CannotResolveClassNameException; use Meritoo\Common\Exception\Reflection\CannotResolveClassNameException;
use Meritoo\Common\Exception\Reflection\MissingChildClassesException; use Meritoo\Common\Exception\Reflection\MissingChildClassesException;
use Meritoo\Common\Exception\Reflection\NotExistingPropertyException;
use Meritoo\Common\Exception\Reflection\TooManyChildClassesException; use Meritoo\Common\Exception\Reflection\TooManyChildClassesException;
use ReflectionClass;
use ReflectionException;
use ReflectionMethod;
use ReflectionObject;
use ReflectionProperty;
/** /**
* Useful reflection methods * Useful reflection methods
* *
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl> * @author Meritoo <github@meritoo.pl>
* @copyright Meritoo.pl * @copyright Meritoo <http://www.meritoo.pl>
*/ */
class Reflection class Reflection
{ {
@@ -40,14 +36,14 @@ class Reflection
{ {
$effect = []; $effect = [];
$reflection = new ReflectionClass($class); $reflection = new \ReflectionClass($class);
$methods = $reflection->getMethods(); $methods = $reflection->getMethods();
if (!empty($methods)) { if (!empty($methods)) {
$className = self::getClassName($class); $className = self::getClassName($class);
foreach ($methods as $method) { foreach ($methods as $method) {
if ($method instanceof ReflectionMethod) { if ($method instanceof \ReflectionMethod) {
if ($withoutInheritance && $className !== $method->class) { if ($withoutInheritance && $className !== $method->class) {
continue; continue;
} }
@@ -68,14 +64,14 @@ class Reflection
*/ */
public static function getConstants($class) public static function getConstants($class)
{ {
$reflection = new ReflectionClass($class); $reflection = new \ReflectionClass($class);
return $reflection->getConstants(); return $reflection->getConstants();
} }
/** /**
* Returns maximum constant from all constants of given class / object. * Returns maximum integer value of constant of given class / object.
* Values of constants should be integers. * Constants whose values are integers are considered only.
* *
* @param object|string $class The object or name of object's class * @param object|string $class The object or name of object's class
* @return int|null * @return int|null
@@ -108,7 +104,7 @@ class Reflection
*/ */
public static function hasMethod($class, $method) public static function hasMethod($class, $method)
{ {
$reflection = new ReflectionClass($class); $reflection = new \ReflectionClass($class);
return $reflection->hasMethod($method); return $reflection->hasMethod($method);
} }
@@ -122,7 +118,7 @@ class Reflection
*/ */
public static function hasProperty($class, $property) public static function hasProperty($class, $property)
{ {
$reflection = new ReflectionClass($class); $reflection = new \ReflectionClass($class);
return $reflection->hasProperty($property); return $reflection->hasProperty($property);
} }
@@ -136,7 +132,7 @@ class Reflection
*/ */
public static function hasConstant($class, $constant) public static function hasConstant($class, $constant)
{ {
$reflection = new ReflectionClass($class); $reflection = new \ReflectionClass($class);
return $reflection->hasConstant($constant); return $reflection->hasConstant($constant);
} }
@@ -150,7 +146,7 @@ class Reflection
*/ */
public static function getConstantValue($class, $constant) public static function getConstantValue($class, $constant)
{ {
$reflection = new ReflectionClass($class); $reflection = new \ReflectionClass($class);
if (self::hasConstant($class, $constant)) { if (self::hasConstant($class, $constant)) {
return $reflection->getConstant($constant); return $reflection->getConstant($constant);
@@ -189,16 +185,16 @@ class Reflection
* Let's dig more and get proper value * Let's dig more and get proper value
* *
* Required to avoid bug: * Required to avoid bug:
* ReflectionObject::__construct() expects parameter 1 to be object, null given * \ReflectionObject::__construct() expects parameter 1 to be object, null given
* (...) * (...)
* 4. at ReflectionObject->__construct (null) * 4. at \ReflectionObject->__construct (null)
* 5. at Reflection ::getPropertyValue (null, 'name', true) * 5. at Reflection ::getPropertyValue (null, 'name', true)
* 6. at ListService->getItemValue (object(Deal), 'project.name', '0') * 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) * while using "project.name" as property - $project has $name property ($project exists in the Deal class)
* and the $project equals null * and the $project equals null
* *
* Krzysztof Niziol <krzysztof.niziol@meritoo.pl> * Meritoo <github@meritoo.pl>
* 2016-11-07 * 2016-11-07
*/ */
if (null !== $object) { if (null !== $object) {
@@ -216,30 +212,42 @@ class Reflection
* Use \ReflectionObject class * Use \ReflectionObject class
*/ */
try { try {
$reflectionProperty = new ReflectionProperty($className, $property); $reflectionProperty = new \ReflectionProperty($className, $property);
$value = $reflectionProperty->getValue($object); $value = $reflectionProperty->getValue($object);
} catch (ReflectionException $exception) { } catch (\ReflectionException $exception) {
/* /*
* 2nd try: * 2nd try:
* Look for the get / has / is methods * Look for the get / has / is methods
*/ */
$class = new ReflectionObject($object); $class = new \ReflectionObject($object);
$valueFound = false; $valueFound = false;
if ($class->hasProperty($property) || $force) { if ($force || $class->hasProperty($property)) {
$property = Inflector::classify($property); $property = Inflector::classify($property);
$methodPrefixes = [ $getterPrefixes = [
'get', 'get',
'has', 'has',
'is', 'is',
]; ];
foreach ($methodPrefixes as $prefix) { foreach ($getterPrefixes as $prefix) {
$method = sprintf('%s%s', $prefix, $property); $getterName = sprintf('%s%s', $prefix, $property);
if ($class->hasMethod($method)) { if ($class->hasMethod($getterName)) {
$value = $object->{$method}(); $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; $valueFound = true;
break; break;
} }
@@ -248,13 +256,14 @@ class Reflection
if (!$valueFound && null !== $reflectionProperty) { if (!$valueFound && null !== $reflectionProperty) {
/* /*
* Oops, we have got exception. * Oops, value of the property is still unknown
* *
* 3rd try: * 3rd try:
* Let's try modify accessibility of the property and try again to get value. * Let's modify accessibility of the property and try again to get value
*/ */
$reflectionProperty->setAccessible(true); $reflectionProperty->setAccessible(true);
$value = $reflectionProperty->getValue($object); $value = $reflectionProperty->getValue($object);
$reflectionProperty->setAccessible(false);
} }
} }
} }
@@ -275,6 +284,14 @@ class Reflection
*/ */
public static function getPropertyValues($objects, $property, $force = false) public static function getPropertyValues($objects, $property, $force = false)
{ {
/*
* No objects?
* Nothing to do
*/
if (empty($objects)) {
return [];
}
if ($objects instanceof Collection) { if ($objects instanceof Collection) {
$objects = $objects->toArray(); $objects = $objects->toArray();
} }
@@ -365,13 +382,13 @@ class Reflection
{ {
$fullClassName = self::getClassName($source); $fullClassName = self::getClassName($source);
if (empty($fullClassName)) { if (null === $fullClassName || '' === $fullClassName) {
return ''; return '';
} }
$className = self::getClassName($source, true); $className = self::getClassName($source, true);
if ($className == $fullClassName) { if ($className === $fullClassName) {
return $className; return $className;
} }
@@ -390,7 +407,7 @@ class Reflection
$className = self::getClassName($source); $className = self::getClassName($source);
$interfaces = class_implements($className); $interfaces = class_implements($className);
return in_array($interface, $interfaces); return in_array($interface, $interfaces, true);
} }
/** /**
@@ -407,8 +424,8 @@ class Reflection
$parents = class_parents($childClassName); $parents = class_parents($childClassName);
if (is_array($parents)) { if (is_array($parents) && 0 < count($parents)) {
return in_array($parentClassName, $parents); return in_array($parentClassName, $parents, true);
} }
return false; return false;
@@ -418,22 +435,22 @@ class Reflection
* Returns given object properties * Returns given object properties
* *
* @param array|object|string $source An array of objects, namespaces, object or namespace * @param array|object|string $source An array of objects, namespaces, object or namespace
* @param int $filter (optional) Filter of properties. Uses ReflectionProperty class * @param int $filter (optional) Filter of properties. Uses \ReflectionProperty class
* constants. By default all properties are returned. * constants. By default all properties are returned.
* @param bool $includeParents (optional) If is set to true, properties of parent classes are * @param bool $includeParents (optional) If is set to true, properties of parent classes are
* included (recursively). Otherwise - not. * included (recursively). Otherwise - not.
* @return array|ReflectionProperty * @return array|\ReflectionProperty
*/ */
public static function getProperties($source, $filter = null, $includeParents = false) public static function getProperties($source, $filter = null, $includeParents = false)
{ {
$className = self::getClassName($source); $className = self::getClassName($source);
$reflection = new ReflectionClass($className); $reflection = new \ReflectionClass($className);
if (null === $filter) { if (null === $filter) {
$filter = ReflectionProperty::IS_PRIVATE $filter = \ReflectionProperty::IS_PRIVATE
+ ReflectionProperty::IS_PROTECTED + \ReflectionProperty::IS_PROTECTED
+ ReflectionProperty::IS_PUBLIC + \ReflectionProperty::IS_PUBLIC
+ ReflectionProperty::IS_STATIC; + \ReflectionProperty::IS_STATIC;
} }
$properties = $reflection->getProperties($filter); $properties = $reflection->getProperties($filter);
@@ -455,12 +472,12 @@ class Reflection
* Returns a parent class or false if there is no parent class * 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 * @param array|object|string $source An array of objects, namespaces, object or namespace
* @return ReflectionClass|bool * @return \ReflectionClass|bool
*/ */
public static function getParentClass($source) public static function getParentClass($source)
{ {
$className = self::getClassName($source); $className = self::getClassName($source);
$reflection = new ReflectionClass($className); $reflection = new \ReflectionClass($className);
return $reflection->getParentClass(); return $reflection->getParentClass();
} }
@@ -471,8 +488,8 @@ class Reflection
* *
* @param array|object|string $class Class who child classes should be returned. An array of objects, strings, * @param array|object|string $class Class who child classes should be returned. An array of objects, strings,
* object or string. * object or string.
* @return array|null
* @throws CannotResolveClassNameException * @throws CannotResolveClassNameException
* @return array|null
*/ */
public static function getChildClasses($class) public static function getChildClasses($class)
{ {
@@ -492,7 +509,7 @@ class Reflection
* Oops, cannot resolve class * Oops, cannot resolve class
*/ */
if (null === $className) { if (null === $className) {
throw new CannotResolveClassNameException($class); throw CannotResolveClassNameException::create($class);
} }
$childClasses = []; $childClasses = [];
@@ -509,7 +526,7 @@ class Reflection
*/ */
$realClass = ClassUtils::getRealClass($oneClass); $realClass = ClassUtils::getRealClass($oneClass);
if (in_array($realClass, $childClasses)) { if (in_array($realClass, $childClasses, true)) {
continue; continue;
} }
@@ -526,10 +543,9 @@ class Reflection
* *
* @param array|object|string $parentClass Class who child class should be returned. An array of objects, * @param array|object|string $parentClass Class who child class should be returned. An array of objects,
* namespaces, object or namespace. * namespaces, object or namespace.
* @return mixed
*
* @throws MissingChildClassesException * @throws MissingChildClassesException
* @throws TooManyChildClassesException * @throws TooManyChildClassesException
* @return mixed
*/ */
public static function getOneChildClass($parentClass) public static function getOneChildClass($parentClass)
{ {
@@ -540,7 +556,7 @@ class Reflection
* Oops, the base / parent class hasn't child class * Oops, the base / parent class hasn't child class
*/ */
if (empty($childClasses)) { if (empty($childClasses)) {
throw new MissingChildClassesException($parentClass); throw MissingChildClassesException::create($parentClass);
} }
/* /*
@@ -548,20 +564,20 @@ class Reflection
* Oops, the base / parent class has too many child classes * Oops, the base / parent class has too many child classes
*/ */
if (count($childClasses) > 1) { if (count($childClasses) > 1) {
throw new TooManyChildClassesException($parentClass, $childClasses); throw TooManyChildClassesException::create($parentClass, $childClasses);
} }
return trim($childClasses[0]); return trim($childClasses[0]);
} }
/** /**
* Returns property, the ReflectionProperty instance, of given object * Returns property, the \ReflectionProperty instance, of given object
* *
* @param array|object|string $class An array of objects, namespaces, object or namespace * @param array|object|string $class An array of objects, namespaces, object or namespace
* @param string $property Name of the property * @param string $property Name of the property
* @param int $filter (optional) Filter of properties. Uses ReflectionProperty class constants. * @param int $filter (optional) Filter of properties. Uses \ReflectionProperty class constants.
* By default all properties are allowed / processed. * 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, $property, $filter = null)
{ {
@@ -569,9 +585,9 @@ class Reflection
$properties = self::getProperties($className, $filter); $properties = self::getProperties($className, $filter);
if (!empty($properties)) { if (!empty($properties)) {
/* @var $reflectionProperty ReflectionProperty */ /* @var $reflectionProperty \ReflectionProperty */
foreach ($properties as $reflectionProperty) { foreach ($properties as $reflectionProperty) {
if ($reflectionProperty->getName() == $property) { if ($reflectionProperty->getName() === $property) {
return $reflectionProperty; return $reflectionProperty;
} }
} }
@@ -587,8 +603,8 @@ class Reflection
* @param array|string $trait An array of strings or string * @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 * @param bool $verifyParents If is set to true, parent classes are verified if they use given
* trait. Otherwise - not. * trait. Otherwise - not.
* @return bool|null
* @throws CannotResolveClassNameException * @throws CannotResolveClassNameException
* @return bool|null
*/ */
public static function usesTrait($class, $trait, $verifyParents = false) public static function usesTrait($class, $trait, $verifyParents = false)
{ {
@@ -598,21 +614,21 @@ class Reflection
/* /*
* Oops, cannot resolve class * Oops, cannot resolve class
*/ */
if (empty($className)) { if (null === $className || '' === $className) {
throw new CannotResolveClassNameException($class); throw CannotResolveClassNameException::create($class);
} }
/* /*
* Oops, cannot resolve trait * Oops, cannot resolve trait
*/ */
if (empty($traitName)) { if (null === $traitName || '' === $traitName) {
throw new CannotResolveClassNameException($class, false); throw new CannotResolveClassNameException($class, false);
} }
$reflection = new ReflectionClass($className); $reflection = new \ReflectionClass($className);
$traitsNames = $reflection->getTraitNames(); $traitsNames = $reflection->getTraitNames();
$uses = in_array($traitName, $traitsNames); $uses = in_array($traitName, $traitsNames, true);
if (!$uses && $verifyParents) { if (!$uses && $verifyParents) {
$parentClassName = self::getParentClassName($className); $parentClassName = self::getParentClassName($className);
@@ -635,7 +651,7 @@ class Reflection
public static function getParentClassName($class) public static function getParentClassName($class)
{ {
$className = self::getClassName($class); $className = self::getClassName($class);
$reflection = new ReflectionClass($className); $reflection = new \ReflectionClass($className);
$parentClass = $reflection->getParentClass(); $parentClass = $reflection->getParentClass();
if (null === $parentClass || false === $parentClass) { if (null === $parentClass || false === $parentClass) {
@@ -644,4 +660,36 @@ class Reflection
return $parentClass->getName(); return $parentClass->getName();
} }
/**
* Sets value of given property
*
* @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, $property, $value)
{
$reflectionProperty = self::getProperty($object, $property);
/*
* Oops, property does not exist
*/
if (null === $reflectionProperty) {
throw NotExistingPropertyException::create($object, $property);
}
$notAccessible = $reflectionProperty->isPrivate() || $reflectionProperty->isProtected();
if ($notAccessible) {
$reflectionProperty->setAccessible(true);
}
$reflectionProperty->setValue($object, $value);
if ($notAccessible) {
$reflectionProperty->setAccessible(false);
}
}
} }

View File

@@ -14,8 +14,8 @@ use Meritoo\Common\Exception\Regex\InvalidColorHexValueException;
/** /**
* Useful regular expressions methods * Useful regular expressions methods
* *
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl> * @author Meritoo <github@meritoo.pl>
* @copyright Meritoo.pl * @copyright Meritoo <http://www.meritoo.pl>
*/ */
class Regex class Regex
{ {
@@ -25,18 +25,21 @@ class Regex
* @var array * @var array
*/ */
private static $patterns = [ private static $patterns = [
'email' => '/[\w-]{2,}@[\w-]+\.[\w]{2,}+/', 'email' => '/^[\w-.]{2,}@[\w-]+\.[\w]{2,}+$/',
'phone' => '/^\+?[0-9 ]+$/', 'phone' => '/^\+?[0-9 ]+$/',
'camelCasePart' => '/([a-z]|[A-Z]){1}[a-z]*/', 'camelCasePart' => '/([a-z]|[A-Z]){1}[a-z]*/',
'urlProtocol' => '/^([a-z]+:\/\/)', 'urlProtocol' => '/^([a-z]+:\/\/)',
'urlDomain' => '([\da-z\.-]+)\.([a-z\.]{2,6})(\/)?([\w\.\-]*)?(\?)?([\w \.\-\/=&]*)\/?$/i', 'urlDomain' => '([\da-z\.-]+)\.([a-z\.]{2,6})(\/)?([\w\.\-]*)?(\?)?([\w \.\-\/=&]*)\/?$/i',
'letterOrDigit' => '/[a-zA-Z0-9]+/', 'letterOrDigit' => '/[a-zA-Z0-9]+/',
'htmlEntity' => '/&[a-z0-9]+;/', 'htmlEntity' => '/&[a-z0-9]+;/',
'htmlAttribute' => '/([\w-]+)="([\w -]+)"/',
'fileName' => '/.+\.\w+$/', 'fileName' => '/.+\.\w+$/',
'isQuoted' => '/^[\'"]{1}.+[\'"]{1}$/', 'isQuoted' => '/^[\'"]{1}.+[\'"]{1}$/',
'windowsBasedPath' => '/^[A-Z]{1}:\\\.*$/', 'windowsBasedPath' => '/^[A-Z]{1}:\\\.*$/',
'money' => '/^[-+]?\d+([\.,]{1}\d*)?$/', 'money' => '/^[-+]?\d+([\.,]{1}\d*)?$/',
'color' => '/^[a-f0-9]{6}$/i', 'color' => '/^[a-f0-9]{6}$/i',
'bundleName' => '/^(([A-Z]{1}[a-z0-9]+)((?2))*)(Bundle)$/',
'binaryValue' => '/[^\x20-\x7E\t\r\n]/',
]; ];
/** /**
@@ -56,43 +59,77 @@ class Regex
*/ */
public static function isValidEmail($email) public static function isValidEmail($email)
{ {
/*
* Not a string?
* Nothing to do
*/
if (!is_string($email)) {
return false;
}
$pattern = self::getEmailPattern(); $pattern = self::getEmailPattern();
return (bool)preg_match($pattern, $email); return (bool)preg_match($pattern, $email);
} }
/** /**
* Returns information if given tax ID (in polish: NIP) is valid * Returns information if given tax ID is valid (in Poland it's named "NIP")
* *
* @param string $taxidString Tax ID (NIP) string * @param string $taxIdString Tax ID (NIP) string
* @return bool * @return bool
*/ */
public static function isValidTaxid($taxidString) public static function isValidTaxId($taxIdString)
{ {
if (!empty($taxidString)) { /*
$weights = [ * Not a string?
6, * Nothing to do
5, */
7, if (!is_string($taxIdString)) {
2, return false;
3, }
4,
5,
6,
7,
];
$taxid = preg_replace('/[\s-]/', '', $taxidString);
$sum = 0;
if (10 == strlen($taxid) && is_numeric($taxid)) { /*
for ($x = 0; $x <= 8; ++$x) { * Empty/Unknown value?
$sum += $taxid[$x] * $weights[$x]; * Nothing to do
} */
if (empty($taxIdString)) {
return false;
}
if ((($sum % 11) % 10) == $taxid[9]) { $taxId = preg_replace('/[\s-]/', '', $taxIdString);
return true;
} /*
} * Tax ID is not 10 characters length OR is not numeric?
* Nothing to do
*/
if (10 !== strlen($taxId) || !is_numeric($taxId)) {
return false;
}
$weights = [
6,
5,
7,
2,
3,
4,
5,
6,
7,
];
$sum = 0;
for ($x = 0; $x <= 8; ++$x) {
$sum += $taxId[$x] * $weights[$x];
}
/*
* Last number it's not a remainder from dividing per 11?
* Nothing to do
*/
if ($sum % 11 == $taxId[9]) {
return true;
} }
return false; return false;
@@ -108,6 +145,14 @@ class Regex
*/ */
public static function isValidUrl($url, $requireProtocol = false) public static function isValidUrl($url, $requireProtocol = false)
{ {
/*
* Not a string?
* Nothing to do
*/
if (!is_string($url)) {
return false;
}
$pattern = self::getUrlPattern($requireProtocol); $pattern = self::getUrlPattern($requireProtocol);
return (bool)preg_match($pattern, $url); return (bool)preg_match($pattern, $url);
@@ -121,88 +166,108 @@ class Regex
*/ */
public static function isValidPhoneNumber($phoneNumber) public static function isValidPhoneNumber($phoneNumber)
{ {
/*
* Not a string?
* Nothing to do
*/
if (!is_string($phoneNumber)) {
return false;
}
$pattern = self::getPhoneNumberPattern(); $pattern = self::getPhoneNumberPattern();
return (bool)preg_match($pattern, $phoneNumber); return (bool)preg_match($pattern, trim($phoneNumber));
} }
/** /**
* Returns array values that matches given pattern (or values that keys matches) * Returns array values that match given pattern (or values that keys match the pattern)
* *
* @param string $pattern Pattern to match * @param string $pattern Pattern to match
* @param array $dataArray The array * @param array $array The array (scalar values only)
* @param bool $itsKeyPattern (optional) If is set to true, keys are checks if they match pattern. Otherwise - * @param bool $itsKeyPattern (optional) If is set to true, keys will be checked if they match pattern.
* values are checks. * Otherwise - values will be checked (default behaviour).
* @return array * @return array
*/ */
public static function getArrayValuesByPattern($pattern, $dataArray, $itsKeyPattern = false) public static function getArrayValuesByPattern($pattern, array $array, $itsKeyPattern = false)
{ {
/*
* No elements?
* Nothing to do
*/
if (empty($array)) {
return [];
}
if ($itsKeyPattern) { if ($itsKeyPattern) {
$effect = []; $effect = [];
if (!empty($dataArray)) { foreach ($array as $key => $value) {
$matches = []; if ((bool)preg_match($pattern, $key)) {
$effect[$key] = $value;
foreach ($dataArray as $key => $value) {
if (preg_match($pattern, $key, $matches)) {
$effect[$key] = $value;
}
} }
} }
return $effect; return $effect;
} }
return preg_grep($pattern, $dataArray); return preg_grep($pattern, $array);
} }
/** /**
* Filters array by given expression and column * Filters array by given expression and column
* *
* Expression can be simple compare expression, like ' == 2', or regular expression. * Expression can be simple compare expression, like " == 2", or regular expression.
* Returns filtered array. * Returns filtered array.
* *
* @param array $array The array that should be filtered * @param array $array The 2-dimensional array that should be filtered
* @param string $arrayColumnKey Column name * @param string $arrayColumnKey Column name
* @param string $filterExpression Filter expression, e.g. '== 2' or '!= \'home\'' * @param string $filterExpression Simple filter expression (e.g. "== 2" or "!= \'home\'") or regular
* @param bool $itsRegularExpression (optional) If is set to true, means that filter expression is a * expression (e.g. "/\d+/" or "/[a-z]+[,;]{2,}/")
* regular expression * @param bool $itsRegularExpression (optional) If is set to true, means that filter expression is a regular
* expression. Otherwise - not (default behaviour).
* @return array * @return array
*/ */
public static function arrayFilter($array, $arrayColumnKey, $filterExpression, $itsRegularExpression = false) public static function arrayFilter($array, $arrayColumnKey, $filterExpression, $itsRegularExpression = false)
{ {
$effect = []; /*
* No elements?
* Nothing to do
*/
if (empty($array)) {
return [];
}
if (!empty($array)) { $effect = $array;
$effect = $array;
foreach ($effect as $key => &$item) { foreach ($effect as $key => &$item) {
if (isset($item[$arrayColumnKey])) { if (!isset($item[$arrayColumnKey])) {
$value = $item[$arrayColumnKey]; continue;
}
if ($itsRegularExpression) { $value = $item[$arrayColumnKey];
$matches = [];
$pattern = '|' . $filterExpression . '|';
$matchesCount = preg_match($pattern, $value, $matches);
$remove = 0 == $matchesCount; 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 { } else {
if ('' == $value) { $value = 'false';
$value = '\'\'';
} elseif (is_string($value)) {
$value = '\'' . $value . '\'';
}
eval('$isTrue = ' . $value . $filterExpression . ';');
/* @var bool $isTrue */
$remove = !$isTrue;
}
if ($remove) {
unset($effect[$key]);
} }
} }
eval(sprintf('$isEqual = %s%s;', $value, $filterExpression));
/* @var bool $isEqual */
$remove = !$isEqual;
}
if ($remove) {
unset($effect[$key]);
} }
} }
@@ -210,36 +275,41 @@ class Regex
} }
/** /**
* Perform regular expression match with many given patterns. * Performs regular expression match with many given patterns.
* Returns information if given $subject matches one or all given $patterns. * Returns information if given $subject matches one or all given $patterns.
* *
* @param array|string $patterns The patterns to match * @param array|string $patterns The patterns to match
* @param string $subject The string to check * @param string $subject The string to check
* @param bool $mustAllMatch (optional) If is set to true, $subject must match all $patterns. Otherwise - * @param bool $mustAllMatch (optional) If is set to true, $subject must match all $patterns. Otherwise -
* not. * not (default behaviour).
* @return bool * @return bool
*/ */
public static function pregMultiMatch($patterns, $subject, $mustAllMatch = false) public static function pregMultiMatch($patterns, $subject, $mustAllMatch = false)
{ {
/*
* No patterns?
* Nothing to do
*/
if (empty($patterns)) {
return false;
}
$effect = false; $effect = false;
$patterns = Arrays::makeArray($patterns); $patterns = Arrays::makeArray($patterns);
if (!empty($patterns)) { if ($mustAllMatch) {
$effect = true;
}
foreach ($patterns as $pattern) {
$matched = (bool)preg_match_all($pattern, $subject);
if ($mustAllMatch) { if ($mustAllMatch) {
$effect = true; $effect = $effect && $matched;
} } else {
if ($matched) {
foreach ($patterns as $pattern) { $effect = $matched;
$matches = []; break;
$matched = (bool)preg_match_all($pattern, $subject, $matches);
if ($mustAllMatch) {
$effect = $effect && $matched;
} else {
if ($matched) {
$effect = $matched;
break;
}
} }
} }
} }
@@ -676,6 +746,14 @@ class Regex
*/ */
public static function isValidMoneyValue($value) public static function isValidMoneyValue($value)
{ {
/*
* Not a scalar value?
* Nothing to do
*/
if (!is_scalar($value)) {
return false;
}
$pattern = self::getMoneyPattern(); $pattern = self::getMoneyPattern();
return (bool)preg_match($pattern, $value); return (bool)preg_match($pattern, $value);
@@ -688,39 +766,162 @@ class Regex
* @param string $color Color to verify * @param string $color Color to verify
* @param bool $throwException (optional) If is set to true, throws an exception if given color is invalid * @param bool $throwException (optional) If is set to true, throws an exception if given color is invalid
* (default behaviour). Otherwise - not. * (default behaviour). Otherwise - not.
* @return string|bool
*
* @throws IncorrectColorHexLengthException * @throws IncorrectColorHexLengthException
* @throws InvalidColorHexValueException * @throws InvalidColorHexValueException
* @return string|bool
*/ */
public static function getValidColorHexValue($color, $throwException = true) public static function getValidColorHexValue($color, $throwException = true)
{ {
/*
* Not a scalar value?
* Nothing to do
*/
if (!is_scalar($color)) {
return false;
}
$color = Miscellaneous::replace($color, '/#/', ''); $color = Miscellaneous::replace($color, '/#/', '');
$length = strlen($color); $length = strlen($color);
if (3 === $length) { /*
$color = Miscellaneous::replace($color, '/(.)(.)(.)/', '$1$1$2$2$3$3'); * Color is not 3 or 6 characters long?
} else { * Nothing to do
if (6 !== $length) { */
if ($throwException) { if (3 !== $length && 6 !== $length) {
throw new IncorrectColorHexLengthException($color);
}
return false;
}
}
$pattern = self::$patterns['color'];
$match = (bool)preg_match($pattern, $color);
if (!$match) {
if ($throwException) { if ($throwException) {
throw new InvalidColorHexValueException($color); throw new IncorrectColorHexLengthException($color);
} }
return false; return false;
} }
return strtolower($color); /*
* 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);
} }
} }

View File

@@ -0,0 +1,235 @@
<?php
/**
* (c) Meritoo.pl, http://www.meritoo.pl
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Meritoo\Common\Utilities;
use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\QueryBuilder;
/**
* Useful methods for repository
*
* @author Meritoo <github@meritoo.pl>
* @copyright Meritoo <http://www.meritoo.pl>
*/
class Repository
{
/**
* Name of key responsible for sorting/position of an item in array
*
* @var string
*/
const POSITION_KEY = 'position';
/**
* Replenishes positions of given items
*
* @param array $items Objects who have "getPosition()" and "setPosition()" methods or arrays
* @param bool $asLast (optional) If is set to true, items are placed at the end (default behaviour). Otherwise -
* at top.
* @param bool $force (optional) If is set to true, positions are set even there is no extreme position.
* Otherwise - if extreme position is unknown (is null) replenishment is stopped / skipped
* (default behaviour).
*/
public static function replenishPositions(array &$items, $asLast = true, $force = false)
{
$position = self::getExtremePosition($items, $asLast);
/*
* Extreme position is unknown, but it's required?
* Use 0 as default/start value
*/
if (null === $position && $force) {
$position = 0;
}
/*
* Extreme position is unknown or there are no items to sort?
* Nothing to do
*/
if (null === $position || empty($items)) {
return;
}
foreach ($items as &$item) {
/*
* The item is not sortable?
*/
if (!self::isSortable($item)) {
continue;
}
/*
* Position has been set?
* Nothing to do
*/
if (self::isSorted($item)) {
continue;
}
/*
* Calculate position
*/
if ($asLast) {
++$position;
} else {
--$position;
}
/*
* It's an object?
* Use proper method to set position
*/
if (is_object($item)) {
$item->setPosition($position);
continue;
}
/*
* It's an array
* Use proper key to set position
*/
$item[static::POSITION_KEY] = $position;
}
}
/**
* 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';
return $repository
->createQueryBuilder($alias)
->orderBy(sprintf('%s.%s', $alias, $property), $direction);
}
/**
* Returns information if given item is sortable
*
* Sortable means it's an:
* - array
* or
* - object and has getPosition() and setPosition()
*
* @param mixed $item An item to verify (object who has "getPosition()" and "setPosition()" methods or an array)
* @return bool
*/
private static function isSortable($item)
{
return is_array($item)
||
(
is_object($item)
&&
Reflection::hasMethod($item, 'getPosition')
&&
Reflection::hasMethod($item, 'setPosition')
);
}
/**
* Returns information if given item is sorted (position has been set)
*
* @param mixed $item An item to verify (object who has "getPosition()" and "setPosition()" methods or an array)
* @return bool
*/
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())
||
(is_array($item) && isset($item[static::POSITION_KEY]));
}
}

View File

@@ -11,8 +11,8 @@ namespace Meritoo\Common\Utilities;
/** /**
* Useful uri methods (only static functions) * Useful uri methods (only static functions)
* *
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl> * @author Meritoo <github@meritoo.pl>
* @copyright Meritoo.pl * @copyright Meritoo <http://www.meritoo.pl>
*/ */
class Uri class Uri
{ {
@@ -24,13 +24,25 @@ class Uri
*/ */
public static function getFullUri($withoutHost = false) public static function getFullUri($withoutHost = false)
{ {
$effect = Miscellaneous::getSafelyGlobalVariable(INPUT_SERVER, 'REQUEST_URI'); $requestedUrl = Miscellaneous::getSafelyGlobalVariable(INPUT_SERVER, 'REQUEST_URI');
if ($withoutHost) { /*
return $effect; * Unknown requested url?
* Nothing to do
*/
if (empty($requestedUrl)) {
return '';
} }
return self::getServerNameOrIp(true) . $effect; /*
* Without host / server name?
* All is done
*/
if ($withoutHost) {
return $requestedUrl;
}
return self::getServerNameOrIp(true) . $requestedUrl;
} }
/** /**
@@ -41,13 +53,25 @@ class Uri
*/ */
public static function getServerNameOrIp($withProtocol = false) public static function getServerNameOrIp($withProtocol = false)
{ {
$protocol = ''; $host = Miscellaneous::getSafelyGlobalVariable(INPUT_SERVER, 'HTTP_HOST');
if ($withProtocol) { /*
$protocol .= self::getProtocolName() . '://'; * Unknown host / server?
* Nothing to do
*/
if (empty($host)) {
return '';
} }
return $protocol . Miscellaneous::getSafelyGlobalVariable(INPUT_SERVER, 'HTTP_HOST'); /*
* With protocol?
* Let's include the protocol
*/
if ($withProtocol) {
return sprintf('%s://%s', self::getProtocolName(), $host);
}
return $host;
} }
/** /**
@@ -57,8 +81,6 @@ class Uri
*/ */
public static function getProtocolName() public static function getProtocolName()
{ {
$effect = '';
$matches = []; $matches = [];
$protocolData = Miscellaneous::getSafelyGlobalVariable(INPUT_SERVER, 'SERVER_PROTOCOL'); // e.g. HTTP/1.1 $protocolData = Miscellaneous::getSafelyGlobalVariable(INPUT_SERVER, 'SERVER_PROTOCOL'); // e.g. HTTP/1.1
$matchCount = preg_match('|(.+)\/(.+)|', $protocolData, $matches); $matchCount = preg_match('|(.+)\/(.+)|', $protocolData, $matches);
@@ -68,11 +90,14 @@ class Uri
* $matches[2] - protocol version, e.g. 1.1 * $matches[2] - protocol version, e.g. 1.1
*/ */
if ($matchCount > 0) { /*
$effect = strtolower($matches[1]); * Oops, cannot match protocol
*/
if (0 == $matchCount) {
return '';
} }
return $effect; return strtolower($matches[1]);
} }
/** /**
@@ -82,13 +107,7 @@ class Uri
*/ */
public static function getRefererUri() public static function getRefererUri()
{ {
$effect = ''; return Miscellaneous::getSafelyGlobalVariable(INPUT_SERVER, 'HTTP_REFERER');
if (filter_has_var(INPUT_SERVER, 'HTTP_REFERER')) {
$effect = Miscellaneous::getSafelyGlobalVariable(INPUT_SERVER, 'HTTP_REFERER');
}
return $effect;
} }
/** /**
@@ -214,10 +233,35 @@ class Uri
*/ */
public static function isExternalUrl($url) public static function isExternalUrl($url)
{ {
/*
* Unknown url or it's just slash?
* Nothing to do
*/
if (empty($url) || '/' === $url) {
return false;
}
$currentUrl = self::getServerNameOrIp(true); $currentUrl = self::getServerNameOrIp(true);
$url = self::replenishProtocol($url); $url = self::replenishProtocol($url);
return !Regex::contains($currentUrl, $url); /*
* Let's prepare pattern of current url
*/
$search = [
':',
'/',
'.',
];
$replace = [
'\:',
'\/',
'\.',
];
$currentUrlPattern = str_replace($search, $replace, $currentUrl);
return !Regex::contains($url, $currentUrlPattern);
} }
/** /**
@@ -273,6 +317,14 @@ class Uri
*/ */
public static function getSecuredUrl($url, $user = '', $password = '') public static function getSecuredUrl($url, $user = '', $password = '')
{ {
/*
* Url is not provided?
* Nothing to do
*/
if (empty($url)) {
return '';
}
$protocol = self::getProtocolName(); $protocol = self::getProtocolName();
$host = self::getServerNameOrIp(); $host = self::getServerNameOrIp();

View File

@@ -15,8 +15,8 @@ use SimpleXMLElement;
/** /**
* Useful XML-related methods (only static functions) * Useful XML-related methods (only static functions)
* *
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl> * @author Meritoo <github@meritoo.pl>
* @copyright Meritoo.pl * @copyright Meritoo <http://www.meritoo.pl>
*/ */
class Xml class Xml
{ {

179
src/ValueObject/Version.php Normal file
View File

@@ -0,0 +1,179 @@
<?php
/**
* (c) Meritoo.pl, http://www.meritoo.pl
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Meritoo\Common\ValueObject;
/**
* Version of software
*
* @author Meritoo <github@meritoo.pl>
* @copyright Meritoo <http://www.meritoo.pl>
*/
class Version
{
/**
* The "major" part.
* Incremented when you make incompatible API changes.
*
* @var int
*/
private $majorPart;
/**
* The "minor" part.
* Incremented when you add functionality in a backwards-compatible manner.
*
* @var int
*/
private $minorPart;
/**
* The "patch" part.
* Incremented when you make backwards-compatible bug fixes.
*
* @var int
*/
private $patchPart;
/**
* Class constructor
*
* @param int $majorPart The "major" part. Incremented when you make incompatible API changes.
* @param int $minorPart The "minor" part. Incremented when you add functionality in a backwards-compatible manner.
* @param int $patchPart The "patch" part. Incremented when you make backwards-compatible bug fixes.
*/
public function __construct($majorPart, $minorPart, $patchPart)
{
$this->majorPart = $majorPart;
$this->minorPart = $minorPart;
$this->patchPart = $patchPart;
}
/**
* Returns the "major" part.
* Incremented when you make incompatible API changes.
*
* @return int
*/
public function getMajorPart()
{
return $this->majorPart;
}
/**
* Returns the "minor" part.
* Incremented when you add functionality in a backwards-compatible manner.
*
* @return int
*/
public function getMinorPart()
{
return $this->minorPart;
}
/**
* Returns the "patch" part.
* Incremented when you make backwards-compatible bug fixes.
*
* @return int
*/
public function getPatchPart()
{
return $this->patchPart;
}
/**
* Returns string representation of instance of this class
*
* @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);
}
}

View File

@@ -9,6 +9,7 @@
namespace Meritoo\Common\Test\Collection; namespace Meritoo\Common\Test\Collection;
use ArrayIterator; use ArrayIterator;
use Generator;
use Meritoo\Common\Collection\Collection; use Meritoo\Common\Collection\Collection;
use Meritoo\Common\Test\Base\BaseTestCase; use Meritoo\Common\Test\Base\BaseTestCase;
use Meritoo\Common\Type\OopVisibilityType; use Meritoo\Common\Type\OopVisibilityType;
@@ -16,8 +17,8 @@ use Meritoo\Common\Type\OopVisibilityType;
/** /**
* Test case of the collection of elements * Test case of the collection of elements
* *
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl> * @author Meritoo <github@meritoo.pl>
* @copyright Meritoo.pl * @copyright Meritoo <http://www.meritoo.pl>
*/ */
class CollectionTest extends BaseTestCase class CollectionTest extends BaseTestCase
{ {
@@ -129,22 +130,39 @@ class CollectionTest extends BaseTestCase
static::assertInstanceOf(ArrayIterator::class, $this->simpleCollection->getIterator()); static::assertInstanceOf(ArrayIterator::class, $this->simpleCollection->getIterator());
} }
public function testAdd() /**
* @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)
{ {
$this->emptyCollection->add('test1'); $collection->add($element);
static::assertTrue($this->emptyCollection->has('test1')); static::assertTrue($collection->has($element));
static::assertEquals(1, $this->emptyCollection->count()); static::assertEquals($expectedCount, $collection->count());
static::assertEquals('test1', $this->emptyCollection[0]); static::assertEquals($element, $collection[$expectedIndex]);
} }
public function testAddWithIndex() /**
* @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)
{ {
$this->emptyCollection->add('test2', 1234); $collection->add($element, $index);
static::assertTrue($this->emptyCollection->has('test2')); static::assertTrue($collection->has($element));
static::assertEquals(1, $this->emptyCollection->count()); static::assertEquals($expectedCount, $collection->count());
static::assertEquals('test2', $this->emptyCollection[1234]); static::assertEquals($element, $collection[$expectedIndex]);
} }
public function testAddMultipleUsingEmptyArray() public function testAddMultipleUsingEmptyArray()
@@ -309,6 +327,87 @@ class CollectionTest extends BaseTestCase
static::assertMethodVisibilityAndArguments(Collection::class, 'exists', OopVisibilityType::IS_PRIVATE, 1, 1); static::assertMethodVisibilityAndArguments(Collection::class, 'exists', OopVisibilityType::IS_PRIVATE, 1, 1);
} }
/**
* 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,
];
}
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */

View File

@@ -16,14 +16,14 @@ use Meritoo\Common\Type\OopVisibilityType;
/** /**
* Test case of the exception used while type of something is unknown * Test case of the exception used while type of something is unknown
* *
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl> * @author Meritoo <github@meritoo.pl>
* @copyright Meritoo.pl * @copyright Meritoo <http://www.meritoo.pl>
*/ */
class UnknownTypeExceptionTest extends BaseTestCase class UnknownTypeExceptionTest extends BaseTestCase
{ {
public function testConstructorVisibilityAndArguments() public function testConstructorVisibilityAndArguments()
{ {
static::assertConstructorVisibilityAndArguments(UnknownTestTypeException::class, OopVisibilityType::IS_PUBLIC, 1, 1); static::assertConstructorVisibilityAndArguments(UnknownTestTypeException::class, OopVisibilityType::IS_PUBLIC, 3);
} }
public function testWithoutException() public function testWithoutException()
@@ -33,7 +33,7 @@ class UnknownTypeExceptionTest extends BaseTestCase
public function testTheException() public function testTheException()
{ {
$this->expectException(UnknownTestTypeException::class); $this->setExpectedException(UnknownTestTypeException::class);
self::assertEmpty((new TestService())->getTranslatedType('test_3')); self::assertEmpty((new TestService())->getTranslatedType('test_3'));
} }
} }
@@ -41,8 +41,8 @@ class UnknownTypeExceptionTest extends BaseTestCase
/** /**
* Type of something (for testing purposes) * Type of something (for testing purposes)
* *
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl> * @author Meritoo <github@meritoo.pl>
* @copyright Meritoo.pl * @copyright Meritoo <http://www.meritoo.pl>
*/ */
class TestType extends BaseType class TestType extends BaseType
{ {
@@ -54,27 +54,31 @@ class TestType extends BaseType
/** /**
* An exception used while type of something is unknown (for testing purposes) * An exception used while type of something is unknown (for testing purposes)
* *
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl> * @author Meritoo <github@meritoo.pl>
* @copyright Meritoo.pl * @copyright Meritoo <http://www.meritoo.pl>
*/ */
class UnknownTestTypeException extends UnknownTypeException class UnknownTestTypeException extends UnknownTypeException
{ {
/** /**
* Class constructor * Creates exception
* *
* @param int|string $unknownType The unknown type of something (for testing purposes) * @param string $unknownType The unknown type of something (for testing purposes)
* @return UnknownTestTypeException
*/ */
public function __construct($unknownType) public static function createException($unknownType)
{ {
parent::__construct($unknownType, new TestType(), 'type of something used for testing'); /* @var UnknownTestTypeException $exception */
$exception = parent::create($unknownType, new TestType(), 'type of something used for testing');
return $exception;
} }
} }
/** /**
* Service used together with type of something (for testing purposes) * Service used together with type of something (for testing purposes)
* *
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl> * @author Meritoo <github@meritoo.pl>
* @copyright Meritoo.pl * @copyright Meritoo <http://www.meritoo.pl>
*/ */
class TestService class TestService
{ {
@@ -82,9 +86,8 @@ class TestService
* Returns translated type (for testing purposes) * Returns translated type (for testing purposes)
* *
* @param string $type Type of something (for testing purposes) * @param string $type Type of something (for testing purposes)
* @return string
*
* @throws UnknownTestTypeException * @throws UnknownTestTypeException
* @return string
*/ */
public function getTranslatedType($type) public function getTranslatedType($type)
{ {

View File

@@ -9,7 +9,7 @@
namespace Meritoo\Common\Test\Exception\Date; namespace Meritoo\Common\Test\Exception\Date;
use Generator; use Generator;
use Meritoo\Common\Exception\Date\UnknownDatePartTypeException; use Meritoo\Common\Exception\Type\UnknownDatePartTypeException;
use Meritoo\Common\Test\Base\BaseTestCase; use Meritoo\Common\Test\Base\BaseTestCase;
use Meritoo\Common\Type\DatePartType; use Meritoo\Common\Type\DatePartType;
use Meritoo\Common\Type\OopVisibilityType; use Meritoo\Common\Type\OopVisibilityType;
@@ -17,14 +17,14 @@ use Meritoo\Common\Type\OopVisibilityType;
/** /**
* Test case of an exception used while type of date part, e.g. "year", is unknown * Test case of an exception used while type of date part, e.g. "year", is unknown
* *
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl> * @author Meritoo <github@meritoo.pl>
* @copyright Meritoo.pl * @copyright Meritoo <http://www.meritoo.pl>
*/ */
class UnknownDatePartTypeExceptionTest extends BaseTestCase class UnknownDatePartTypeExceptionTest extends BaseTestCase
{ {
public function testConstructorVisibilityAndArguments() public function testConstructorVisibilityAndArguments()
{ {
static::assertConstructorVisibilityAndArguments(UnknownDatePartTypeException::class, OopVisibilityType::IS_PUBLIC, 2, 2); static::assertConstructorVisibilityAndArguments(UnknownDatePartTypeException::class, OopVisibilityType::IS_PUBLIC, 3);
} }
/** /**
@@ -34,9 +34,9 @@ class UnknownDatePartTypeExceptionTest extends BaseTestCase
* *
* @dataProvider provideDatePartAndValue * @dataProvider provideDatePartAndValue
*/ */
public function testConstructorMessage($unknownDatePart, $value, $expectedMessage) public function testMessage($unknownDatePart, $value, $expectedMessage)
{ {
$exception = new UnknownDatePartTypeException($unknownDatePart, $value); $exception = UnknownDatePartTypeException::createException($unknownDatePart, $value);
static::assertEquals($expectedMessage, $exception->getMessage()); static::assertEquals($expectedMessage, $exception->getMessage());
} }

View File

@@ -16,14 +16,14 @@ use Meritoo\Common\Type\OopVisibilityType;
/** /**
* Test case of an exception used while file with given path is empty (has no content) * Test case of an exception used while file with given path is empty (has no content)
* *
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl> * @author Meritoo <github@meritoo.pl>
* @copyright Meritoo.pl * @copyright Meritoo <http://www.meritoo.pl>
*/ */
class EmptyFileExceptionTest extends BaseTestCase class EmptyFileExceptionTest extends BaseTestCase
{ {
public function testConstructorVisibilityAndArguments() public function testConstructorVisibilityAndArguments()
{ {
static::assertConstructorVisibilityAndArguments(EmptyFileException::class, OopVisibilityType::IS_PUBLIC, 1, 1); static::assertConstructorVisibilityAndArguments(EmptyFileException::class, OopVisibilityType::IS_PUBLIC, 3);
} }
/** /**
@@ -32,9 +32,9 @@ class EmptyFileExceptionTest extends BaseTestCase
* *
* @dataProvider providePathOfFile * @dataProvider providePathOfFile
*/ */
public function testConstructorMessage($emptyFilePath, $expectedMessage) public function testMessage($emptyFilePath, $expectedMessage)
{ {
$exception = new EmptyFileException($emptyFilePath); $exception = EmptyFileException::create($emptyFilePath);
static::assertEquals($expectedMessage, $exception->getMessage()); static::assertEquals($expectedMessage, $exception->getMessage());
} }

View File

@@ -15,19 +15,19 @@ use Meritoo\Common\Type\OopVisibilityType;
/** /**
* Test case of an exception used while path of given file is empty * Test case of an exception used while path of given file is empty
* *
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl> * @author Meritoo <github@meritoo.pl>
* @copyright Meritoo.pl * @copyright Meritoo <http://www.meritoo.pl>
*/ */
class EmptyFilePathExceptionTest extends BaseTestCase class EmptyFilePathExceptionTest extends BaseTestCase
{ {
public function testConstructorVisibilityAndArguments() public function testConstructorVisibilityAndArguments()
{ {
static::assertConstructorVisibilityAndArguments(EmptyFilePathException::class, OopVisibilityType::IS_PUBLIC); static::assertConstructorVisibilityAndArguments(EmptyFilePathException::class, OopVisibilityType::IS_PUBLIC, 3);
} }
public function testConstructorMessage() public function testConstructorMessage()
{ {
$exception = new EmptyFilePathException(); $exception = EmptyFilePathException::create();
static::assertEquals('Path of the file is empty. Did you provide path of proper file?', $exception->getMessage()); static::assertEquals('Path of the file is empty. Did you provide path of proper file?', $exception->getMessage());
} }
} }

View File

@@ -16,14 +16,14 @@ use Meritoo\Common\Type\OopVisibilityType;
/** /**
* Test case of an exception used while file with given path does not exist * Test case of an exception used while file with given path does not exist
* *
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl> * @author Meritoo <github@meritoo.pl>
* @copyright Meritoo.pl * @copyright Meritoo <http://www.meritoo.pl>
*/ */
class NotExistingFileExceptionTest extends BaseTestCase class NotExistingFileExceptionTest extends BaseTestCase
{ {
public function testConstructorVisibilityAndArguments() public function testConstructorVisibilityAndArguments()
{ {
static::assertConstructorVisibilityAndArguments(NotExistingFileException::class, OopVisibilityType::IS_PUBLIC, 1, 1); static::assertConstructorVisibilityAndArguments(NotExistingFileException::class, OopVisibilityType::IS_PUBLIC, 3);
} }
/** /**
@@ -34,7 +34,7 @@ class NotExistingFileExceptionTest extends BaseTestCase
*/ */
public function testConstructorMessage($notExistingFilePath, $expectedMessage) public function testConstructorMessage($notExistingFilePath, $expectedMessage)
{ {
$exception = new NotExistingFileException($notExistingFilePath); $exception = NotExistingFileException::create($notExistingFilePath);
static::assertEquals($expectedMessage, $exception->getMessage()); static::assertEquals($expectedMessage, $exception->getMessage());
} }

View File

@@ -16,14 +16,14 @@ use Meritoo\Common\Type\OopVisibilityType;
/** /**
* Test case of an exception used while method cannot be called, because is disabled * Test case of an exception used while method cannot be called, because is disabled
* *
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl> * @author Meritoo <github@meritoo.pl>
* @copyright Meritoo.pl * @copyright Meritoo <http://www.meritoo.pl>
*/ */
class DisabledMethodExceptionTest extends BaseTestCase class DisabledMethodExceptionTest extends BaseTestCase
{ {
public function testConstructorVisibilityAndArguments() public function testConstructorVisibilityAndArguments()
{ {
static::assertConstructorVisibilityAndArguments(DisabledMethodException::class, OopVisibilityType::IS_PUBLIC, 2, 1); static::assertConstructorVisibilityAndArguments(DisabledMethodException::class, OopVisibilityType::IS_PUBLIC, 3);
} }
/** /**
@@ -36,7 +36,7 @@ class DisabledMethodExceptionTest extends BaseTestCase
*/ */
public function testConstructorMessage($disabledMethod, $alternativeMethod, $expectedMessage) public function testConstructorMessage($disabledMethod, $alternativeMethod, $expectedMessage)
{ {
$exception = new DisabledMethodException($disabledMethod, $alternativeMethod); $exception = DisabledMethodException::create($disabledMethod, $alternativeMethod);
static::assertEquals($expectedMessage, $exception->getMessage()); static::assertEquals($expectedMessage, $exception->getMessage());
} }

View File

@@ -16,14 +16,14 @@ use Meritoo\Common\Type\OopVisibilityType;
/** /**
* Test case of an exception used while name of class or trait cannot be resolved * Test case of an exception used while name of class or trait cannot be resolved
* *
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl> * @author Meritoo <github@meritoo.pl>
* @copyright Meritoo.pl * @copyright Meritoo <http://www.meritoo.pl>
*/ */
class CannotResolveClassNameExceptionTest extends BaseTestCase class CannotResolveClassNameExceptionTest extends BaseTestCase
{ {
public function testConstructorVisibilityAndArguments() public function testConstructorVisibilityAndArguments()
{ {
static::assertConstructorVisibilityAndArguments(CannotResolveClassNameException::class, OopVisibilityType::IS_PUBLIC, 2, 1); static::assertConstructorVisibilityAndArguments(CannotResolveClassNameException::class, OopVisibilityType::IS_PUBLIC, 3);
} }
/** /**
@@ -37,7 +37,7 @@ class CannotResolveClassNameExceptionTest extends BaseTestCase
*/ */
public function testConstructorMessage($source, $forClass, $expectedMessage) public function testConstructorMessage($source, $forClass, $expectedMessage)
{ {
$exception = new CannotResolveClassNameException($source, $forClass); $exception = CannotResolveClassNameException::create($source, $forClass);
static::assertEquals($expectedMessage, $exception->getMessage()); static::assertEquals($expectedMessage, $exception->getMessage());
} }

View File

@@ -16,14 +16,14 @@ use Meritoo\Common\Type\OopVisibilityType;
/** /**
* Test case of an exception used while given class has no child classes * Test case of an exception used while given class has no child classes
* *
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl> * @author Meritoo <github@meritoo.pl>
* @copyright Meritoo.pl * @copyright Meritoo <http://www.meritoo.pl>
*/ */
class MissingChildClassesExceptionTest extends BaseTestCase class MissingChildClassesExceptionTest extends BaseTestCase
{ {
public function testConstructorVisibilityAndArguments() public function testConstructorVisibilityAndArguments()
{ {
static::assertConstructorVisibilityAndArguments(MissingChildClassesException::class, OopVisibilityType::IS_PUBLIC, 1, 1); static::assertConstructorVisibilityAndArguments(MissingChildClassesException::class, OopVisibilityType::IS_PUBLIC, 3);
} }
/** /**
@@ -35,7 +35,7 @@ class MissingChildClassesExceptionTest extends BaseTestCase
*/ */
public function testConstructorMessage($parentClass, $expectedMessage) public function testConstructorMessage($parentClass, $expectedMessage)
{ {
$exception = new MissingChildClassesException($parentClass); $exception = MissingChildClassesException::create($parentClass);
static::assertEquals($expectedMessage, $exception->getMessage()); static::assertEquals($expectedMessage, $exception->getMessage());
} }

View File

@@ -16,27 +16,27 @@ use Meritoo\Common\Type\OopVisibilityType;
/** /**
* Test case of an exception used while given class has more than one child class * Test case of an exception used while given class has more than one child class
* *
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl> * @author Meritoo <github@meritoo.pl>
* @copyright Meritoo.pl * @copyright Meritoo <http://www.meritoo.pl>
*/ */
class TooManyChildClassesExceptionTest extends BaseTestCase class TooManyChildClassesExceptionTest extends BaseTestCase
{ {
public function testConstructorVisibilityAndArguments() public function testConstructorVisibilityAndArguments()
{ {
static::assertConstructorVisibilityAndArguments(TooManyChildClassesException::class, OopVisibilityType::IS_PUBLIC, 2, 2); static::assertConstructorVisibilityAndArguments(TooManyChildClassesException::class, OopVisibilityType::IS_PUBLIC, 3);
} }
/** /**
* @param array|object|string $parentClass Class that has more than one child class, but it shouldn't. An array * @param array|object|string $parentClass Class that has more than one child class, but it shouldn't. An array
* of objects, strings, object or string. * of objects, strings, object or string.
* @param array $childClasses Child classes * @param array $childClasses Child classes
* @param string $expectedMessage Expected exception's message * @param string $expectedMessage Expected exception's message
* *
* @dataProvider provideParentAndChildClasses * @dataProvider provideParentAndChildClasses
*/ */
public function testConstructorMessage($parentClass, array $childClasses, $expectedMessage) public function testConstructorMessage($parentClass, array $childClasses, $expectedMessage)
{ {
$exception = new TooManyChildClassesException($parentClass, $childClasses); $exception = TooManyChildClassesException::create($parentClass, $childClasses);
static::assertEquals($expectedMessage, $exception->getMessage()); static::assertEquals($expectedMessage, $exception->getMessage());
} }

View File

@@ -16,14 +16,14 @@ use Meritoo\Common\Type\OopVisibilityType;
/** /**
* Test case of an exception used while length of given hexadecimal value of color is incorrect * Test case of an exception used while length of given hexadecimal value of color is incorrect
* *
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl> * @author Meritoo <github@meritoo.pl>
* @copyright Meritoo.pl * @copyright Meritoo <http://www.meritoo.pl>
*/ */
class IncorrectColorHexLengthExceptionTest extends BaseTestCase class IncorrectColorHexLengthExceptionTest extends BaseTestCase
{ {
public function testConstructorVisibilityAndArguments() public function testConstructorVisibilityAndArguments()
{ {
static::assertConstructorVisibilityAndArguments(IncorrectColorHexLengthException::class, OopVisibilityType::IS_PUBLIC, 1, 1); static::assertConstructorVisibilityAndArguments(IncorrectColorHexLengthException::class, OopVisibilityType::IS_PUBLIC, 3);
} }
/** /**
@@ -34,7 +34,7 @@ class IncorrectColorHexLengthExceptionTest extends BaseTestCase
*/ */
public function testConstructorMessage($color, $expectedMessage) public function testConstructorMessage($color, $expectedMessage)
{ {
$exception = new IncorrectColorHexLengthException($color); $exception = IncorrectColorHexLengthException::create($color);
static::assertEquals($expectedMessage, $exception->getMessage()); static::assertEquals($expectedMessage, $exception->getMessage());
} }

View File

@@ -16,14 +16,14 @@ use Meritoo\Common\Type\OopVisibilityType;
/** /**
* Test case of an exception used while given hexadecimal value of color is invalid * Test case of an exception used while given hexadecimal value of color is invalid
* *
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl> * @author Meritoo <github@meritoo.pl>
* @copyright Meritoo.pl * @copyright Meritoo <http://www.meritoo.pl>
*/ */
class InvalidColorHexValueExceptionTest extends BaseTestCase class InvalidColorHexValueExceptionTest extends BaseTestCase
{ {
public function testConstructorVisibilityAndArguments() public function testConstructorVisibilityAndArguments()
{ {
static::assertConstructorVisibilityAndArguments(InvalidColorHexValueException::class, OopVisibilityType::IS_PUBLIC, 1, 1); static::assertConstructorVisibilityAndArguments(InvalidColorHexValueException::class, OopVisibilityType::IS_PUBLIC, 3);
} }
/** /**
@@ -34,7 +34,7 @@ class InvalidColorHexValueExceptionTest extends BaseTestCase
*/ */
public function testConstructorMessage($color, $expectedMessage) public function testConstructorMessage($color, $expectedMessage)
{ {
$exception = new InvalidColorHexValueException($color); $exception = InvalidColorHexValueException::create($color);
static::assertEquals($expectedMessage, $exception->getMessage()); static::assertEquals($expectedMessage, $exception->getMessage());
} }

View File

@@ -0,0 +1,65 @@
<?php
/**
* (c) Meritoo.pl, http://www.meritoo.pl
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Meritoo\Common\Test\Exception\Regex;
use Generator;
use Meritoo\Common\Exception\Regex\InvalidHtmlAttributesException;
use Meritoo\Common\Test\Base\BaseTestCase;
use Meritoo\Common\Type\OopVisibilityType;
/**
* Test case of an exception used while html attributes are invalid
*
* @author Meritoo <github@meritoo.pl>
* @copyright Meritoo <http://www.meritoo.pl>
*/
class InvalidHtmlAttributesExceptionTest extends BaseTestCase
{
public function testConstructorVisibilityAndArguments()
{
static::assertConstructorVisibilityAndArguments(InvalidHtmlAttributesException::class, OopVisibilityType::IS_PUBLIC, 3);
}
/**
* @param string $htmlAttributes Invalid html attributes
* @param string $expectedMessage Expected exception's message
*
* @dataProvider provideHtmlAttributes
*/
public function testConstructorMessage($htmlAttributes, $expectedMessage)
{
$exception = InvalidHtmlAttributesException::create($htmlAttributes);
static::assertEquals($expectedMessage, $exception->getMessage());
}
/**
* Provides html attributes
*
* @return Generator
*/
public function provideHtmlAttributes()
{
$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'),
];
}
}

View File

@@ -16,14 +16,14 @@ use Meritoo\Common\Type\OopVisibilityType;
/** /**
* Test case of an exception used while url is invalid * Test case of an exception used while url is invalid
* *
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl> * @author Meritoo <github@meritoo.pl>
* @copyright Meritoo.pl * @copyright Meritoo <http://www.meritoo.pl>
*/ */
class InvalidUrlExceptionTest extends BaseTestCase class InvalidUrlExceptionTest extends BaseTestCase
{ {
public function testConstructorVisibilityAndArguments() public function testConstructorVisibilityAndArguments()
{ {
static::assertConstructorVisibilityAndArguments(InvalidUrlException::class, OopVisibilityType::IS_PUBLIC, 1, 1); static::assertConstructorVisibilityAndArguments(InvalidUrlException::class, OopVisibilityType::IS_PUBLIC, 3);
} }
/** /**
@@ -34,7 +34,7 @@ class InvalidUrlExceptionTest extends BaseTestCase
*/ */
public function testConstructorMessage($url, $expectedMessage) public function testConstructorMessage($url, $expectedMessage)
{ {
$exception = new InvalidUrlException($url); $exception = InvalidUrlException::create($url);
static::assertEquals($expectedMessage, $exception->getMessage()); static::assertEquals($expectedMessage, $exception->getMessage());
} }

View File

@@ -17,14 +17,14 @@ use Meritoo\Common\Type\OopVisibilityType;
* Test case of an exception used while the visibility of a property, a method or (as of PHP 7.1.0) a constant is * Test case of an exception used while the visibility of a property, a method or (as of PHP 7.1.0) a constant is
* unknown * unknown
* *
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl> * @author Meritoo <github@meritoo.pl>
* @copyright Meritoo.pl * @copyright Meritoo <http://www.meritoo.pl>
*/ */
class UnknownOopVisibilityTypeExceptionTest extends BaseTestCase class UnknownOopVisibilityTypeExceptionTest extends BaseTestCase
{ {
public function testConstructorVisibilityAndArguments() public function testConstructorVisibilityAndArguments()
{ {
static::assertConstructorVisibilityAndArguments(UnknownOopVisibilityTypeException::class, OopVisibilityType::IS_PUBLIC, 1, 1); static::assertConstructorVisibilityAndArguments(UnknownOopVisibilityTypeException::class, OopVisibilityType::IS_PUBLIC, 3);
} }
/** /**
@@ -35,7 +35,7 @@ class UnknownOopVisibilityTypeExceptionTest extends BaseTestCase
*/ */
public function testConstructorMessage($unknownType, $expectedMessage) public function testConstructorMessage($unknownType, $expectedMessage)
{ {
$exception = new UnknownOopVisibilityTypeException($unknownType); $exception = UnknownOopVisibilityTypeException::createException($unknownType);
static::assertEquals($expectedMessage, $exception->getMessage()); static::assertEquals($expectedMessage, $exception->getMessage());
} }

View File

@@ -1,45 +0,0 @@
<?php
/**
* (c) Meritoo.pl, http://www.meritoo.pl
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Meritoo\Common\Test\Utilities;
use Meritoo\Common\Test\Base\BaseTestCase;
use Meritoo\Common\Utilities\Bundle;
/**
* Test case of the useful methods for bundle
*
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl>
* @copyright Meritoo.pl
*/
class BundleTest extends BaseTestCase
{
public function verifyConstructor()
{
static::assertHasNoConstructor(Bundle::class);
}
public function testGetBundleViewPathEmptyPathAndBundle()
{
self::assertNull(Bundle::getBundleViewPath('', ''));
self::assertNull(Bundle::getBundleViewPath('test', ''));
self::assertNull(Bundle::getBundleViewPath('', 'test'));
}
public function testGetBundleViewPathWithDefaultExtension()
{
self::assertEquals('Lorem:Ipsum.html.twig', Bundle::getBundleViewPath('Ipsum', 'Lorem'));
self::assertEquals('LobortisTincidunt:FusceElementum.html.twig', Bundle::getBundleViewPath('FusceElementum', 'LobortisTincidunt'));
}
public function testGetBundleViewPathWithCustomExtension()
{
self::assertNull(Bundle::getBundleViewPath('Ipsum', 'Lorem', ''));
self::assertEquals('Lorem:Ipsum.js.twig', Bundle::getBundleViewPath('Ipsum', 'Lorem', 'js.twig'));
}
}

View File

@@ -1,134 +0,0 @@
<?php
/**
* (c) Meritoo.pl, http://www.meritoo.pl
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Meritoo\Common\Test\Utilities;
use Generator;
use Meritoo\Common\Test\Base\BaseTestCase;
use Meritoo\Common\Utilities\Locale;
/**
* Test case of the useful locale methods
*
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl>
* @copyright Meritoo.pl
*/
class LocaleTest extends BaseTestCase
{
public function verifyConstructor()
{
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 provideLanguageAndCountryCode
*/
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));
}
/**
* @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".
*
* @dataProvider provideCategoryAndLanguageCode
*/
public function testSetLocale($category, $languageCode)
{
self::assertTrue(Locale::setLocale($category, $languageCode));
}
/**
* Provides language and country code
*
* @return Generator
*/
public function provideLanguageAndCountryCode()
{
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',
];
}
/**
* Provides category and language
*
* @return Generator
*/
public function provideCategoryAndLanguageCode()
{
yield[
LC_ALL,
'fr',
];
yield[
LC_COLLATE,
'fr',
];
yield[
LC_CTYPE,
'en',
];
yield[
LC_NUMERIC,
'en',
];
}
}

View File

@@ -1,269 +0,0 @@
<?php
/**
* (c) Meritoo.pl, http://www.meritoo.pl
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Meritoo\Common\Test\Utilities;
use DateTime;
use Generator;
use Meritoo\Common\Exception\Reflection\CannotResolveClassNameException;
use Meritoo\Common\Exception\Reflection\MissingChildClassesException;
use Meritoo\Common\Exception\Reflection\TooManyChildClassesException;
use Meritoo\Common\Test\Base\BaseTestCase;
use Meritoo\Common\Test\Utilities\Reflection\A;
use Meritoo\Common\Test\Utilities\Reflection\B;
use Meritoo\Common\Test\Utilities\Reflection\C;
use Meritoo\Common\Test\Utilities\Reflection\D;
use Meritoo\Common\Test\Utilities\Reflection\E;
use Meritoo\Common\Utilities\Reflection;
use ReflectionProperty;
/**
* Test case of the useful reflection methods
*
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl>
* @copyright Meritoo.pl
*/
class ReflectionTest extends BaseTestCase
{
public function verifyConstructor()
{
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\Common\Test\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->expectException(CannotResolveClassNameException::class);
self::assertNull(Reflection::getChildClasses($invalidClass));
self::assertNull(Reflection::getChildClasses(123));
}
public function testGetChildClassesNotExistingClass()
{
$this->expectException(CannotResolveClassNameException::class);
self::assertEquals('', Reflection::getChildClasses('xyz'));
}
public function testGetChildClassesExistingClass()
{
/*
* Attention. I have to create instances of these classes to load them and be available while using
* get_declared_classes() function in the Reflection::getChildClasses() method. Without these instances the
* Reflection::getChildClasses() method returns an empty array even if given class has child classes.
*/
new A();
new B();
new C();
$effect = [
C::class,
];
self::assertEquals($effect, Reflection::getChildClasses(B::class));
$effect = [
B::class,
C::class,
];
self::assertEquals($effect, Reflection::getChildClasses(A::class));
}
public function testGetOneChildClassWithMissingChildClasses()
{
$this->expectException(MissingChildClassesException::class);
self::assertEquals('LoremIpsum', Reflection::getOneChildClass(C::class));
}
public function testGetOneChildClassWithTooManyChildClasses()
{
$this->expectException(TooManyChildClassesException::class);
self::assertEquals(B::class, Reflection::getOneChildClass(A::class));
self::assertEquals(C::class, Reflection::getOneChildClass(A::class));
}
public function testGetOneChildClass()
{
self::assertEquals(C::class, Reflection::getOneChildClass(B::class));
}
public function testGetMethods()
{
self::assertEquals(1, count(Reflection::getMethods(B::class, true)));
self::assertEquals(3, count(Reflection::getMethods(B::class)));
self::assertEquals(2, count(Reflection::getMethods(A::class)));
self::assertEquals(2, count(Reflection::getMethods(C::class, true)));
self::assertEquals(5, count(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)
{
$this->expectException(CannotResolveClassNameException::class);
self::assertNull(Reflection::usesTrait($class, $trait));
}
/**
* @param mixed $trait Empty value, e.g. ""
* @dataProvider provideEmptyValue
*/
public function testUsesTraitInvalidTrait($trait)
{
$this->expectException(CannotResolveClassNameException::class);
self::assertNull(Reflection::usesTrait(DateTime::class, $trait));
}
public function testUsesTraitExistingClass()
{
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));
}
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()
{
self::assertCount(1, Reflection::getProperties(B::class));
}
public function testGetPropertiesUsingFilter()
{
self::assertCount(1, Reflection::getProperties(B::class, ReflectionProperty::IS_PROTECTED));
self::assertCount(0, Reflection::getProperties(B::class, ReflectionProperty::IS_PRIVATE));
self::assertCount(1, Reflection::getProperties(B::class, ReflectionProperty::IS_PRIVATE, true));
}
public function testGetPropertiesWithParents()
{
self::assertCount(2, Reflection::getProperties(B::class, null, true));
}
/**
* Provides invalid class and trait
*
* @return Generator
*/
public function provideInvalidClassAndTrait()
{
yield[
'',
'',
];
yield[
null,
null,
];
yield[
0,
0,
];
yield[
[],
[],
];
}
}

View File

@@ -1,297 +0,0 @@
<?php
/**
* (c) Meritoo.pl, http://www.meritoo.pl
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Meritoo\Common\Utilities;
use Meritoo\Common\Test\Base\BaseTestCase;
/**
* Test case of the useful regular expressions methods
*
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl>
* @copyright Meritoo.pl
*/
class RegexTest extends BaseTestCase
{
private $simpleText;
private $camelCaseText;
public function verifyConstructor()
{
static::assertHasNoConstructor(Regex::class);
}
public function testGetCamelCaseParts()
{
$parts = [];
self::assertEquals($parts, Regex::getCamelCaseParts(''));
$parts = [
'lorem',
];
self::assertEquals($parts, Regex::getCamelCaseParts('lorem'));
$parts = [
'lorem',
'Ipsum',
'Dolor',
'Sit',
];
self::assertEquals($parts, Regex::getCamelCaseParts($this->camelCaseText));
$parts = [
'Lorem',
'Ipsum',
'Dolor',
'Sit',
];
$string = ucfirst($this->camelCaseText); // 'LoremIpsumDolorSit'
self::assertEquals($parts, Regex::getCamelCaseParts($string));
}
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));
}
public function testIsValidUrl()
{
$validUrls = [
'http://php.net',
'http://php.net/',
'http://php.net/docs.php',
'http://php.net/get-involved.php',
'http://php.net/manual/en/function.preg-match.php',
'http://domain.com/BigLetters',
'http://domain.com/Another-Big-Letters',
'http://domain.com/?a=1&b=c2d',
'http://domAin.COM/?a=1&B=c2D',
'http://domain.com/index.php?a=1&b=c2d',
'http://domain.com/another-page-2.php?a=1&b=c2d',
'https://domain.com',
'https://domain.com/',
];
$invalidUrls = [
'',
null,
false,
true,
0,
1,
123,
'123',
'http:',
'http://',
'http://abc',
'ftp://def',
];
foreach ($validUrls as $url) {
self::assertTrue(Regex::isValidUrl($url));
}
foreach ($invalidUrls as $url) {
self::assertFalse(Regex::isValidUrl($url));
}
}
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'));
}
public function testIsLetterOrDigit()
{
self::assertTrue(Regex::isLetterOrDigit('a'));
self::assertTrue(Regex::isLetterOrDigit(10));
self::assertFalse(Regex::isLetterOrDigit(';'));
}
public function testStartsWith()
{
$string = 'Lorem ipsum dolor sit amet';
$beginning = 'Lor';
self::assertTrue(Regex::startsWith($string, $beginning));
$beginning = 'L';
self::assertTrue(Regex::startsWith($string, $beginning));
$beginning = 'X';
self::assertFalse(Regex::startsWith($string, $beginning));
$string = '1234567890';
$beginning = '1';
self::assertTrue(Regex::startsWith($string, $beginning));
$beginning = ';';
self::assertFalse(Regex::startsWith($string, $beginning));
}
public function testStartsWithDirectorySeparator()
{
/*
* Slash as separator
*/
$separatorSlash = '/';
self::assertTrue(Regex::startsWithDirectorySeparator('/my/extra/directory', $separatorSlash));
self::assertFalse(Regex::startsWithDirectorySeparator('my/extra/directory', $separatorSlash));
/*
* Backslash as separator
*/
$separatorBackslash = '\\';
self::assertTrue(Regex::startsWithDirectorySeparator('\my\extra\directory', $separatorBackslash));
self::assertFalse(Regex::startsWithDirectorySeparator('my\extra\directory', $separatorBackslash));
}
public function testEndsWithDirectorySeparator()
{
/*
* 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 &raquo;'));
}
public function testContains()
{
self::assertTrue(Regex::contains($this->simpleText, 'ipsum'));
self::assertFalse(Regex::contains($this->simpleText, 'neque'));
}
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.
}
/**
* {@inheritdoc}
*/
protected function setUp()
{
parent::setUp();
$this->simpleText = 'lorem ipsum dolor sit';
$this->camelCaseText = str_replace(' ', '', lcfirst(ucwords($this->simpleText))); // 'loremIpsumDolorSit'
}
/**
* {@inheritdoc}
*/
protected function tearDown()
{
parent::tearDown();
unset($this->simpleText);
unset($this->camelCaseText);
}
}

View File

@@ -1,84 +0,0 @@
<?php
/**
* (c) Meritoo.pl, http://www.meritoo.pl
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Meritoo\Common\Test\Utilities;
use Meritoo\Common\Test\Base\BaseTestCase;
use Meritoo\Common\Utilities\Uri;
/**
* Test case of the useful uri methods (only static functions)
*
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl>
* @copyright Meritoo.pl
*/
class UriTest extends BaseTestCase
{
public function verifyConstructor()
{
static::assertHasNoConstructor(Uri::class);
}
public function testAddProtocolToUrl()
{
$http = 'http';
$https = 'https';
$url = 'my.domain/some/url';
$httpUrl = sprintf('%s://%s', $http, $url);
$httpsUrl = sprintf('%s://%s', $https, $url);
self::assertEquals($httpUrl, Uri::addProtocolToUrl($httpUrl));
self::assertEquals($httpUrl, Uri::addProtocolToUrl($url));
self::assertEquals($httpsUrl, Uri::addProtocolToUrl($url, $https));
self::assertEquals($httpsUrl, Uri::addProtocolToUrl($httpsUrl, $http));
}
/**
* @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.
*
* @dataProvider provideUrlsToReplenishProtocol
*/
public function testReplenishProtocol($expected, $url, $protocol = '')
{
self::assertSame($expected, Uri::replenishProtocol($url, $protocol));
}
/**
* Provides urls to replenish protocol
*
* @return \Generator
*/
public function provideUrlsToReplenishProtocol()
{
yield[
'://test',
'test',
'',
];
yield[
'ftp://lorem.ipsum',
'lorem.ipsum',
'ftp',
];
}
}

View File

@@ -0,0 +1,176 @@
<?php
/**
* (c) Meritoo.pl, http://www.meritoo.pl
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Meritoo\Common\Test\Test\Base;
use DateTime;
use Generator;
use Meritoo\Common\Test\Base\BaseTestCase;
use Meritoo\Common\Type\OopVisibilityType;
use Meritoo\Common\Utilities\GeneratorUtility;
/**
* Test case of the base test case with common methods and data providers
*
* @author Meritoo <github@meritoo.pl>
* @copyright Meritoo <http://www.meritoo.pl>
*/
class BaseTestCaseTest extends BaseTestCase
{
public function testConstructor()
{
static::assertConstructorVisibilityAndArguments(BaseTestCase::class, OopVisibilityType::IS_PUBLIC, 3);
}
public function testProvideEmptyValue()
{
$elements = [
[''],
[' '],
[null],
[0],
[false],
[[]],
];
$generator = (new SimpleTestCase())->provideEmptyValue();
self::assertEquals($elements, GeneratorUtility::getGeneratorElements($generator));
}
public function testProvideBooleanValue()
{
$elements = [
[false],
[true],
];
$generator = (new SimpleTestCase())->provideBooleanValue();
self::assertEquals($elements, GeneratorUtility::getGeneratorElements($generator));
}
public function testProvideDateTimeInstance()
{
$dateFormat = 'Y-m-d H:i';
$expectedElements = [
[new DateTime()],
[new DateTime('yesterday')],
[new DateTime('now')],
[new DateTime('tomorrow')],
];
$generator = (new SimpleTestCase())->provideDateTimeInstance();
$generatedElements = GeneratorUtility::getGeneratorElements($generator);
/* @var DateTime $instance1 */
$instance1 = $generatedElements[0][0];
/* @var DateTime $instance2 */
$instance2 = $generatedElements[1][0];
/* @var DateTime $instance3 */
$instance3 = $generatedElements[2][0];
/* @var DateTime $instance4 */
$instance4 = $generatedElements[3][0];
self::assertCount(count($expectedElements), $generatedElements);
self::assertEquals($instance1->format($dateFormat), (new DateTime())->format($dateFormat));
self::assertEquals($instance2->format($dateFormat), (new DateTime('yesterday'))->format($dateFormat));
self::assertEquals($instance3->format($dateFormat), (new DateTime('now'))->format($dateFormat));
self::assertEquals($instance4->format($dateFormat), (new DateTime('tomorrow'))->format($dateFormat));
}
public function testProvideDateTimeRelativeFormat()
{
$elements = [
['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'],
];
$generator = (new SimpleTestCase())->provideDateTimeRelativeFormat();
self::assertEquals($elements, GeneratorUtility::getGeneratorElements($generator));
}
public function testProvideNotExistingFilePath()
{
$elements = [
['lets-test.doc'],
['lorem/ipsum.jpg'],
['surprise/me/one/more/time.txt'],
];
$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',
];
}
}
/**
* Simple test case
*
* @author Meritoo <github@meritoo.pl>
* @copyright Meritoo <http://www.meritoo.pl>
*/
class SimpleTestCase extends BaseTestCase
{
}

View File

@@ -9,17 +9,22 @@
namespace Meritoo\Common\Test\Type\Base; namespace Meritoo\Common\Test\Type\Base;
use Generator; use Generator;
use Meritoo\Common\Test\Base\BaseTestCase;
use Meritoo\Common\Type\Base\BaseType; use Meritoo\Common\Type\Base\BaseType;
use PHPUnit\Framework\TestCase;
/** /**
* Test case of the base / abstract type of something * Test case of the base / abstract type of something
* *
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl> * @author Meritoo <github@meritoo.pl>
* @copyright Meritoo.pl * @copyright Meritoo <http://www.meritoo.pl>
*/ */
class BaseTypeTest extends TestCase class BaseTypeTest extends BaseTestCase
{ {
public function testConstructor()
{
static::assertHasNoConstructor(BaseType::class);
}
/** /**
* @param BaseType $type Type of something * @param BaseType $type Type of something
* @param array $expectedTypes Expected concrete types of given instance of type * @param array $expectedTypes Expected concrete types of given instance of type
@@ -179,8 +184,8 @@ class BaseTypeTest extends TestCase
/** /**
* Empty type of something used for testing * Empty type of something used for testing
* *
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl> * @author Meritoo <github@meritoo.pl>
* @copyright Meritoo.pl * @copyright Meritoo <http://www.meritoo.pl>
*/ */
class TestEmptyType extends BaseType class TestEmptyType extends BaseType
{ {
@@ -189,8 +194,8 @@ class TestEmptyType extends BaseType
/** /**
* Type of something used for testing * Type of something used for testing
* *
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl> * @author Meritoo <github@meritoo.pl>
* @copyright Meritoo.pl * @copyright Meritoo <http://www.meritoo.pl>
*/ */
class TestType extends BaseType class TestType extends BaseType
{ {

View File

@@ -14,8 +14,8 @@ use Meritoo\Common\Type\DatePartType;
/** /**
* Test case of the type of date part, e.g. "year" * Test case of the type of date part, e.g. "year"
* *
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl> * @author Meritoo <github@meritoo.pl>
* @copyright Meritoo.pl * @copyright Meritoo <http://www.meritoo.pl>
*/ */
class DatePartTypeTest extends BaseTypeTestCase class DatePartTypeTest extends BaseTypeTestCase
{ {

View File

@@ -6,21 +6,21 @@
* file that was distributed with this source code. * file that was distributed with this source code.
*/ */
namespace Meritoo\Common\Test\Utilities; namespace Meritoo\Common\Test\Type;
use DateTime; use DateTime;
use Generator; use Generator;
use Meritoo\Common\Test\Base\BaseTestCase; use Meritoo\Common\Test\Base\BaseTypeTestCase;
use Meritoo\Common\Type\DatePeriod;
use Meritoo\Common\Type\OopVisibilityType; use Meritoo\Common\Type\OopVisibilityType;
use Meritoo\Common\Utilities\DatePeriod;
/** /**
* Test case of date's period * Test case of date's period
* *
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl> * @author Meritoo <github@meritoo.pl>
* @copyright Meritoo.pl * @copyright Meritoo <http://www.meritoo.pl>
*/ */
class DatePeriodTest extends BaseTestCase class DatePeriodTest extends BaseTypeTestCase
{ {
public function testConstructorVisibilityAndArguments() public function testConstructorVisibilityAndArguments()
{ {
@@ -58,33 +58,6 @@ class DatePeriodTest extends BaseTestCase
self::assertEquals($endDate, $period->getEndDate()); self::assertEquals($endDate, $period->getEndDate());
} }
/**
* @param mixed $period Empty value, e.g. ""
* @dataProvider provideEmptyValue
*/
public function testIsCorrectPeriodEmptyPeriod($period)
{
self::assertFalse(DatePeriod::isCorrectPeriod($period));
}
/**
* @param int $period Incorrect period to verify
* @dataProvider provideIncorrectPeriod
*/
public function testIsCorrectPeriodIncorrectPeriod($period)
{
self::assertFalse(DatePeriod::isCorrectPeriod($period));
}
/**
* @param int $period The period to verify
* @dataProvider providePeriod
*/
public function testIsCorrectPeriod($period)
{
self::assertTrue(DatePeriod::isCorrectPeriod($period));
}
/** /**
* @param DatePeriod $period The date period to verify * @param DatePeriod $period The date period to verify
* @param string $format Format used to format the date * @param string $format Format used to format the date
@@ -142,36 +115,6 @@ class DatePeriodTest extends BaseTestCase
]; ];
} }
/**
* Provides incorrect period
*
* @return Generator
*/
public function provideIncorrectPeriod()
{
yield[-1];
yield[0];
yield[10];
}
/**
* Provides period to verify
*
* @return Generator
*/
public function providePeriod()
{
yield[DatePeriod::LAST_WEEK];
yield[DatePeriod::THIS_WEEK];
yield[DatePeriod::NEXT_WEEK];
yield[DatePeriod::LAST_MONTH];
yield[DatePeriod::THIS_MONTH];
yield[DatePeriod::NEXT_MONTH];
yield[DatePeriod::LAST_YEAR];
yield[DatePeriod::THIS_YEAR];
yield[DatePeriod::NEXT_YEAR];
}
/** /**
* Provides period and incorrect format of date to verify * Provides period and incorrect format of date to verify
* *
@@ -270,4 +213,68 @@ class DatePeriodTest extends BaseTestCase
'2002-02-02 00:00', '2002-02-02 00:00',
]; ];
} }
/**
* Returns all expected types of the tested type
*
* @return array
*/
protected function getAllExpectedTypes()
{
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,
];
}
/**
* {@inheritdoc}
*/
protected function getTestedTypeInstance()
{
return new DatePeriod();
}
/**
* {@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,
];
}
} }

View File

@@ -14,8 +14,8 @@ use Meritoo\Common\Utilities\Arrays;
/** /**
* Test case of the useful arrays methods * Test case of the useful arrays methods
* *
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl> * @author Meritoo <github@meritoo.pl>
* @copyright Meritoo.pl * @copyright Meritoo <http://www.meritoo.pl>
*/ */
class ArraysTest extends BaseTestCase class ArraysTest extends BaseTestCase
{ {
@@ -25,7 +25,7 @@ class ArraysTest extends BaseTestCase
private $complexArray; private $complexArray;
private $superComplexArray; private $superComplexArray;
public function verifyConstructor() public function testConstructor()
{ {
static::assertHasNoConstructor(Arrays::class); static::assertHasNoConstructor(Arrays::class);
} }

View File

@@ -0,0 +1,252 @@
<?php
/**
* (c) Meritoo.pl, http://www.meritoo.pl
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Meritoo\Common\Test\Utilities;
use Generator;
use Meritoo\Common\Exception\Bundle\IncorrectBundleNameException;
use Meritoo\Common\Test\Base\BaseTestCase;
use Meritoo\Common\Utilities\Bundle;
/**
* Test case of the useful methods for bundle
*
* @author Meritoo <github@meritoo.pl>
* @copyright Meritoo <http://www.meritoo.pl>
*/
class BundleTest extends BaseTestCase
{
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"
*
* @throws IncorrectBundleNameException
* @dataProvider provideEmptyViewPathAndBundle
*/
public function testGetBundleViewPathUsingEmptyPathAndBundle($viewPath, $bundleName)
{
self::assertNull(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"
*
* @dataProvider provideViewPathAndIncorrectBundleName
*/
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?';
$message = sprintf($template, $bundleName);
$this->setExpectedException(IncorrectBundleNameException::class, $message);
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")
*
* @throws IncorrectBundleNameException
* @dataProvider provideFullAndShortBundleName
*/
public function testGetShortBundleName($fullBundleName, $shortBundleName)
{
self::assertEquals($shortBundleName, Bundle::getShortBundleName($fullBundleName));
}
/**
* Provides empty path of the view / template and/or name of bundle
*
* @return Generator
*/
public function provideEmptyViewPathAndBundle()
{
yield[
'',
'',
];
yield[
'test',
'',
];
yield[
'',
'test',
];
}
/**
* 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',
];
}
/**
* 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',
];
}
}

View File

@@ -15,8 +15,8 @@ use Meritoo\Common\Utilities\Composer;
/** /**
* Test case of the useful Composer-related methods * Test case of the useful Composer-related methods
* *
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl> * @author Meritoo <github@meritoo.pl>
* @copyright Meritoo.pl * @copyright Meritoo <http://www.meritoo.pl>
*/ */
class ComposerTest extends BaseTestCase class ComposerTest extends BaseTestCase
{ {
@@ -27,7 +27,7 @@ class ComposerTest extends BaseTestCase
*/ */
private $composerJsonPath; private $composerJsonPath;
public function verifyConstructor() public function testConstructor()
{ {
static::assertHasNoConstructor(Composer::class); static::assertHasNoConstructor(Composer::class);
} }
@@ -88,6 +88,6 @@ class ComposerTest extends BaseTestCase
{ {
parent::setUp(); parent::setUp();
$this->composerJsonPath = $this->getFilePathToTests(Composer::FILE_NAME_MAIN); $this->composerJsonPath = $this->getFilePathForTesting(Composer::FILE_NAME_MAIN);
} }
} }

View File

@@ -11,19 +11,20 @@ namespace Meritoo\Common\Test\Utilities;
use DateInterval; use DateInterval;
use DateTime; use DateTime;
use Generator; use Generator;
use Meritoo\Common\Exception\Date\UnknownDatePartTypeException; use Meritoo\Common\Exception\Type\UnknownDatePartTypeException;
use Meritoo\Common\Test\Base\BaseTestCase; use Meritoo\Common\Test\Base\BaseTestCase;
use Meritoo\Common\Type\DatePeriod;
use Meritoo\Common\Utilities\Date; use Meritoo\Common\Utilities\Date;
/** /**
* Test case of the Date methods (only static functions) * Test case of the Date methods (only static functions)
* *
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl> * @author Meritoo <github@meritoo.pl>
* @copyright Meritoo.pl * @copyright Meritoo <http://www.meritoo.pl>
*/ */
class DateTest extends BaseTestCase class DateTest extends BaseTestCase
{ {
public function verifyConstructor() public function testConstructor()
{ {
static::assertHasNoConstructor(Date::class); static::assertHasNoConstructor(Date::class);
} }
@@ -223,7 +224,7 @@ class DateTest extends BaseTestCase
*/ */
public function testGetDayOfWeekIncorrectValues($year, $month, $day) public function testGetDayOfWeekIncorrectValues($year, $month, $day)
{ {
$this->expectException(UnknownDatePartTypeException::class); $this->setExpectedException(UnknownDatePartTypeException::class);
self::assertEmpty(Date::getDayOfWeek($year, $month, $day)); self::assertEmpty(Date::getDayOfWeek($year, $month, $day));
} }
@@ -506,6 +507,35 @@ class DateTest extends BaseTestCase
self::assertTrue($randomDate >= $intervalMinDate && $randomDate <= $intervalMaxDate); self::assertTrue($randomDate >= $intervalMinDate && $randomDate <= $intervalMaxDate);
} }
/**
* @param mixed $period Empty value, e.g. ""
* @dataProvider provideEmptyValue
*/
public function testGetDatesForPeriodUsingEmptyPeriod($period)
{
self::assertNull(Date::getDatesForPeriod($period));
}
/**
* @param int $period Incorrect period to verify
* @dataProvider provideIncorrectPeriod
*/
public function testGetDatesForPeriodUsingIncorrectPeriod($period)
{
self::assertNull(Date::getDatesForPeriod($period));
}
/**
* @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)
{
self::assertEquals($expected, Date::getDatesForPeriod($period));
}
/** /**
* Provides incorrect invalidCount of DateTime * Provides incorrect invalidCount of DateTime
* *
@@ -758,4 +788,112 @@ class DateTest extends BaseTestCase
50, 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)
),
];
}
} }

View File

@@ -14,12 +14,12 @@ use Meritoo\Common\Utilities\GeneratorUtility;
/** /**
* Test case of the useful methods for the Generator class * Test case of the useful methods for the Generator class
* *
* @author Krzysztof Niziol <krzysztof.niziol@meritoo.pl> * @author Meritoo <github@meritoo.pl>
* @copyright Meritoo.pl * @copyright Meritoo <http://www.meritoo.pl>
*/ */
class GeneratorUtilityTest extends BaseTestCase class GeneratorUtilityTest extends BaseTestCase
{ {
public function verifyConstructor() public function testConstructor()
{ {
static::assertHasNoConstructor(GeneratorUtility::class); static::assertHasNoConstructor(GeneratorUtility::class);
} }

View File

@@ -0,0 +1,224 @@
<?php
/**
* (c) Meritoo.pl, http://www.meritoo.pl
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Meritoo\Common\Test\Utilities;
use Generator;
use Meritoo\Common\Test\Base\BaseTestCase;
use Meritoo\Common\Utilities\Locale;
use ReflectionException;
/**
* Test case of the useful locale methods
*
* @author Meritoo <github@meritoo.pl>
* @copyright Meritoo <http://www.meritoo.pl>
*/
class LocaleTest extends BaseTestCase
{
/**
* @throws ReflectionException
*/
public function testConstructor()
{
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.
* @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 testGetLocale($category, $languageCode, $countryCode, $expectedLocale)
{
Locale::setLocale($category, $languageCode, $countryCode);
self::assertEquals($expectedLocale, Locale::getLocale($category));
}
/**
* 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',
];
}
/**
* 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',
];
}
}

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