-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathTextformatterSrcset.module
342 lines (285 loc) · 11.1 KB
/
TextformatterSrcset.module
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
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
<?php
class TextformatterSrcset extends Textformatter implements ConfigurableModule {
/**
* Module information
*
*/
public static function getModuleInfo() {
return array(
'title' => 'Srcset Image Textformatter',
'version' => 100,
'summary' => "Adds the srcset to images within a textarea" ,
'author' => 'Conclurer GbR'
);
}
/**
* Module settings
*
*/
protected static $defaultConfigData = array(
// settings
"resolutions" => "350,700", //Only numbers, seperated by comma
"sizes" => "auto", //What to put into the sizes attribute
"retina" => true, //Create an image double the largest image size for HiDPI devices
"data_attr"=> false, //Add the data-* attributes
"wh_attr" => false, //Should we add width and height attributes?
"lqp" => true, //Use a low quality placeholder for the src attribute
"small_source" => false, //Use the smallest size as a source image instead of a scaled down image
"class" => '' //Classes added to the image
);
protected $data = array(); // module data
/**
* Set all settings to data
*
*/
public function __construct() {
foreach(self::$defaultConfigData as $key => $value) {
$this->data[$key] = $value;
}
}
/**
* Get data by key
*
*/
public function __get($key) {
return isset($this->data[$key]) ? $this->data[$key] : null;
}
/**
* Set data at given key
*
*/
public function __set($key, $value) {
$this->data[$key] = $value;
}
public function formatValue(Page $page, Field $field, &$str) {
//Get all image tags from the $str and place them in $images
preg_match_all('/<img[^>]+>/i',$str, $images);
$images = $images[0];
//No images? Then return
if(count($images)==0) return;
//#todo What happens if this is only 1 image?
//Setup...
$matches = array();
$fileLocation = wire("config")->urls->files;
$sizes = array_map( 'intval', array_filter( explode(',', $this->resolutions), 'is_numeric' ));
sort($sizes);
$options = array( 'upscaling' => false, 'cropping' => true);
$options_low = array( 'upscaling' => true, 'cropping' => true, 'quality' => floor(wire("config")->imageSizerOptions['quality']*0.33));
//Looping through all images
foreach($images as $original) {
//Building our new image string
$new = '';
$meta = array();
/**
* The following code was taken and modified from Martijn Geerts and the TextformatterImageInterceptor module.
*/
//Get the PageImage from our image
if(strpos($original, $fileLocation)) {
//Find source image
preg_match_all( '/src="(.*?)"/i', $original, $array);
$meta['source'] = $array[1][0]; // original
// ProcessWire alignment done with a class
preg_match_all( '/class="(.*?)"/i', $original, $array);
$meta['pw_align'] = isset($array[1][0]) ? $array[1][0] : null; // original
//Get alt tag if it exists
preg_match_all( '/alt="(.*?)"/i', $original, $array);
$meta['alt'] = isset($array[1][0]) ? $array[1][0] : null;
// example: 1023/image-name.100x100.jpg
$string = str_replace($fileLocation, "", $meta['source']);
// create array
$array = explode("/", $string);
// id of page where where image belongs to
$meta['id'] = (int) $array[0];
// refering to to page where the image lives.
$p = wire("pages")->get($meta['id']);
// raw image variation name
$variationName = $array[1];
// basename of image.
//$imageName = preg_replace("/\d+x\d+\./i","", $variationName);
$tmp1= explode('.',$variationName);
$meta['imageName'] = $tmp1[0];
$meta['ext'] = $tmp1[count($tmp1)-1];
//Thanks to Horst Nogajski for the following snippet
foreach($p->fields as $field) {
if (! (bool) ($field->type instanceof FieldtypeImage)) continue; // if no images field, go on
// find the field that holds the image
if (!$p->get($field->name)->has('name=' . $meta['imageName'] . '.' . $meta['ext'])) continue;
$image = $p->get($field->name)->get('name=' . $meta['imageName'] . '.' . $meta['ext']);
}
//Get image size #todo use regex here
$array = explode(".",$string);
$array = substr($array[count($array)-2],0,-3); //Get the image tag and remove everything. results in e.g. 720x201
$array = explode("x",$array);
if(count($array) == 2) //Shitty filtering in case it is the original image
$meta['width'] = (int)$array[0];
else
$meta['width'] = $image->width;
//$meta['height'] = $array[1]; //Height is set to always 0 by PW
}
//$image is now our PageImage, $p the page of the Image
/**
* Build the srcset
*/
//When no sizes are set
if(empty($sizes)){
$srcset = "{$meta['source']} 1x";
//... and retina is active
if($this->retina) {
//And our image is sized (e.g. larger image possible). Then we can provide a better image to HiDPI devices
if($image->width() > $meta['width']) {
//Create retina version
$retina_image = $image->size($meta['width']*2,0,$options);
$srcset .= ", {$retina_image->url} 2x";
}
}
}
else {
//Sizes are set
$srcset = "";
//For every size
foreach($sizes as $size) {
//Do we need this size as a source?
if($size < $meta['width']) {
//Orientation
if($image->width > $image->height) {
$new_image = $image->size($size,0,$options);
}
else {
$new_image = $image->size(0,$size,$options);
}
$srcset .= "{$new_image->url} {$new_image->width}w,";
}
}
//If HiDPI is enabled
if($this->retina) {
if($image->width() >= $meta['width']) {
//Create retina version
$retina_image = $image->size($meta['width']*2,0,$options);
}
else {
//Use the largest image
$retina_image = $image;
}
$srcset .= "{$retina_image->url} {$retina_image->width}w,";
}
//Remove the last comma
$srcset = substr($srcset,0,-1);
}
/**
* Build the src
*/
$src = $meta['source'];
if($this->lqp OR $this->small_source) {
//Should we use the smalles image from the sizes?
if($this->small_source && !empty($sizes)) {
//Orientation
if($image->width > $image->height) {
$src_image = $image->size($sizes[0],0,$options);
}
else {
$src_image = $image->size(0,$sizes[0],$options);
}
}
//Or do we really use a LQ image? Note, the 300 size is fixed here
else {
$new_size = floor($image->width*0.2);
$src_image = $image->size($new_size,0,$options_low);
}
$src = $src_image->url;
}
/**
* Finally, Build the <img>
*/
$attribute = '';
$wh_attr = '';
$class = '';
if($this->data_attr) {
$attribute = "data-";
}
if($this->wh_attr) {
$tmp_height = $image->size($meta['width'],0)->height;
$wh_attr = " width='{$meta['width']}' height='{$tmp_height}'";
}
if($meta['pw_align'] != "" OR $this->class != "") {
$class = " class='";
if($meta['pw_align'] != "")
$class .= "{$meta['pw_align']} ";
if($this->class != '')
$class .= "{$this->class}";
$class .= "'";
}
//Put it all together
$new = "<img src='{$src}' {$attribute}srcset='{$srcset}' {$attribute}sizes='{$this->sizes}'{$wh_attr} alt='{$meta['alt']}'{$class}/>";
//Add to our new images
$matches[] = $new;
}
//Replace all Image tags with our new ones and return.
$str = str_replace($images,$matches,$str);
return;
}
/**
* Return an InputfieldsWrapper of Inputfields used to configure the class
*
* @param array $data Array of config values indexed by field name
* @return InputfieldWrapper
*
*/
public static function getModuleConfigInputfields(array $data)
{
$data = array_merge(self::$defaultConfigData, $data);
$wrapper = new InputfieldWrapper();
$resolutionsInput = wire('modules')->get('InputfieldText');
$resolutionsInput->name = 'resolutions';
$resolutionsInput->label = __('Resolutions');
$resolutionsInput->description = __('Enter the resolutions (in Pixel) to be created for the srcset. Seperate by comma, leave empty if you do not need multiple sizes.');
$resolutionsInput->value = $data['resolutions'];
$wrapper->add($resolutionsInput);
$sizesInput = wire('modules')->get('InputfieldText');
$sizesInput->name = 'sizes';
$sizesInput->label = __('Sizes-Attribute');
$sizesInput->description = __('Enter the value for the "sizes" attribute. Default is "auto".');
$sizesInput->value = $data['sizes'];
$wrapper->add($sizesInput);
$retinaInput = wire('modules')->get('InputfieldCheckbox');
$retinaInput->name = 'retina';
$retinaInput->label = __('Generate HiDPI images');
$retinaInput->description = __('Activate to create HiDPI images (double resolution). They appear as an additional size.');
if(!empty($data['retina'])) $retinaInput->checked = 1;
$wrapper->add($retinaInput);
$lqpInput = wire('modules')->get('InputfieldCheckbox');
$lqpInput->name = 'lqp';
$lqpInput->columnWidth = 50;
$lqpInput->label = __('Low-quality Placeholder');
$lqpInput->description = __('Activate to create a low-quality placeholder (LQP) image for the src-attribute.');
if(!empty($data['lqp'])) $lqpInput->checked = 1;
$wrapper->add($lqpInput);
$small_sourceInput = wire('modules')->get('InputfieldCheckbox');
$small_sourceInput->name = 'small_source';
$small_sourceInput->columnWidth = 50;
$small_sourceInput->label = __('Use smallest size as LQP');
$small_sourceInput->description = __('Activate to use the smallest sized image as the low-quality placeholder');
if(!empty($data['small_source'])) $small_sourceInput->checked = 1;
$wrapper->add($small_sourceInput);
$wh_attrInput = wire('modules')->get('InputfieldCheckbox');
$wh_attrInput->name = 'wh_attr';
$wh_attrInput->columnWidth = 50;
$wh_attrInput->label = __('Width/Height Attributes');
$wh_attrInput->description = __('Activate to add the right width and height attribute.');
if(!empty($data['wh_attr'])) $wh_attrInput->checked = 1;
$wrapper->add($wh_attrInput);
$data_attrInput = wire('modules')->get('InputfieldCheckbox');
$data_attrInput->name = 'data_attr';
$data_attrInput->columnWidth = 50;
$data_attrInput->label = __('Data* Attributes');
$data_attrInput->description = __('Activate to add a data*- before the srcset and sizes attributes.');
if(!empty($data['data_attr'])) $data_attrInput->checked = 1;
$wrapper->add($data_attrInput);
$classInput = wire('modules')->get('InputfieldText');
$classInput->name = 'class';
$classInput->label = __('CSS Class');
$classInput->description = __('Enter CSS-class names that will be added to each image.');
$classInput->value = $data['class'];
$wrapper->add($classInput);
return $wrapper;
}
}