-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathTextformatterPageimageSource.module
More file actions
208 lines (164 loc) · 5.53 KB
/
TextformatterPageimageSource.module
File metadata and controls
208 lines (164 loc) · 5.53 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
<?php namespace ProcessWire;
/**
* Textformatter Pageimage Source
*
* #pw-summary Update JPG/PNG image references with your Pageimage Source configuration.
* #pw-body Based on TextformatterWebpImages by Ryan Cramer.
*
* @copyright 2022 NB Communication Ltd
* @license Mozilla Public License v2.0 http://mozilla.org/MPL/2.0/
*
*/
class TextformatterPageimageSource extends Textformatter implements Module {
/**
* getModuleInfo is a module required by all modules to tell ProcessWire about them
*
* @return array
*
*/
public static function getModuleInfo() {
return [
'title' => 'Textformatter Pageimage Source',
'version' => 010,
'summary' => 'Update JPG/PNG image references with your Pageimage Source configuration.',
'author' => 'nbcommunication',
'href' => 'https://github.com/nbcommunication/PageimageSource',
'icon' => 'picture-o',
'requires' => 'PageimageSource',
];
}
/**
* Last page ID that called this module
*
* @var int
*
*/
protected $cursor = 0;
/**
* Image fields indexed by page ID (reset on every call to formatValue that changes the page ID)
*
* @var array
*
*/
protected $imageFields = [];
/**
* Cache of replacements indexed by page ID (reset on every call to formatValue that changes the page ID)
*
* @var array
*
*/
protected $replacements = [];
/**
* Format the given $value for the given $page $field
*
* @param Page $page
* @param Field $field
* @param string $value
*
*/
public function formatValue(Page $page, Field $field, &$value) {
if($this->cursor !== $page->id) {
$this->imageFields = [];
$this->replacements = [];
}
$urlFiles = $this->wire()->config->urls('files');
$exts = ['jpeg', 'jpg', 'png'];
$this->cursor = $page->id;
$cacheKey = "$field.$page";
if(isset($this->replacements[$cacheKey])) {
$replacements = $this->replacements[$cacheKey];
} else {
$replacements = [];
// Do any image references with this ext appear in value?
foreach($exts as $key => $ext) {
if(strpos($value, ".$ext") === false) unset($exts[$key]);
}
// If no images then exit
if(!count($exts)) return;
// Find all <img> elements referenced
if(!preg_match_all(
'/<img.*?src=["|\'](' . str_replace('/', '\/', $urlFiles) . '\d+\/.*?\.(' . implode('|', $exts) . '))["|\'].*?>/',
$value,
$matches
)) return;
foreach($matches[0] as $key => $fullMatch) {
$matchUrl = $matches[1][$key];
// If image exists somewhere outside our files, skip
if(strpos($matchUrl, $urlFiles) !== 0) continue;
// Determine page id that owns file from its URL
$id = str_replace($urlFiles, '', dirname($matchUrl));
// If extended paths are in use, remove slashes
if(strpos($id, '/') !== false) $id = str_replace('/', '', $id);
// Get page from the id
$id = (int) $id;
$p = $id === $page->id ? $page : $this->wire()->pages->get($id);
// If the page isn't a page, skip
if(!$p->id) continue;
// Get the image fields for this page
if(isset($this->imageFields[$p->id])) {
$imageFields = $this->imageFields[$p->id];
} else {
$imageFields = [];
foreach($p->template->fieldgroup as $field) {
if(!$field->type instanceof FieldtypeImage) continue;
$v = $p->get($field->name);
if(empty($v)) continue;
if($v instanceof Pageimage) $v = $v->pagefiles;
if(!$v instanceof Pageimages) continue;
if(!$v->count()) continue;
$imageFields[$field->name] = $v;
}
$this->imageFields[$p->id] = $imageFields;
}
$image = null;
$filename = basename($matchUrl);
foreach($imageFields as $images) {
$image = $images->getFile($filename);
if($image) break;
}
if($image instanceof Pageimage) {
$attrs = ['width', 'height'];
$original = [];
$variation = [];
foreach($attrs as $attr) {
$original[$attr] = $image->get($attr);
if(preg_match('/' . $attr . '="(\d*?)"/', $fullMatch, $attrMatches)) {
$variation[$attr] = (int) $attrMatches[1];
} else {
$variation[$attr] = 0;
}
}
// Resize if a variation
if(preg_match('/\.(\d+)x(\d+)(.*?)\./', $filename, $dimensions)) {
$image = $image->size((int) $dimensions[1] ?: 0, (int) $dimensions[2] ?: 0, [
'hidpi' => strpos($dimensions[3] ?? '', 'hidpi') !== false,
]);
} else if(array_sum($variation)) {
$image = $image->size($variation['width'], $variation['height']);
}
// Work out the missing dimensions
if(!$variation['width'] && $variation['height']) {
$variation['width'] = round(($original['width'] / $original['height']) * $variation['height']);
}
if(!$variation['height'] && $variation['width']) {
$variation['height'] = round(($original['height'] / $original['width']) * $variation['width']);
}
// Add width and height to the render template if not already there
// Also add data attributes with the original dimensions
$tpl = str_replace($matchUrl, '{url}', $fullMatch);
foreach($attrs as $attr) {
if(!preg_match('/' . $attr . '="\d*?"/', $tpl, $tplMatches)) {
$tpl = str_replace(['">', '" />'], '" ' . $attr . '="' . $variation[$attr] . '">', $tpl);
}
$tpl = str_replace(['">', '" />'], '" data-' . $attr . '="' . $original[$attr] . '">', $tpl);
}
$replacements[$fullMatch] = $image->render($tpl);
}
}
$this->replacements[$cacheKey] = $replacements;
}
if(count($replacements)) {
$value = str_replace(array_keys($replacements), array_values($replacements), $value);
}
}
}