Passed
Push — master ( 47232b...207a99 )
by Bjørn
01:36 queued 12s
created

ServeConvertedWebP   A

Complexity

Total Complexity 20

Size/Duplication

Total Lines 173
Duplicated Lines 0 %

Test Coverage

Coverage 90.41%

Importance

Changes 12
Bugs 2 Features 1
Metric Value
eloc 69
c 12
b 2
f 1
dl 0
loc 173
ccs 66
cts 73
cp 0.9041
rs 10
wmc 20

5 Methods

Rating   Name   Duplication   Size   Complexity  
A serveOriginal() 0 10 3
A serveDestination() 0 4 1
A processOptions() 0 17 2
A warningHandler() 0 2 1
C serve() 0 74 13
1
<?php
2
namespace WebPConvert\Serve;
3
4
use WebPConvert\Convert\Exceptions\ConversionFailedException;
5
use WebPConvert\Helpers\InputValidator;
6
use WebPConvert\Helpers\MimeType;
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 7
    private static function processOptions($options)
45
    {
46 7
        $options2 = new Options();
47 7
        $options2->addOptions(
48 7
            new BooleanOption('reconvert', false),
49 7
            new BooleanOption('serve-original', false),
50 7
            new BooleanOption('show-report', false),
51 7
            new BooleanOption('suppress-warnings', true),
52 7
            new BooleanOption('redirect-to-self-instead-of-serving', false),
53 7
            new ArrayOption('serve-image', []),
54 7
            new SensitiveArrayOption('convert', [])
55
        );
56 7
        foreach ($options as $optionId => $optionValue) {
57 7
            $options2->setOrCreateOption($optionId, $optionValue);
58
        }
59 7
        $options2->check();
60 7
        return $options2->getOptions();
61
    }
62
63
    /**
64
     * Serve original file (source).
65
     *
66
     * @param   string  $source                        path to source file
67
     * @param   array   $serveImageOptions (optional)  options for serving an image
68
     *                  Supported options:
69
     *                  - All options supported by ServeFile::serve()
70
     * @throws  ServeFailedException  if source is not an image or mime type cannot be determined
71
     * @return  void
72
     */
73 3
    public static function serveOriginal($source, $serveImageOptions = [])
74
    {
75 3
        InputValidator::checkSource($source);
76 3
        $contentType = MimeType::getMimeTypeDetectionResult($source);
77 3
        if (is_null($contentType)) {
78
            throw new ServeFailedException('Rejecting to serve original (mime type cannot be determined)');
79 3
        } elseif ($contentType === false) {
80
            throw new ServeFailedException('Rejecting to serve original (it is not an image)');
81
        } else {
82 3
            ServeFile::serve($source, $contentType, $serveImageOptions);
83
        }
84 3
    }
85
86
    /**
87
     * Serve destination file.
88
     *
89
     * TODO: SHould this really be public?
90
     *
91
     * @param   string  $destination                   path to destination file
92
     * @param   array   $serveImageOptions (optional)  options for serving (such as which headers to add)
93
     *       Supported options:
94
     *       - All options supported by ServeFile::serve()
95
     * @return  void
96
     */
97 4
    public static function serveDestination($destination, $serveImageOptions = [])
98
    {
99 4
        InputValidator::checkDestination($destination);
100 4
        ServeFile::serve($destination, 'image/webp', $serveImageOptions);
101 4
    }
102
103
104 3
    public static function warningHandler()
105
    {
106
        // do nothing! - as we do not return anything, the warning is suppressed
107 3
    }
