ContextBuilder   A
last analyzed

Complexity

Total Complexity 16

Size/Duplication

Total Lines 179
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Test Coverage

Coverage 90.57%

Importance

Changes 4
Bugs 0 Features 0
Metric Value
wmc 16
c 4
b 0
f 0
lcom 1
cbo 2
dl 0
loc 179
ccs 48
cts 53
cp 0.9057
rs 10

10 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 2
A setFormat() 0 6 1
A from() 0 6 1
A add() 0 6 1
A run() 0 6 1
A getContext() 0 12 2
A __destruct() 0 4 1
A write() 0 18 4
A getFile() 0 12 2
A cleanDirectory() 0 4 1
1
<?php
2
3
namespace Docker\Context;
4
5
use Symfony\Component\Filesystem\Filesystem;
6
7
class ContextBuilder
8
{
9
    /**
10
     * @var string
11
     */
12
    private $directory;
13
14
    /**
15
     * @var string
16
     */
17
    private $from = 'base';
18
19
    /**
20
     * @var array
21
     */
22
    private $commands = [];
23
24
    /**
25
     * @var array
26
     */
27
    private $files = [];
28
29
    /**
30
     * @var \Symfony\Component\Filesystem\Filesystem
31
     */
32
    private $fs;
33
34
    /**
35
     * @var string
36
     */
37
    private $format;
38
39
    /**
40
     * @param \Symfony\Component\Filesystem\Filesystem
41
     */
42 12
    public function __construct(Filesystem $fs = null)
43
    {
44 12
        $this->fs = $fs ?: new Filesystem();
45 12
        $this->format = Context::FORMAT_STREAM;
46 12
    }
47
48
    /**
49
     * Sets the format of the Context output
50
     *
51
     * @param string $format
52
     *
53
     * @return \Docker\Context\ContextBuilder
54
     */
55
    public function setFormat($format)
56
    {
57
        $this->format = $format;
58
59
        return $this;
60
    }
61
62
    /**
63
     * Set the FROM instruction of Dockerfile
64
     *
65
     * @param string $from From which image we start
66
     *
67
     * @return \Docker\Context\ContextBuilder
68
     */
69 5
    public function from($from)
70
    {
71 5
        $this->from = $from;
72
73 5
        return $this;
74
    }
75
76
    /**
77
     * Add a ADD instruction to Dockerfile
78
     *
79
     * @param string $path    Path wanted on the image
80
     * @param string $content Content of file
81
     *
82
     * @return \Docker\Context\ContextBuilder
83
     */
84 6
    public function add($path, $content)
85
    {
86 6
        $this->commands[] = ['type' => 'ADD', 'path' => $path, 'content' => $content];
87
88 6
        return $this;
89
    }
90
91
    /**
92
     * Add a RUN instruction to Dockerfile
93
     *
94
     * @param string $command Command to run
95
     *
96
     * @return \Docker\Context\ContextBuilder
97
     */
98 1
    public function run($command)
99
    {
100 1
        $this->commands[] = ['type' => 'RUN', 'command' => $command];
101
102 1
        return $this;
103
    }
104
105
    /**
106
     * Create context given the state of builder
107
     *
108
     * @return \Docker\Context\Context
109
     */
110 12
    public function getContext()
111
    {
112 12
        if ($this->directory !== null) {
113
            $this->cleanDirectory();
114
        }
115
116 12
        $this->directory = sys_get_temp_dir().'/'.md5($this->from.serialize($this->commands));
117 12
        $this->fs->mkdir($this->directory);
118 12
        $this->write($this->directory);
119
120 12
        return new Context($this->directory, $this->format);
121
    }
122
123
    /**
124
     * @void
125
     */
126 12
    public function __destruct()
127
    {
128 12
        $this->cleanDirectory();
129 12
    }
130
131
    /**
132
     * Write docker file and associated files in a directory
133
     *
134
     * @param string $directory Target directory
135
     *
136
     * @void
137
     */
138 12
    private function write($directory)
139
    {
140 12
        $dockerfile = [];
141 12
        $dockerfile[] = 'FROM '.$this->from;
142
143 12
        foreach ($this->commands as $command) {
144 7
            switch ($command['type']) {
145 7
                case 'RUN':
146 1
                    $dockerfile[] = 'RUN '.$command['command'];
147 1
                    break;
148 6
                case 'ADD':
149 6
                    $dockerfile[] = 'ADD '.$this->getFile($directory, $command['content']).' '.$command['path'];
150 6
                    break;
151 7
            }
152 12
        }
153
154 12
        $this->fs->dumpFile($directory.DIRECTORY_SEPARATOR.'Dockerfile', implode(PHP_EOL, $dockerfile));
155 12
    }
156
157
    /**
158
     * Generated a file in a directory
159
     *
160
     * @param string $directory Targeted directory
161
     * @param string $content   Content of file
162
     *
163
     * @return string Name of file generated
164
     */
165 6
    private function getFile($directory, $content)
166
    {
167 6
        $hash = md5($content);
168
169 6
        if (!array_key_exists($hash, $this->files)) {
170 6
            $file = tempnam($directory, '');
171 6
            $this->fs->dumpFile($file, $content);
172 6
            $this->files[$hash] = basename($file);
173 6
        }
174
175 6
        return $this->files[$hash];
176
    }
177
178
    /**
179
     * Clean directory generated
180
     */
181 12
    private function cleanDirectory()
182
    {
183 12
        $this->fs->remove($this->directory);
184 12
    }
185
}
186