Completed
Pull Request — master (#1)
by Joao
02:03
created

Definition::environmentVar()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 1
1
<?php
2
/**
3
 * User: jg
4
 * Date: 26/05/17
5
 * Time: 00:56
6
 */
7
8
namespace ByJG\Config;
9
10
use ByJG\Config\Exception\NotFoundException;
11
use Psr\SimpleCache\CacheInterface;
12
13
class Definition
14
{
15
    private $lastEnv = null;
16
17
    private $environments = [];
18
19
    private $envVar = 'APPLICATION_ENV';
20
21
    /**
22
     * @var CacheInterface[]
23
     */
24
    private $cache = [];
25
26
    /**
27
     * @var \DateInterval[]
28
     */
29
    private $cacheTTL = [];
30
31
    private function loadConfig($currentConfig, $env)
32
    {
33
        $file = __DIR__ . '/../../../../config/config-' . $env .  '.php';
34
35
        if (!file_exists($file)) {
36
            $file = __DIR__ . '/../config/config-' . $env .  '.php';
37
        }
38
39
        if (!file_exists($file)) {
40
            throw new NotFoundException(
41
                "The config file '"
42
                . "config-$env.php'"
43
                . 'does not found'
44
            );
45
        }
46
47
        $config = (include $file);
48
        return array_merge($config, $currentConfig);
49
    }
50
51
    public function setCache(CacheInterface $cache, $env = "live")
52
    {
53
        $this->cache[$env] = $cache;
54
        $this->cacheTTL[$env] = new \DateInterval('P7D');
55
        return $this;
56
    }
57
58
    public function setCacheTTL(\DateInterval $ttl, $env = "live")
59
    {
60
        if (!isset($this->cache[$env])) {
61
            throw new \Exception('Environment does not exists. Could not set Cache TTL.');
62
        }
63
64
        $this->cacheTTL[$env] = $ttl;
65
    }
66
67
    public function addEnvironment($env)
68
    {
69
        if (isset($this->environments[$env])) {
70
            throw new \InvalidArgumentException("Environment '$env' already exists");
71
        }
72
        $this->lastEnv = $env;
73
        $this->environments[$env] = [];
74
        return $this;
75
    }
76
77
    public function inheritFrom($env)
78
    {
79
        $this->environments[$this->lastEnv][] = $env;
80
        return $this;
81
    }
82
83
    public function environmentVar($var)
84
    {
85
        $this->envVar = $var;
86
    }
87
88
    public function getCurrentEnv()
89
    {
90
        $env = getenv($this->envVar);
91
        if (empty($env)) {
92
            throw new \InvalidArgumentException("The environment variable '$this->envVar' is not set");
93
        }
94
        return  $env;
95
    }
96
97
    /**
98
     * @param string|null $env
99
     * @return \ByJG\Config\Container
100
     */
101
    public function build($env = null)
102
    {
103
        if (empty($env)) {
104
            $env = $this->getCurrentEnv();
105
        }
106
107
        if (!isset($this->environments[$env])) {
108
            throw new \InvalidArgumentException("Environment '$env' does not defined");
109
        }
110
111
        $container = null;
0 ignored issues
show
Unused Code introduced by
$container is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
112
        if (isset($this->cache[$env])) {
113
            $container = $this->cache[$env]->get("container-cache-$env");
114
            if (!is_null($container)) {
115
                return $container;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $container; (object|integer|double|string|array|boolean) is incompatible with the return type documented by ByJG\Config\Definition::build of type ByJG\Config\Container.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
116
            }
117
        }
118
119
        $config = [];
120
        $config = $this->loadConfig($config, $env);
121
        foreach ($this->environments[$env] as $environment) {
122
            $config = $this->loadConfig($config, $environment);
123
        }
124
125
        $container = new Container($config);
126
        if (isset($this->cache[$env])) {
127
            $this->cache[$env]->set("container-cache-$env", $container, $this->cacheTTL[$env]);
0 ignored issues
show
Documentation introduced by
$this->cacheTTL[$env] is of type object<DateInterval>, but the function expects a null|integer|object<Psr\SimpleCache\DateInterval>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
128
        }
129
        return $container;
130
    }
131
}
132