Test Failed
Push — master ( 39fcfb...91c09e )
by Bjørn
02:56
created

ServeConvertedWebP   A

Complexity

Total Complexity 20

Size/Duplication

Total Lines 149
Duplicated Lines 0 %

Test Coverage

Coverage 85.71%

Importance

Changes 0
Metric Value
eloc 57
dl 0
loc 149
ccs 42
cts 49
cp 0.8571
rs 10
c 0
b 0
f 0
wmc 20

4 Methods

Rating   Name   Duplication   Size   Complexity  
C serve() 0 63 14
A serveOriginal() 0 9 3
A serveDestination() 0 3 1
A processOptions() 0 15 2
1
<?php
2
namespace WebPConvert\Serve;
3
4
use ImageMimeTypeGuesser\ImageMimeTypeGuesser;
5
6
use WebPConvert\Convert\Exceptions\ConversionFailedException;
7
use WebPConvert\Serve\Exceptions\ServeFailedException;
8
use WebPConvert\Serve\Header;
9
use WebPConvert\Serve\Report;
10
use WebPConvert\Serve\ServeFile;
11
use WebPConvert\Options\ArrayOption;
12
use WebPConvert\Options\BooleanOption;
13
use WebPConvert\Options\Options;
14
use WebPConvert\Options\SensitiveArrayOption;
15
use WebPConvert\Options\Exceptions\InvalidOptionTypeException;
16
use WebPConvert\Options\Exceptions\InvalidOptionValueException;
17
use WebPConvert\WebPConvert;
18
19
/**
20
 * Serve a converted webp image.
21
 *
22
 * The webp that is served might end up being one of these:
23
 * - a fresh convertion
24
 * - the destionation
25
 * - the original
26
 *
27
 * Exactly which is a decision based upon options, file sizes and file modification dates
28
 * (see the serve method of this class for details)
29
 *
30
 * @package    WebPConvert
31
 * @author     Bjørn Rosell <[email protected]>
32
 * @since      Class available since Release 2.0.0
33
 */
