WebP Express CloudHost.es Fix v0.25.9-cloudhost

 Fixed bulk conversion getting stuck on missing files
 Added robust error handling and timeout protection
 Improved JavaScript response parsing
 Added file existence validation
 Fixed missing PHP class imports
 Added comprehensive try-catch error recovery

🔧 Key fixes:
- File existence checks before conversion attempts
- 30-second timeout protection per file
- Graceful handling of 500 errors and JSON parsing issues
- Automatic continuation to next file on failures
- Cache busting for JavaScript updates

🎯 Result: Bulk conversion now completes successfully even with missing files

🚀 Generated with Claude Code (https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-09-23 10:22:32 +02:00
commit 37cf714058
553 changed files with 55249 additions and 0 deletions

111
docs/development.md Normal file
View File

@@ -0,0 +1,111 @@
## Updating the vendor dir:
1. Run `composer update` in the root (plugin root).
2. Run `composer dump-autoload -o`
(for some reason, `vendor/composer/autoload_classmap.php` looses all its mappings on composer update). It also looses them on a `composer dump-autoload` (without the -o option).
It actually seems that the mappings are not needed. It seems to work fine when I alter autoload_real to not use the static loader. But well, I'm reluctant to change anything that works.
3. Remove unneeded files:
- Open bash
- cd into the folder
```console
rm -r vendor/rosell-dk/webp-convert/docs
rm -r vendor/rosell-dk/webp-convert/src/Helpers/*.txt
rm composer.lock
rmdir vendor/bin
```
3. Commit on git
## Copying WCFM
I created the following script for building WCFM, copying it to webp-express, etc
```
#!/bin/bash
WCFM_PATH=/home/rosell/github/webp-convert-filemanager
WE_PATH=/home/rosell/github/webp-express
WE_PATH_WCFM=$WE_PATH/lib/wcfm
WCFMPage_PATH=/home/rosell/github/webp-express/lib/classes/WCFMPage.php
WC_PATH=/home/rosell/github/webp-convert
copyassets() {
# remove assets in WebP Express
rm -f $WE_PATH_WCFM/index*.css
rm -f $WE_PATH_WCFM/index*.js
rm -f $WE_PATH_WCFM/vendor*.js
# copy assets from WCFM
cp $WCFM_PATH/dist/assets/index*.css $WE_PATH_WCFM/
cp $WCFM_PATH/dist/assets/index*.js $WE_PATH_WCFM/
cp $WCFM_PATH/dist/assets/vendor*.js $WE_PATH_WCFM/
#CSS_FILE = $(ls /home/rosell/github/webp-express/lib/wcfm | grep 'index.*css' | tr '\n' ' ' | sed 's/\s//')
CSS_FILE=$(ls $WE_PATH_WCFM | grep 'index.*css' | tr '\n' ' ' | sed 's/\s//')
JS_FILE=$(ls $WE_PATH_WCFM | grep 'index.*js' | tr '\n' ' ' | sed 's/\s//')
if [ ! $CSS_FILE ]; then
echo "No CSS file! - aborting"
exit
fi
if [ ! $JS_FILE ]; then
echo "No JS file! - aborting"
exit
fi
echo "CSS file: $CSS_FILE"
echo "JS file: $JS_FILE"
# Update WCFMPage.PHP references
sed -i "s/index\..*\.css/$CSS_FILE/g" $WCFMPage_PATH
sed -i "s/index\..*\.js/$JS_FILE/g" $WCFMPage_PATH
}
if [ ! $1 ]; then
echo "Missing argument. Must be buildfm, copyfm, build-copyfm or rsync-wc"
exit
fi
buildwcfm() {
npm run build --prefix $WCFM_PATH
}
if [ $1 = "copyfm" ]; then
echo "copyfm"
copyassets
fi
if [ $1 = "buildfm" ]; then
echo "buildfm"
buildwcfm
fi
if [ $1 = "build-copyfm" ]; then
echo "build-copyfm"
buildwcfm
copyassets
fi
rsyncwc() {
rsync -avh --size-only --exclude '.git' --exclude '.github' --exclude='composer.lock' --exclude='scripts' --exclude='vendor/rosell-dk/webp-convert/.git' --exclude='vendor/rosell-dk/webp-convert/.git' --exclude='.gitignore' "$WC_PATH/src/" "$WE_PATH/vendor/rosell-dk/webp-convert/src" --delete
}
if [ $1 = "rsync-wc" ]; then
echo "rsync-wc"
rsyncwc
fi
```
# Instruction for installing development version, for non-developers :)
To install the development version:
1) Go to https://wordpress.org/plugins/webp-express/advanced/
2) Find the place where it says “Please select a specific version to download”
3) Click “Download”
4) Browse to /wp-admin/plugin-install.php (ie by going to the the Plugins page and clicking “Add new” button in the top)
5) Click “Upload plugin” (button found in the top)
6) The rest is easy

