Completed
Push — master ( 9b3dee...418a58 )
by Geza
04:21
created

Local   A

Complexity

Total Complexity 19

Size/Duplication

Total Lines 148
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Importance

Changes 7
Bugs 1 Features 3
Metric Value
wmc 19
c 7
b 1
f 3
lcom 1
cbo 5
dl 0
loc 148
rs 10

9 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 3
A configure() 0 16 1
A getClearScreenshotDirectoryFeatureValidator() 0 6 2
A load() 0 9 3
A upload() 0 8 1
A getDefaultDirectory() 0 4 1
A getTargetPath() 0 5 2
A ensureDirectoryExists() 0 10 3
A clearScreenshotDirectory() 0 13 3
1
<?php
2
3
namespace Bex\Behat\ScreenshotExtension\Driver;
4
5
use Bex\Behat\ScreenshotExtension\Driver\ImageDriverInterface;
6
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
7
use Symfony\Component\DependencyInjection\ContainerBuilder;
8
use Symfony\Component\Filesystem\Exception\IOException;
9
use Symfony\Component\Filesystem\Filesystem;
10
use Symfony\Component\Finder\Finder;
11
use Symfony\Component\Finder\SplFileInfo;
12
13
class Local implements ImageDriverInterface
14
{
15
    const DEFAULT_DIRECTORY = 'behat-screenshot';
16
    const CONFIG_PARAM_SCREENSHOT_DIRECTORY = 'screenshot_directory';
17
    const CONFIG_PARAM_CLEAR_SCREENSHOT_DIRECTORY = 'clear_screenshot_directory';
18
    const ERROR_MESSAGE_FINFO_NOT_FOUND = 'The fileinfo PHP extension is required, but not installed.';
19
20
    /**
21
     * @var Filesystem
22
     */
23
    private $filesystem;
24
25
    /**
26
     * @var string
27
     */
28
    private $screenshotDirectory;
29
30
    /**
31
     * @var Finder
32
     */
33
    private $finder;
34
    
35
    /**
36
     * @var \finfo
37
     */
38
    private $fileInfo;
39
40
    /**
41
     * @param Filesystem $filesystem
42
     * @param Finder $finder
43
     * @param \finfo $fileInfo
44
     */
45
    public function __construct(Filesystem $filesystem = null, Finder $finder = null, $fileInfo = null)
46
    {
47
        $this->filesystem = $filesystem ?: new Filesystem();
48
        $this->finder = $finder ?: new Finder();
49
        $this->fileInfo = $fileInfo;
50
    }
51
52
    /**
53
     * @param  ArrayNodeDefinition $builder
54
     */
55
    public function configure(ArrayNodeDefinition $builder)
56
    {
57
        $builder
58
            ->children()
59
                ->scalarNode(self::CONFIG_PARAM_SCREENSHOT_DIRECTORY)
60
                    ->defaultValue($this->getDefaultDirectory())
61
                ->end()
62
                ->booleanNode(self::CONFIG_PARAM_CLEAR_SCREENSHOT_DIRECTORY)
63
                    ->defaultValue(false)
64
                    ->validate()
65
                        ->ifTrue($this->getClearScreenshotDirectoryFeatureValidator())
66
                        ->thenInvalid(self::ERROR_MESSAGE_FINFO_NOT_FOUND)
67
                    ->end()
68
                ->end()
69
            ->end();
70
    }
71
72
    /**
73
     * @return \Closure
74
     */
75
    private function getClearScreenshotDirectoryFeatureValidator()
76
    {
77
        return function ($isFeatureEnabled) {
78
            return $isFeatureEnabled && !class_exists('\finfo');
79
        };
80
    }
81
82
83
    /**
84
     * @param  ContainerBuilder $container
85
     * @param  array            $config
86
     */
87
    public function load(ContainerBuilder $container, array $config)
88
    {
89
        $this->screenshotDirectory = $config[self::CONFIG_PARAM_SCREENSHOT_DIRECTORY];
90
91
        if ($config[self::CONFIG_PARAM_CLEAR_SCREENSHOT_DIRECTORY]) {
92
            $this->fileInfo = $this->fileInfo ?: new \finfo();
93
            $this->clearScreenshotDirectory();
94
        }
95
    }
96
97
    /**
98
     * @param string $binaryImage
99
     * @param string $filename
100
     *
101
     * @return string URL to the image
102
     */
103
    public function upload($binaryImage, $filename)
104
    {
105
        $targetFile = $this->getTargetPath($filename);
106
        $this->ensureDirectoryExists(dirname($targetFile));
107
        $this->filesystem->dumpFile($targetFile, $binaryImage);
108
109
        return $targetFile;
110
    }
111
112
    /**
113
     * @return string
114
     */
115
    private function getDefaultDirectory()
116
    {
117
        return sys_get_temp_dir() . DIRECTORY_SEPARATOR . self::DEFAULT_DIRECTORY;
118
    }
119
120
    /**
121
     * @param string $fileName
122
     *
123
     * @return string
124
     */
125
    private function getTargetPath($fileName)
126
    {
127
        $path = rtrim($this->screenshotDirectory, DIRECTORY_SEPARATOR);
128
        return empty($path) ? $fileName : $path . DIRECTORY_SEPARATOR . $fileName;
129
    }
130
131
    /**
132
     * @param string $directory
133
     *
134
     * @throws IOException
135
     */
136
    private function ensureDirectoryExists($directory)
137
    {
138
        try {
139
            if (!$this->filesystem->exists($directory)) {
140
                $this->filesystem->mkdir($directory, 0770);
141
            }
142
        } catch (IOException $e) {
143
            throw new \RuntimeException(sprintf('Cannot create screenshot directory "%s".', $directory));
144
        }
145
    }
146
147
    private function clearScreenshotDirectory()
148
    {
149
        $filesToDelete = [];
150
151
        /** @var SplFileInfo $file */
152
        foreach ($this->finder->files()->in($this->getTargetPath('')) as $file) {
153
            if (strpos($this->fileInfo->file($file->getRealPath(), FILEINFO_MIME_TYPE), 'image/') !== false) {
154
                $filesToDelete[] = $file->getRealPath();
155
            }
156
        }
157
158
        $this->filesystem->remove($filesToDelete);
159
    }
160
}
161