Completed
Push — master ( c11fed...3aa47b )
by Dominik
14s queued 10s
created

addRewriteRule()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 38
Code Lines 36

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 36
nc 1
nop 1
dl 0
loc 38
rs 9.344
c 0
b 0
f 0
1
<?php
2
3
namespace Flynt\TimberDynamicResize;
4
5
use Twig_SimpleFilter;
6
use Timber;
7
use Routes;
8
9
const DB_VERSION = '1.1';
10
const TABLE_NAME = 'resized_images';
11
const IMAGE_ROUTE = 'dynamic-images';
12
const IMAGE_PATH_SEPARATOR = 'dynamic';
13
14
function getTableName()
15
{
16
    global $wpdb;
17
    return $wpdb->prefix . TABLE_NAME;
18
}
19
20
call_user_func(function () {
21
    $optionName = TABLE_NAME . '_db_version';
22
23
    $installedVersion = get_option($optionName);
24
25
    if ($installedVersion !== DB_VERSION) {
26
        global $wpdb;
27
        $tableName = getTableName();
28
29
        $charsetCollate = $wpdb->get_charset_collate();
30
31
        $sql = "CREATE TABLE $tableName (
32
            url varchar(511),
33
            arguments text
34
        ) $charsetCollate;";
35
36
        require_once ABSPATH . 'wp-admin/includes/upgrade.php';
37
        dbDelta($sql);
38
39
        update_option($optionName, DB_VERSION);
40
    }
41
});
42
43
add_action('timber/twig/filters', function ($twig) {
44
    $twig->addFilter(
45
        new Twig_SimpleFilter('resizeDynamic', function (
46
            $src,
47
            $w,
48
            $h = 0,
49
            $crop = 'default',
50
            $force = false
51
        ) {
52
            $resizeOp = new Timber\Image\Operation\Resize($w, $h, $crop);
53
            $fileinfo = pathinfo($src);
54
            $resizedUrl = $resizeOp->filename(
55
                $fileinfo['dirname'] . '/' . $fileinfo['filename'],
56
                $fileinfo['extension']
57
            );
58
59
            $arguments = [
60
                'src' => $src,
61
                'w' => $w,
62
                'h' => $h,
63
                'crop' => $crop,
64
                'force' => $force
65
            ];
66
67
            global $wpdb;
68
            $tableName = getTableName();
69
            $wpdb->query(
70
                $wpdb->prepare("REPLACE INTO {$tableName} VALUES (%s, %s)", [
71
                    $resizedUrl,
72
                    json_encode($arguments)
73
                ])
74
            );
75
76
            return str_replace(
77
                '/app/uploads/',
78
                '/app/uploads/' . IMAGE_PATH_SEPARATOR . '/',
79
                $resizedUrl
80
            );
81
        })
82
    );
83
84
    return $twig;
85
});
86
87
Routes::map(IMAGE_ROUTE, function () {
88
    $src = str_replace(
89
        '/app/uploads/' . IMAGE_PATH_SEPARATOR . '/',
90
        '/app/uploads/',
91
        home_url($_GET['src'] ?? '')
92
    );
93
94
    global $wpdb;
95
    $tableName = getTableName();
96
    $resizedImage = $wpdb->get_row(
97
        $wpdb->prepare("SELECT * FROM {$tableName} WHERE url = %s", $src)
98
    );
99
100
    if (empty($resizedImage)) {
101
        header("HTTP/1.0 404 Not Found");
102
        exit();
103
    }
104
    $urlParts = wp_parse_url($src);
105
    $homeUrl = home_url();
106
    $localDev = parse_url($homeUrl)['host'] !== $urlParts['host'];
107
    if ($localDev) {
108
        $src = http_build_url($homeUrl, ['path' => $urlParts['path']]);
0 ignored issues
show
Unused Code introduced by
The assignment to $src is dead and can be removed.
Loading history...
109
    }
110
    $moveImageFunction = function ($location) {
111
        return str_replace(
112
            '/app/uploads/',
113
            '/app/uploads/' . IMAGE_PATH_SEPARATOR . '/',
114
            $location
115
        );
116
    };
117
    add_filter('timber/image/new_url', $moveImageFunction);
118
    add_filter('timber/image/new_path', $moveImageFunction);
119
    $arguments = json_decode($resizedImage->arguments, true);
120
    $url = Timber\ImageHelper::resize(
121
        $arguments['src'],
122
        (int) $arguments['w'],
123
        (int) $arguments['h'],
124
        $arguments['crop'],
125
        false
126
    );
127
128
    remove_filter('timber/image/new_url', $moveImageFunction);
129
    remove_filter('timber/image/new_path', $moveImageFunction);
130
131
    Timber\ImageHelper::img_to_webp($url);
132
133
    if ($localDev) {
134
        unset($urlParts['path']);
135
        $url = http_build_url($url, $urlParts);
136
    }
137
    header("Location: {$url}", true, 301);
138
    exit();
139
});
140
141
function addRewriteRule($rules)
142
{
143
    $dynamicImageRule = <<<EOD
144
\n# BEGIN Flynt dynamic images
145
RewriteEngine On
146
RewriteCond %{REQUEST_URI} ^/app/uploads/dynamic
147
RewriteCond %{REQUEST_FILENAME} !-f
148
RewriteCond %{REQUEST_FILENAME} !-d
149
RewriteRule ^(.*)$ /dynamic-images?src=$1 [L,R]
150
151
<IfModule mod_setenvif.c>
152
# Vary: Accept for all the requests to jpeg and png
153
SetEnvIf Request_URI "\.(jpe?g|png)$" REQUEST_image
154
</IfModule>
155
156
<IfModule mod_rewrite.c>
157
RewriteEngine On
158
159
# Check if browser supports WebP images
160
RewriteCond %{HTTP_ACCEPT} image/webp
161
162
# Check if WebP replacement image exists
163
RewriteCond %{DOCUMENT_ROOT}/$1.webp -f
164
165
# Serve WebP image instead
166
RewriteRule (.+)\.(jpe?g|png)$ $1.webp [T=image/webp]
167
</IfModule>
168
169
<IfModule mod_headers.c>
170
Header append Vary Accept env=REQUEST_image
171
</IfModule>
172
173
<IfModule mod_mime.c>
174
AddType image/webp .webp
175
</IfModule>
176
# END Flynt dynamic images\n\n
177
EOD;
178
    return $dynamicImageRule . $rules;
179
}
180
181
add_filter('mod_rewrite_rules', 'Flynt\\TimberDynamicResize\\addRewriteRule');
182
183
add_action('after_switch_theme', function () {
184
    add_action('shutdown', 'flush_rewrite_rules');
185
});
186
187
add_action('switch_theme', function () {
188
    remove_filter('mod_rewrite_rules', 'Flynt\\TimberDynamicResize\\addRewriteRule');
189
    flush_rewrite_rules();
190
});
191