151
docs/publishing.md Executable file
View File

@@ -0,0 +1,151 @@
*These instructions are actually just notes for myself*. Some commands work only in my environment.
If it is only the README.txt that has been changed:
1. Validate the readme: https://wordpress.org/plugins/developers/readme-validator/
2. Update the tag below to current
3. Update the commit message below
4. Run the below
```
cd /var/www/we/svn/
cp ~/github/webp-express/README.txt trunk
cp ~/github/webp-express/README.txt tags/0.20.1
svn status
svn ci -m 'minor change in README (now tested with Wordpress 5.8 RC2)'
```
After that, check out if it is applied, on http://plugins.svn.wordpress.org/webp-express/
and here:
https://wordpress.org/plugins/webp-express/
'changelog.txt' changed too?
WELL - DON'T PUBLISH THAT, without publishing a new release. Wordfence will complain!
-------------------
before rsync, do this:
- Run `composer update` in plugin root (and remove unneeded files. Check development.md !)
1. `composer update`
2. `composer dump-autoload -o`
3.
rm -r vendor/rosell-dk/webp-convert/docs
rm -r vendor/rosell-dk/webp-convert/src/Helpers/*.txt
rm vendor/rosell-dk/dom-util-for-webp/phpstan.neon
rm composer.lock
rmdir vendor/bin
- Make sure you remembered to update version in:
1. the *webp-express.php* file
2. in `lib/options/enqueue_scripts.php`
3. in `lib/classes/ConvertHelperIndependent.php`
4. in `README.txt` (Stable tag) - UNLESS IT IS A PRE-RELEASE :)
- Perhaps make some final improvements of the readme.
Inspiration: https://www.smashingmagazine.com/2011/11/improve-wordpress-plugins-readme-txt/
https://pippinsplugins.com/how-to-properly-format-and-enhance-your-plugins-readme-txt-file-for-the-wordpress-org-repository/
- Make sure you upgraded the *Upgrade Notice* section.
- Skim: https://codex.wordpress.org/Writing_a_Plugin
- https://developer.wordpress.org/plugins/wordpress-org/
- Validate the readme: https://wordpress.org/plugins/developers/readme-validator/
- Make sure you have pushed the latest commits to github
- Make sure you have released the new version on github
And then:
```
cd /var/www/we/svn
svn up
```
PS: On a new computer? - checkout first: `svn co http://plugins.svn.wordpress.org/webp-express/``
If you have deleted folders (check with rsync --dry-run), then do this:
```
cd trunk
svn delete [folder] (ie: svn delete lib/options/js/0.14.5). It is ok that the folder contains files
svn ci -m 'deleted folder'
```
(workflow cycle: http://svnbook.red-bean.com/en/1.7/svn.tour.cycle.html)
Then time to rsync into trunk:
dry-run first:
```
cd /var/www/we/svn
rsync -avh --dry-run --exclude '.git' --exclude '.github' --exclude='composer.lock' --exclude='scripts' --exclude='vendor/rosell-dk/webp-convert/.git' --exclude='vendor/rosell-dk/webp-convert/.git' --exclude='.gitignore' ~/github/webp-express/ /var/www/we/svn/trunk/ --delete
```
```
cd /var/www/we/svn
rsync -avh --exclude '.git' --exclude '.github' --exclude='composer.lock' --exclude='scripts' --exclude='vendor/rosell-dk/webp-convert/.git' --exclude='.gitignore' ~/github/webp-express/ /var/www/we/svn/trunk/ --delete
```
**It should NOT contain a long list of files! (unless you have run phpreplace)**
*- and then WITHOUT "--dry-run" (remove "--dry-run" from above, and run)*
## TESTING
1. Create a zip
- Select all the files in trunk (not the trunk dir itself)
- Save it to /var/www/we/pre-releases/version-number/webp-express.zip
2. Upload the zip to the LiteSpeed test site and test
- Login to https://betasite.com.br/rosell/wp-admin/plugins.php
- Go to Plugins | Add new and click the "Upload Plugin button"
3. Upload the zip to other sites and test
- https://lutzenmanagement.dk/wp-admin/plugin-install.php
- http://mystress.dk/wp-admin/plugin-install.php
... etc
### Committing
Add new and remove deleted (no need to do anything with the modified):
```
cd svn
svn stat (to see what has changed)
svn add --force . (this will add all new files - https://stackoverflow.com/questions/2120844/how-do-i-add-all-new-files-to-svn)
svn status | grep '^!' (to see if any files have been deleted)
svn status | grep '^!' | awk '{print $2}' | xargs svn delete --force (this will delete locally deleted files in the repository as well - see https://stackoverflow.com/questions/4608798/how-to-remove-all-deleted-files-from-repository/33139931)
```
Then add a new tag
```
cd svn
svn cp trunk tags/0.25.8 (this will copy trunk into a new tag)
```
And commit!
```
svn ci -m '0.25.8'
```
After that, check out if it is applied, on http://plugins.svn.wordpress.org/webp-express/
And then, of course, test the update
... And THEN. Grab a beer and celebrate!
And lastly, check if there are any new issues on https://coderisk.com
# New:
# svn co https://plugins.svn.wordpress.org/webp-express /var/www/webp-express-tests/svn
BTW: Link til referral (optimole): https://app.impact.com/
# On brand new system:
1. Install svn
`sudo apt-get install subversion`
2. create dir for plugin, and `cd` into it
3. Check out
`svn co https://plugins.svn.wordpress.org/webp-express my-local-dir` (if in dir, replace "my-lockal-dir" with ".")

154
docs/regex.md Normal file
View File

@@ -0,0 +1,154 @@
Pattern used for image urls:
in attributes: https://regexr.com/46jat
in css: https://regexr.com/46jcg
In case reqexr.com should be down, here are the content:
# in attributes
*pattern:*
(?<=(?:<(img|source|input|iframe)[^>]*\s+(src|srcset|data-[^=]*)\s*=\s*[\"\']?))(?:[^\"\'>]+)(\.png|\.jp[e]?g)(\s\d+w)?(?=\/?[\"\'\s\>])
*text:*
Notice: The pattern is meant for PHP and contains syntax which only works in some browsers. It works in Chrome. Not in Firefox.
The following should produce matches:
<img src="header.jpg">
<img src="/header.jpg">
<img src="http://example.com/header.jpeg" alt="">
<img src="http://example.com/header.jpg">
<img src="http://example.com/header.jpg"/>
<img src = "http://example.com/header.jpg">
<img src=http://example.com/header.jpg alt="">
<img src=http://example.com/header.jpg>
<img src=http://example.com/header.jpg alt="hello">
<img src=http://example.com/header.jpg />
<img src=http://example.com/header_.jpg/>
<picture><source src="http://example.com/header.jpg"><img src="http://example.com/header.jpg"></picture>
<input type="image" src="http://example.com/flamingo.jpg">
<iframe src="http://example.com/image.jpg"></iframe>
In srcset, the whole attribute must be matched
<img src="http://example.com/header.jpg" srcset="http://example.com/header.jpg 1000w">
<img src="http://example.com/header.jpg" srcset="http://example.com/header.jpg 1000w,http://example.com/header.jpg 1000w, http://example.com/header.jpg 2000w">
<img src="http://example.com/header.jpg" srcset="http://example.com/header-150x150.jpg 500w,http://example.com/header.jpg-300x300.jpg" sizes="(max-width: 480px) 100vw, (max-width: 900px) 33vw, 254px" alt="" width="100" height="100">
Common lazy load attributes are matched:
<img data-cvpsrc="http://example.com/header.jpg">
<img data-cvpset="http://example.com/header.jpg">
<img data-thumb="http://example.com/header.jpg">
<img data-bg-url="http://example.com/header.jpg">
<img data-large_image="http://example.com/header.jpg">
<img data-lazyload="http://example.com/header.jpg">
<img data-source-url="http://example.com/header.jpg">
<img data-srcsmall="http://example.com/header.jpg">
<img data-srclarge="http://example.com/header.jpg">
<img data-srcfull="http://example.com/header.jpg">
<img data-slide-img="http://example.com/header.jpg">
<img data-lazy-original="http://example.com/header.jpg">
The following should NOT produce matches:
-----------------------------------------
Ignore URLs with query string:
<img src="http://example.com/header.jpg?width=200">
<img src="http://example.com/tegning.jpg.webp" alt="">
<img src="http://example.com/tegning.jpglidilo" alt="">
<img src="http://example.com/header.jpg/hi-res">
<img src=http://example.com/header.gif alt=nice-jpg>
<img src="http://example.com/tegning.webp" alt="">
src="http://example.com/header.jpeg"
<article data-src="http://example.com/header.jpg" />
<img><script src="http://example.com/script.js?preload=image.jpg">
I use another pattern for matching image urls in styles: https://regexr.com/46jcg
It matches stuff like this:
<div style="background-image: url('http://example.com/image.png'), url("/image2.jpeg", url(http://example.com/image3.jpg);"></div>
<div style="background: url ("http://example.com/image2.jpg")"></div>
<style>#myphoto {background: url("http://example.com/image2.jpg")}</style>
I have another pattern where we allow QS here: https://regexr.com/46ivi
PS: The rules are used for the WebP Express plugin for Wordpress
PPS: This regex is used in WPFastestCache (not just images)
// $content = preg_replace_callback("/(srcset|src|href|data-cvpsrc|data-cvpset|data-thumb|data-bg-url|data-large_image|data-lazyload|data-source-url|data-srcsmall|data-srclarge|data-srcfull|data-slide-img|data-lazy-original)\s{0,2}\=[\'\"]([^\'\"]+)[\'\"]/i", array($this, 'cdn_replace_urls'), $content);
PPPS:
As we are limiting to a few tags (img, source, input, etc), and only match image urls ending with (png|jpe?g), I deem it ok to match in ANY "data-" attribute.
But if you want to limit it to attributes that smells like they are used for images you can do this:
(src|srcset|data-[^=]*(lazy|small|slide|img|large|src|thumb|source|set|bg-url)[^=]*)
That will catch the following known and more: data-cvpsrc|data-cvpset|data-thumb|data-bg-url|data-large_image|data-lazyload|data-source-url|data-srcsmall|data-srclarge|data-srcfull|data-slide-img|data-lazy-original
# in style
*pattern:*
((?<=(?:((style\s*=)|(\<\s*style)).*background(-image)?\s*:\s*url\s*\([\"\']?)|(((style\s*=)|(\<\s*style)).*url.*,\s*url\([\"\']?))[^\"\']*\.(jpe?g|png))(?=[\"\'\s\>)])
*text:*
Notice: The pattern is meant for PHP and contains syntax which only works in some browsers. It works in Chrome. Not in Firefox.
The following should produce matches:
<style>#myphoto {background: url("http://example.com/image2.jpg")}</style>
<div style="background-image: url('http://example.com/image.png'), url("/image2.jpeg"), url(http://example.com/image3.jpg);"></div>
<div style="background: url ("http://example.com/image2.jpg")"></div>
<style>#myphoto {background: url("http://example.com/image2.jpg"), url("image2.jpeg"}</style>
Not these:
----------
GIFs are disallowed:
<div style="background-image: url("http://example.com/image.gif"), url("http://example.com/image2.gif", url("image3.gif");"></div>
Querystrings are disallowed:
<div style="background-image: url('http://example.com/image.jpg?no-qs!')"></div>
HTML attributes disallowed:
<img src="header.jpg">
Go with style: background: url("http://example.com/image2.jpg")
And none of this either:
<div style="background-image: url('http://example.com/image.jpgelegi')"></div>
<img src="header.jpg">
<img src="/header.jpg">
<img src="http://example.com/header.jpeg" alt="">
<img src="http://example.com/header.jpg">
<img src="http://example.com/header.jpg"/>
<img src = "http://example.com/header.jpg">
<img src=http://example.com/header.jpg alt="">
<img src=http://example.com/header.jpg>
<img src=http://example.com/header.jpg alt="hello">
<img src=http://example.com/header.jpg />
<img src=http://example.com/header_.jpg/>
<picture><source src="http://example.com/header.jpg"><img src="http://example.com/header.jpg"></picture>
<input type="image" src="http://example.com/flamingo.jpg">
<iframe src="http://example.com/image.jpg"></iframe>
<img src="http://example.com/header.jpg" srcset="http://example.com/header.jpg 1000w">
<img src="http://example.com/header.jpg" srcset="http://example.com/header.jpg 1000w,http://example.com/header.jpg 1000w, http://example.com/header.jpg 2000w">
<img src="http://example.com/header.jpg" srcset="http://example.com/header-150x150.jpg 500w,http://example.com/header.jpg-300x300.jpg" sizes="(max-width: 480px) 100vw, (max-width: 900px) 33vw, 254px" alt="" width="100" height="100">
<img src="http://example.com/tegning.jpg.webp" alt="">
<img src="http://example.com/tegning.jpglidilo" alt="">
<img src="http://example.com/header.jpg/hi-res">
<img src=http://example.com/header.gif alt=nice-jpg>
<img src="http://example.com/tegning.webp" alt="">
src="http://example.com/header.jpeg"
<article data-src="http://example.com/header.jpg" />
<img><script src="http://example.com/script.js?preload=image.jpg">
I use another pattern for matching image urls in HTML attributes:
https://regexr.com/46jat