Skip to content

Commit 2760ac6

Browse files
Initial commit
0 parents  commit 2760ac6

37 files changed

+2335
-0
lines changed

.gitignore

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
.idea/
2+
vendor/
3+
.php_cs.cache
4+
.phpunit.result.cache
5+
composer.lock
6+
phpunit.xml
7+
build/

.php_cs

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
<?php
2+
use PhpCsFixer\Config;
3+
use PhpCsFixer\Finder;
4+
5+
return Config::create()
6+
->setUsingCache(true)
7+
->setFinder(
8+
Finder::create()
9+
->exclude([
10+
'vendor',
11+
])
12+
->in(__DIR__)
13+
)
14+
->setRules([
15+
'@PSR2' => true,
16+
'class_definition' => [
17+
'multiLineExtendsEachSingleLine' => true,
18+
],
19+
'array_syntax' => ['syntax' => 'short'],
20+
'binary_operator_spaces' => [
21+
'align_double_arrow' => false,
22+
'align_equals' => false,
23+
],
24+
'concat_space' => [
25+
'spacing' => 'one',
26+
],
27+
'general_phpdoc_annotation_remove' => [
28+
'author',
29+
'package',
30+
],
31+
'no_multiline_whitespace_before_semicolons' => true,
32+
'no_null_property_initialization' => true,
33+
'no_useless_else' => true,
34+
'no_useless_return' => true,
35+
'ordered_class_elements' => [
36+
'order' => [
37+
'use_trait',
38+
'constant_public',
39+
'constant_protected',
40+
'constant_private',
41+
'property_public',
42+
'property_protected',
43+
'property_private',
44+
'construct'
45+
]
46+
],
47+
'ordered_imports' => [
48+
'sortAlgorithm' => 'alpha'
49+
],
50+
'phpdoc_order' => true,
51+
'phpdoc_types_order' => [
52+
'null_adjustment' => 'always_last'
53+
],
54+
'phpdoc_single_line_var_spacing' => true,
55+
'phpdoc_annotation_without_dot' => true,
56+
'yoda_style' => false,
57+
'blank_line_before_statement' => [
58+
'statements' => [
59+
'return'
60+
]
61+
],
62+
'no_blank_lines_after_class_opening' => true
63+
]);