108
109
    /**
110
     * Serve converted webp.
111
     *
112
     * Serve a converted webp. If a file already exists at the destination, that is served (unless it is
113
     * older than the source - in that case a fresh conversion will be made, or the file at the destination
114
     * is larger than the source - in that case the source is served). Some options may alter this logic.
115
     * In case no file exists at the destination, a fresh conversion is made and served.
116
     *
117
     * @param   string  $source              path to source file
118
     * @param   string  $destination         path to destination
119
     * @param   array   $options (optional)  options for serving/converting
120
     *       Supported options:
121
     *       'show-report'     => (boolean)   If true, the decision will always be 'report'
122
     *       'serve-original'  => (boolean)   If true, the decision will be 'source' (unless above option is set)
123
     *       'reconvert     '  => (boolean)   If true, the decision will be 'fresh-conversion' (unless one of the
124
     *                                        above options is set)
125
     *       - All options supported by WebPConvert::convert()
126
     *       - All options supported by ServeFile::serve()
127
     * @param  \WebPConvert\Loggers\BaseLogger $serveLogger (optional)
128
     * @param  \WebPConvert\Loggers\BaseLogger $convertLogger (optional)
129
     *
130
     * @throws  \WebPConvert\Exceptions\WebPConvertException  If something went wrong.
131
     * @return  void
132
     */
133 7
    public static function serve($source, $destination, $options = [], $serveLogger = null, $convertLogger = null)
134
    {
135 7
        InputValidator::checkSourceAndDestination($source, $destination);
136
137 7
        $options = self::processOptions($options);
138
139 7
        if ($options['suppress-warnings']) {
140 7
            set_error_handler(
141 7
                array('\\WebPConvert\\Serve\\ServeConvertedWebP', "warningHandler"),
142 7
                E_WARNING | E_USER_WARNING | E_NOTICE | E_USER_NOTICE
143
            );
144
        }
145
146
147
        //$options = array_merge(self::$defaultOptions, $options);
148
149
        // Step 1: Is there a file at the destination? If not, trigger conversion
150
        // However 1: if "show-report" option is set, serve the report instead
151
        // However 2: "reconvert" option should also trigger conversion
152 7
        if ($options['show-report']) {
153 1
            Header::addLogHeader('Showing report', $serveLogger);
154 1
            Report::convertAndReport($source, $destination, $options);
155 1
            return;
156
        }
157
158 6
        if (!@file_exists($destination)) {
159 1
            Header::addLogHeader('Converting (there were no file at destination)', $serveLogger);
160 1
            WebPConvert::convert($source, $destination, $options['convert'], $convertLogger);
161 5
        } elseif ($options['reconvert']) {
162 1
            Header::addLogHeader('Converting (told to reconvert)', $serveLogger);
163 1
            WebPConvert::convert($source, $destination, $options['convert'], $convertLogger);
164
        } else {
165
            // Step 2: Is the destination older than the source?
166
            //         If yes, trigger conversion (deleting destination is implicit)
167 4
            $timestampSource = @filemtime($source);
168 4
            $timestampDestination = @filemtime($destination);
169 4
            if (($timestampSource !== false) &&
170 4
                ($timestampDestination !== false) &&
171 4
                ($timestampSource > $timestampDestination)) {
172 1
                    Header::addLogHeader('Converting (destination was older than the source)', $serveLogger);
173 1
                    WebPConvert::convert($source, $destination, $options['convert'], $convertLogger);
174
            }
175
        }
176
177
        // Step 3: Serve the smallest file (destination or source)
178
        // However, first check if 'serve-original' is set
179 6
        if ($options['serve-original']) {
180 1
            Header::addLogHeader('Serving original (told to)', $serveLogger);
181 1
            self::serveOriginal($source, $options['serve-image']);
182 1
            return;
183
        }
184
185 5
        if ($options['redirect-to-self-instead-of-serving']) {
186
            Header::addLogHeader(
187
                'Redirecting to self! ' .
188
                    '(hope you got redirection to existing webps set up, otherwise you will get a loop!)',
189
                $serveLogger
190
            );
191
            header('Location: ?fresh', 302);
192
            return;
193
        }
194
195 5
        $filesizeDestination = @filesize($destination);
196 5
        $filesizeSource = @filesize($source);
197 5
        if (($filesizeSource !== false) &&
198 5
            ($filesizeDestination !== false) &&
199 5
            ($filesizeDestination > $filesizeSource)) {
200 1
                Header::addLogHeader('Serving original (it is smaller)', $serveLogger);
201 1
                self::serveOriginal($source, $options['serve-image']);
202 1
                return;
203
        }
204
205 4
        Header::addLogHeader('Serving converted file', $serveLogger);
206 4
        self::serveDestination($destination, $options['serve-image']);
207 4
    }
208
}
209