34
class ServeConvertedWebP
35
{
36
37
    /**
38
     * Process options.
39
     *
40
     * @throws \WebPConvert\Options\Exceptions\InvalidOptionTypeException   If the type of an option is invalid
41
     * @throws \WebPConvert\Options\Exceptions\InvalidOptionValueException  If the value of an option is invalid
42
     * @param array $options
43
     */
44
    private static function processOptions($options)
45
    {
46
        $options2 = new Options();
47
        $options2->addOptions(
48
            new BooleanOption('reconvert', false),
49
            new BooleanOption('serve-original', false),
50 3
            new BooleanOption('show-report', false),
51
            new ArrayOption('serve-image', []),
52 3
            new SensitiveArrayOption('convert', []),
53 3
        );
54
        foreach ($options as $optionId => $optionValue) {
55 3
            $options2->setOrCreateOption($optionId, $optionValue);
56
        }
57
        $options2->check();
58 3
        return $options2->getOptions();
59
    }
60 3
61
    /**
62
     * Serve original file (source).
63
     *
64
     * @param   string  $source                        path to source file
65
     * @param   array   $serveImageOptions (optional)  options for serving an image
66
     *                  Supported options:
67
     *                  - All options supported by ServeFile::serve()
68
     * @throws  ServeFailedException  if source is not an image or mime type cannot be determined
69
     * @return  void
70
     */
71 6
    public static function serveOriginal($source, $serveImageOptions = [])
72
    {
73 6
        $contentType = ImageMimeTypeGuesser::lenientGuess($source);
74 6
        if (is_null($contentType)) {
75
            throw new ServeFailedException('Rejecting to serve original (mime type cannot be determined)');
76
        } elseif ($contentType === false) {
77
            throw new ServeFailedException('Rejecting to serve original (it is not an image)');
78
        } else {
79
            ServeFile::serve($source, $contentType, $serveImageOptions);
80
        }
81
    }
82
83
    /**
84
     * Serve destination file.
85
     *
86
     * @param   string  $destination                   path to destination file
87
     * @param   array   $serveImageOptions (optional)  options for serving (such as which headers to add)
88
     *       Supported options:
89
     *       - All options supported by ServeFile::serve()
90
     * @return  void
91
     */
92
    public static function serveDestination($destination, $serveImageOptions = [])
93
    {
94
        ServeFile::serve($destination, 'image/webp', $serveImageOptions);
95
    }
96
97
    /**
98
     * Serve converted webp.
99
     *
100 7
     * Serve a converted webp. If a file already exists at the destination, that is served (unless it is
101
     * older than the source - in that case a fresh conversion will be made, or the file at the destination
102 7
     * is larger than the source - in that case the source is served). Some options may alter this logic.
103
     * In case no file exists at the destination, a fresh conversion is made and served.
104
     *
105 7
     * @param   string  $source              path to source file
106
     * @param   string  $destination         path to destination
107
     * @param   array   $options (optional)  options for serving/converting
108 7
     *       Supported options:
109
     *       'show-report'     => (boolean)   If true, the decision will always be 'report'
110
     *       'serve-original'  => (boolean)   If true, the decision will be 'source' (unless above option is set)
111
     *       'reconvert     '  => (boolean)   If true, the decision will be 'fresh-conversion' (unless one of the
112 7
     *                                        above options is set)
113
     *       - All options supported by WebPConvert::convert()
114
     *       - All options supported by ServeFile::serve()
115
     * @param  \WebPConvert\Loggers\BaseLogger $logger (optional)
116
     *
117 7
     * @throws  \WebPConvert\Exceptions\WebPConvertException  If something went wrong.
118 1
     * @return  void
119 1
     */
120 1
    public static function serve($source, $destination, $options = [], $logger = null)
121
    {
122
        if (empty($source)) {
123 6
            throw new ServeFailedException('Source argument missing');
124 2
        }
125 2
        if (empty($destination)) {
126 4
            throw new ServeFailedException('Destination argument missing');
127
        }
128
        if (@!file_exists($source)) {
129
            throw new ServeFailedException('Source file was not found');
130
        }
131
132 4
        $options = self::processOptions($options);
133 4
//print_r($options); exit;
134 4
135 4
        //$options = array_merge(self::$defaultOptions, $options);
136 4
137 1
        // Step 1: Is there a file at the destination? If not, trigger conversion
138 1
        // However 1: if "show-report" option is set, serve the report instead
139
        // However 2: "reconvert" option should also trigger conversion
140
        if ($options['show-report']) {
141
            Header::addLogHeader('Showing report', $logger);
142
            Report::convertAndReport($source, $destination, $options);
143
            return;
144 6
        }
145 1
146 1
        if (!@file_exists($destination)) {
147
            Header::addLogHeader('Converting (there were no file at destination)', $logger);
148
            WebPConvert::convert($source, $destination, $options['convert'], $logger);
149 6
        } elseif ($options['reconvert']) {
150 6
            Header::addLogHeader('Converting (told to reconvert)', $logger);
151 6
            WebPConvert::convert($source, $destination, $options['convert'], $logger);
152 6
        } else {
153 6
            // Step 2: Is the destination older than the source?
154 1
            //         If yes, trigger conversion (deleting destination is implicit)
155 1
            $timestampSource = @filemtime($source);
156
            $timestampDestination = @filemtime($destination);
157
            if (($timestampSource !== false) &&
158 6
                ($timestampDestination !== false) &&
159 6
                ($timestampSource > $timestampDestination)) {
160 6
                    Header::addLogHeader('Converting (destination was older than the source)', $logger);
161
                    WebPConvert::convert($source, $destination, $options['convert'], $logger);
162
            }
163
        }
164
165
        // Step 3: Serve the smallest file (destination or source)
166
        // However, first check if 'serve-original' is set
167
        if ($options['serve-original']) {
168
            Header::addLogHeader('Serving original (told to)', $logger);
169
            self::serveOriginal($source, $options['serve-image']);
170
        }
171
172
        $filesizeDestination = @filesize($destination);
173
        $filesizeSource = @filesize($source);
174
        if (($filesizeSource !== false) &&
175
            ($filesizeDestination !== false) &&
176
            ($filesizeDestination > $filesizeSource)) {
177
                Header::addLogHeader('Serving original (it is smaller)', $logger);
178
                self::serveOriginal($source, $options['serve-image']);
179
        }
180
181
        Header::addLogHeader('Serving converted file', $logger);
182
        self::serveDestination($destination, $options['serve-image']);
183
    }
184
}
185