.scrutinizer.yml

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
build:
2+
tests:
3+
override:
4+
- command: vendor/bin/phpunit --coverage-clover=build/clover.xml
5+
coverage:
6+
file: build/clover.xml
7+
format: clover
8+
9+
filter:
10+
excluded_paths:
11+
- tests/*

.travis.yml

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
language: php
2+
3+
php:
4+
- 7.1
5+
- 7.2
6+
- 7.3
7+
- 7.4snapshot
8+
# php8 is not supported yet
9+
#- nightly
10+
11+
env:
12+
matrix:
13+
- DEPENDENCIES="high"
14+
- DEPENDENCIES="low"
15+
global:
16+
- DEFAULT_COMPOSER_FLAGS="--prefer-dist --no-interaction --no-ansi --no-progress --no-suggest"
17+
18+
matrix:
19+
fast_finish: true
20+
#allow_failures:
21+
#- php: nightly
22+
23+
install:
24+
- if [[ "$DEPENDENCIES" = 'high' ]]; then travis_retry composer update $DEFAULT_COMPOSER_FLAGS; fi
25+
- if [[ "$DEPENDENCIES" = 'low' ]]; then travis_retry composer update $DEFAULT_COMPOSER_FLAGS --prefer-lowest; fi
26+
27+
cache:
28+
directories:
29+
- $HOME/.composer/cache

README.md

+153
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
# Lamoda multi-env
2+
Library that provides classes to work with envs in multitenant environment
3+
4+
Library based on params passed to it on initialization stage will decide which env variable should be used
5+
for current request.
6+
7+
## Installation
8+
9+
1. Install library with composer:
10+
```bash
11+
composer require lamoda/multi-env
12+
```
13+
14+
## Usage
15+
16+
### Library usage to work in not multitenant environment (could be useful in development mode)
17+
18+
```php
19+
<?php
20+
21+
use \Lamoda\MultiEnv\Strategy\RawEnvResolvingStrategy;
22+
use \Lamoda\MultiEnv\Decorator\EnvProviderDecorator;
23+
24+
// RawEnvResolvingStrategy - just wrap native PHP get_env function call
25+
$strategy = new RawEnvResolvingStrategy();
26+
EnvProviderDecorator::init($strategy);
27+
28+
// Will be search original TEST_ENV env variable
29+
EnvProviderDecorator::getEnv('TEST_ENV');
30+
```
31+
32+
### Library usage to work in multitenant environment
33+
34+
```php
35+
<?php
36+
37+
use \Lamoda\MultiEnv\Strategy\HostBasedEnvResolvingStrategy;
38+
use \Lamoda\MultiEnv\Decorator\EnvProviderDecorator;
39+
40+
/*
41+
* Pass as first param one of available HostDetectorInterface implementations
42+
* Pass as second param one of available EnvNameFormatterInterface implementations
43+
*/
44+
$strategy = new HostBasedEnvResolvingStrategy($hostDetector, $envFormatter);
45+
EnvProviderDecorator::init($strategy);
46+
47+
/*
48+
* Will search env with some specific prefix/postfix resolved by HostDetectorInterface
49+
* For example host_id__TEST_ENV
50+
*/
51+
EnvProviderDecorator::getEnv('TEST_ENV');
52+
```
53+
54+
### Library set up with multiple strategy
55+
```php
56+
<?php
57+
58+
use \Lamoda\MultiEnv\Strategy\FirstSuccessfulEnvResolvingStrategy;
59+
use \Lamoda\MultiEnv\Strategy\RawEnvResolvingStrategy;
60+
use \Lamoda\MultiEnv\Strategy\HostBasedEnvResolvingStrategy;
61+
use \Lamoda\MultiEnv\HostDetector\FirstSuccessfulHostDetector;
62+
use \Lamoda\MultiEnv\HostDetector\CliArgsBasedHostDetector;
63+
use \Lamoda\MultiEnv\HostDetector\ServerHeadersBasedHostDetector;
64+
use \Lamoda\MultiEnv\Formatter\PrefixEnvNameFormatter;
65+
use \Lamoda\MultiEnv\HostDetector\Factory\GetOptAdapterFactory;
66+
use \Lamoda\MultiEnv\Decorator\EnvProviderDecorator;
67+
68+
$rawEnvResolvingStrategy = new RawEnvResolvingStrategy();
69+
$hostBasedEnvResolvingStrategy = new HostBasedEnvResolvingStrategy(
70+
new FirstSuccessfulHostDetector([
71+
new ServerHeadersBasedHostDetector('HTTP_X_TEST_HEADER'),
72+
new CliArgsBasedHostDetector('host_id', GetOptAdapterFactory::build())
73+
]),
74+
new PrefixEnvNameFormatter('___')
75+
);
76+
77+
$firstSuccessfulStrategy = new FirstSuccessfulEnvResolvingStrategy([
78+
$rawEnvResolvingStrategy,
79+
$hostBasedEnvResolvingStrategy
80+
]);
81+
EnvProviderDecorator::init($firstSuccessfulStrategy);
82+
83+
/*
84+
* Try find original env 'TEST_ENV' first.
85+
* If original env not found than try to find env with some specific prefix/postfix resolved by HostDetectorInterface.
86+
* For example host_id__TEST_ENV
87+
*/
88+
EnvProviderDecorator::getEnv('TEST_ENV');
89+
```
90+
91+
## Available HostDetectorInterface implementations
92+
93+
1. __\Lamoda\MultiEnv\HostDetector\ServerHeadersBasedHostDetector__ - use to identificate host via HTTP request
94+
```php
95+
<?php
96+
97+
use \Lamoda\MultiEnv\HostDetector\ServerHeadersBasedHostDetector;
98+
use \Lamoda\MultiEnv\HostDetector\Exception\HostDetectorException;
99+
100+
/*
101+
* Search passed needle in $_SERVER header. Use found value to identify current host
102+
* Throw HostDetectorException when passed empty needle
103+
*/
104+
$headerBasedHostDetector = new ServerHeadersBasedHostDetector('HTTP_X_SOME_HEADER');
105+
$hostId = $headerBasedHostDetector->getCurrentHost();
106+
```
107+
2. __\Lamoda\MultiEnv\HostDetector\CliArgsBasedHostDetector__ - use to identificate host via Cli script run
108+
```php
109+
<?php
110+
111+
use \Lamoda\MultiEnv\HostDetector\CliArgsBasedHostDetector;
112+
use \Lamoda\MultiEnv\HostDetector\Factory\GetOptAdapterFactory;
113+
use \Lamoda\MultiEnv\HostDetector\Exception\HostDetectorException;
114+
115+
/*
116+
* Search passed needle in CLI args. Use found value to identify current host
117+
* Throw HostDetectorException when passed empty needle
118+
*/
119+
$cliArgsBasedHostDetector = new CliArgsBasedHostDetector('needle', GetOptAdapterFactory::build());
120+
$hostId = $cliArgsBasedHostDetector->getCurrentHost();
121+
```
122+
123+
3. __\Lamoda\MultiEnv\HostDetector\FirstSuccessfulHostDetector__ - use to aggregate multiple HostDetector's
124+
```php
125+
<?php
126+
127+
use \Lamoda\MultiEnv\HostDetector\ServerHeadersBasedHostDetector;
128+
use \Lamoda\MultiEnv\HostDetector\CliArgsBasedHostDetector;
129+
use \Lamoda\MultiEnv\HostDetector\Factory\GetOptAdapterFactory;
130+
use \Lamoda\MultiEnv\HostDetector\FirstSuccessfulHostDetector;
131+
132+
// Iterate through passed HostDetector's and return first not empty HostId
133+
$firstSuccessfulHostDetector = new FirstSuccessfulHostDetector([
134+
new CliArgsBasedHostDetector('some_host_id', GetOptAdapterFactory::build()),
135+
new ServerHeadersBasedHostDetector('HTTP_HOST_ID')
136+
]);
137+
$hostId = $firstSuccessfulHostDetector->getCurrentHost();
138+
```
139+
140+
## Available EnvNameFormatterInterface implementations
141+
1. __\Lamoda\MultiEnv\Formatter\PrefixEnvNameFormatter__ - format env name. Combine __original env name__, __delimiter__,
142+
__host id__ in order \*__host id__\*, \*__delimiter__\*, \*__original env name__\*
143+
```php
144+
<?php
145+
146+
use \Lamoda\MultiEnv\Formatter\PrefixEnvNameFormatter;
147+
use \Lamoda\MultiEnv\Model\HostId;
148+
use \Lamoda\MultiEnv\Formatter\Exception\FormatterException;
149+
150+
$formatter = new PrefixEnvNameFormatter('__');
151+
// Throw FormatterException if passed empty originalEnvName
152+
$formatterName = $formatter->formatEnvName('originalEnvName', new HostId('test_host'));
153+
```

composer.json

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{
2+
"name": "lamoda/multi-env",
3+
"description": "Library that provides classes to work with envs in multitenant environment",
4+
"type": "library",
5+
"license": "MIT",
6+
"require": {
7+
"php": "^7.1",
8+
"ulrichsg/getopt-php": "^3.2"
9+
},
10+
"require-dev": {
11+
"phpunit/phpunit": "^7.5",
12+
"friendsofphp/php-cs-fixer": "^2.14"
13+
},
14+
"autoload": {
15+
"psr-4": {
16+
"Lamoda\\MultiEnv\\": "src/"
17+
}
18+
},
19+
"autoload-dev": {
20+
"psr-4": {
21+
"Lamoda\\MultiEnvTests\\": "tests/"
22+
}
23+
},
24+
"config": {
25+
"sort-packages": true
26+
}
27+
}

phpunit.xml.dist

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/7.5/phpunit.xsd"
4+
backupGlobals="false"
5+
bootstrap="vendor/autoload.php"
6+
colors="true"
7+
convertErrorsToExceptions="true"
8+
convertNoticesToExceptions="true"
9+
convertWarningsToExceptions="true"
10+
verbose="true">
11+
<testsuites>
12+
<testsuite name="default">
13+
<directory suffix="Test.php">tests</directory>
14+
</testsuite>
15+
</testsuites>
16+
17+
<filter>
18+
<whitelist processUncoveredFilesFromWhitelist="true">
19+
<directory suffix=".php">src</directory>
20+
</whitelist>
21+
</filter>
22+
</phpunit>
+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Lamoda\MultiEnv\Decorator;
6+
7+
use Lamoda\MultiEnv\Decorator\Exception\EnvProviderDecoratorException;
8+
use Lamoda\MultiEnv\Strategy\EnvResolvingStrategyInterface;
9+
10+
final class EnvProviderDecorator
11+
{
12+
/**
13+
* @var ?EnvResolvingStrategyInterface $resolvingStrategy
14+
*/
15+
private static $resolvingStrategy;
16+
17+
public static function init(EnvResolvingStrategyInterface $resolvingStrategy): void
18+
{
19+
self::$resolvingStrategy = $resolvingStrategy;
20+
}
21+
22+
public static function resetStrategy(): void
23+
{
24+
self::$resolvingStrategy = null;
25+
}
26+
27+
/**
28+
* @param string $envName
29+
* @throws EnvProviderDecoratorException
30+
* @return string
31+
*/
32+
public static function getEnv(string $envName): string
33+
{
34+
if (self::$resolvingStrategy === null) {
35+
throw EnvProviderDecoratorException::becauseDecoratorNotInitialised();
36+
}
37+
38+
return self::$resolvingStrategy->getEnv($envName);
39+
}
40+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Lamoda\MultiEnv\Decorator\Exception;
6+
7+
use Lamoda\MultiEnv\Exception\EnvProviderExceptionInterface;
8+
9+
final class EnvProviderDecoratorException extends \RuntimeException implements EnvProviderExceptionInterface
10+
{
11+
public static function becauseDecoratorNotInitialised(): self
12+
{
13+
return new self('Decorator not initialised. Run init method first');
14+
}
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Lamoda\MultiEnv\Exception;
6+
7+
interface EnvProviderExceptionInterface
8+
{
9+
}

0 commit comments

Comments
 (0)