fix: includes

This commit is contained in:
2024-06-18 09:25:38 +02:00
commit e5155e1123
9 changed files with 1430 additions and 0 deletions

22
.editorconfig Normal file
View File

@@ -0,0 +1,22 @@
# This file is for unifying the coding style for different editors and IDEs
# editorconfig.org
# WordPress Coding Standards
# https://make.wordpress.org/core/handbook/coding-standards/
root = true
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
indent_style = tab
indent_size = 4
[{.jshintrc,*.json,*.yml}]
indent_style = space
indent_size = 2
[{*.txt,wp-config-sample.php}]
end_of_line = crlf

11
.gitignore vendored Normal file
View File

@@ -0,0 +1,11 @@
.DS_Store
phpunit.xml
Thumbs.db
wp-cli.local.yml
node_modules/
*.sql
*.tar.gz
*.zip
/vendor
.idea
composer.lock

21
LICENSE Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2022 eighteen73
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

62
README.md Normal file
View File

@@ -0,0 +1,62 @@
# Thumbor for WordPress
**This plugin is in early development and may yet undergo changes that affect its functionality. Use it at your own risk until we publish a versioned release.**
This plugin modifies Wordpress image URLs so they can be served from [Thumbor](https://www.thumbor.org/).
A well configured Thumbor server can deliver highly optimised images to improve website load times, and take a large of your web server by removing the need for WordPress to generate image derivatives for itself.
## Prerequisites
You need access to a Thumbor service to use this plugin.
Note this typically only works on remote WordPress websites because Thumbor needs web access to the uploaded images. With some environment configuration you may be able to make it work in a development environment but that setup is outside the scope of this plugin.
## Installation
Install and activate the plugin as normal then add the following configuration to your website.
```php
define( 'THUMBOR_URL', 'https://media.example.com' );
define( 'THUMBOR_SECRET_KEY', 'your_thumbor_secret_key' );
```
If you Thumbor server runs in unsafe mode (which is _highly_ discouraged) you may set `THUMBOR_SECRET_KEY` to `null`.
### Optional: Disabling “big image” resizing
WordPress can automatically resize large image uploads which will save unnecessarily large requests from your Thumbor server. This plugin can change that limit with the following configuration.
```php
# Disable “big image” resizing
define( 'THUMBOR_UPLOAD_IMAGE_THRESHOLD', false );
# Set the longest image edge
define( 'THUMBOR_UPLOAD_IMAGE_THRESHOLD', 2000 );
```
See [`big_image_size_threshold`](https://developer.wordpress.org/reference/hooks/big_image_size_threshold/) docs for more information.
### Optional: Delete prior image files
Once the plugin is enabled you can make use of a WP-CLI command to delete any image derivatives that have already been created.
**Use this command with great care because it will delete media files from your server.**
```shell
wp media regenerate
```
## Deactivating/pausing the plugin
The plugin automatically deactivates itself when `THUMBOR_URL` is not set. So in your development environment you can remove the above configuration to make WordPress return to its default behaviour.
While enabled the plugin has prevented WordPress from making it's own resized versions of images. You can use the following WP-CLI command to generate any missing images after disabling the plugin:
```shell
wp media regenerate --only-missing
```
## Credits
This plugin is heavily based on code that was forked from the [Tachyon plugin](https://github.com/humanmade/tachyon-plugin) by Human Made. All due credit to the authors of that plugin.

23
composer.json Normal file
View File

@@ -0,0 +1,23 @@
{
"name": "eighteen73/wordpress-thumbor",
"description": "A WordPress plugin to serve media via a Thumbor server",
"type": "wordpress-plugin",
"license": "MIT",
"minimum-stability": "stable",
"require": {
"php": ">=8.0"
},
"autoload": {
"psr-4": {
"Eighteen73\\Thumbor\\": "includes/classes/"
}
},
"config": {
"allow-plugins": {
"dealerdirect/phpcodesniffer-composer-installer": true
}
},
"require-dev": {
"eighteen73/wordpress-coding-standards": "^2.0.0"
}
}

View File

@@ -0,0 +1,99 @@
<?php
/**
* Override native media behaviour.
*
* @package wordpress-thumbor
*/
namespace Eighteen73\Thumbor;
/**
* Plugin singleton class.
*/
class MediaOverrides {
/**
* Oh look, a singleton!
*
* @var Thumbor|null
*/
private static $instance = null;
/**
* Singleton implementation
*
* @return object
*/
public static function instance() {
if ( ! defined( 'THUMBOR_URL' ) || empty( THUMBOR_URL ) ) {
return;
}
if ( ! is_a( self::$instance, __CLASS__ ) ) {
$class = get_called_class();
self::$instance = new $class();
self::$instance->setup();
}
return self::$instance;
}
/**
* Silence is golden.
*/
private function __construct() {}
/**
* Register actions and filters, but only if basic Thumbor functions are available.
* The basic functions are found in ./wordpress-thumbor.php.
*
* @uses add_action, add_filter
* @return null
*/
private function setup() {
if ( ! function_exists( 'thumbor_url' ) ) {
return;
}
// Don't scale down big images
add_filter( 'big_image_size_threshold', [ $this, 'image_threshold' ], 999, 1 );
// Don't resize any images
add_filter( 'intermediate_image_sizes_advanced', [ $this, 'prevent_resizing' ], 10, 5 );
}
/**
* Prevents any images from being automatically created.
*
* @param int $threshold The threshold value in pixels.
*
* @return bool|int The new “big image” threshold value.
*/
public static function image_threshold( $threshold ) {
if ( ! defined( 'THUMBOR_UPLOAD_IMAGE_THRESHOLD' ) ) {
return $threshold;
}
if ( THUMBOR_UPLOAD_IMAGE_THRESHOLD === false ) {
return false;
} elseif ( is_int( THUMBOR_UPLOAD_IMAGE_THRESHOLD ) ) {
return THUMBOR_UPLOAD_IMAGE_THRESHOLD;
}
return $threshold;
}
/**
* Prevents any images from being automatically created.
*
* @param array $sizes Associative array of image sizes to be created.
* @param array $image_meta The image meta data: width, height, file, sizes, etc.
*
* @return array Associative array of image sizes to be created.
*/
public static function prevent_resizing( $sizes, $image_meta ) {
return [];
}
}

File diff suppressed because it is too large Load Diff

23
phpcs.xml Normal file
View File

@@ -0,0 +1,23 @@
<?xml version="1.0"?>
<ruleset name="WordPress-Thumbor">
<description>WordPress Thumbor</description>
<!-- Scan all files in directory -->
<file>.</file>
<exclude-pattern type="relative">lib/packages/*</exclude-pattern>
<!-- Scan only PHP files -->
<arg name="extensions" value="php"/>
<!-- Show colors in console -->
<arg value="-colors"/>
<!-- Show sniff codes in all reports -->
<arg value="ns"/>
<rule ref="Squiz.PHP.EmbeddedPhp">
<exclude name="Squiz.Commenting.FileComment.Missing"/>
</rule>
<rule ref="Eighteen73-WordPress-Default" />
</ruleset>

138
wordpress-thumbor.php Normal file
View File

@@ -0,0 +1,138 @@
<?php
/**
* Plugin Name: WordPress Thumbor
* Plugin URI: https://github.com/eighteen73/wordpress-thumbor
* Description: A WordPress plugin to serve media via a Thumbor server
* Author: eighteen73 Web Team
* Author URI: https://eighteen73.co.uk
* Update URI: https://github.com/eighteen73/wordpress-thumbor
* Text Domain: wordpress-thumbor
*
* @package wordpress-thumbor
*/
use Eighteen73\Thumbor\MediaOverrides;
use Eighteen73\Thumbor\ThumborImage;
spl_autoload_register(
function ( $class_name ) {
$path_parts = explode( '\\', $class_name );
if ( ! empty( $path_parts ) ) {
$package = $path_parts[0];
unset( $path_parts[0] );
if ( 'Eighteen73' === $package ) {
require_once __DIR__ . '/includes/classes/' . implode( '/', $path_parts ) . '.php';
}
}
}
);
MediaOverrides::instance();
ThumborImage::instance();
/**
* Generates a Thumbor URL.
*
* @see https://docs.altis-dxp.com/media/dynamic-images/
*
* @param string $image_url URL to the publicly accessible image you want to manipulate.
* @param array|string $args An array of arguments, i.e. array( 'w' => '300', 'resize' => array( 123, 456 ) ), or in string form (w=123&h=456).
* @param string|null $scheme One of http or https.
* @return string The raw final URL. You should run this through esc_url() before displaying it.
*/
function thumbor_url( $image_url, $args = [], $scheme = null ) {
if ( ! defined( 'THUMBOR_URL' ) || empty( THUMBOR_URL ) ) {
return;
}
/*
* Cache result for unique set of args to save reruns. This is because we're seeing the same image being re-run within a single
* request and there's a chance that filters applied within are expensive. A short TTL is used in case persistent cache is used
* but it doesn't need to be longed lived.
*/
$cache_key = md5( $image_url . json_encode( $args ) . ( $scheme ?? '' ) );
$cache_ttl = 60;
$cached_url = wp_cache_get( $cache_key, 'thumbor_url' );
if ( $cached_url ) {
return $cached_url;
}
$upload_dir = wp_upload_dir();
$upload_baseurl = $upload_dir['baseurl'];
if ( is_multisite() ) {
$upload_baseurl = preg_replace( '#/sites/[\d]+#', '', $upload_baseurl );
}
$image_url = trim( $image_url );
$image_file = basename( parse_url( $image_url, PHP_URL_PATH ) );
$image_url = str_replace( $image_file, urlencode( $image_file ), $image_url );
if ( strpos( $image_url, $upload_baseurl ) !== 0 ) {
return $image_url;
}
if ( false !== apply_filters( 'thumbor_skip_for_url', false, $image_url, $args, $scheme ) ) {
return $image_url;
}
$image_url = apply_filters( 'thumbor_pre_image_url', $image_url, $args, $scheme );
$args = apply_filters( 'thumbor_pre_args', $args, $image_url, $scheme );
if ( isset( $args['fit'] ) ) {
$scale = 'fit-in';
$width = $args['fit'][0];
$height = $args['fit'][1];
} elseif ( isset( $args['resize'] ) ) {
$scale = null;
$width = $args['resize'][0];
$height = $args['resize'][1];
} elseif ( isset( $args['w'] ) ) {
$scale = 'fit-in';
$width = $args['w'];
$height = 'orig';
} elseif ( isset( $args['h'] ) ) {
$scale = 'fit-in';
$width = 'orig';
$height = $args['h'];
} else {
$scale = 'fit-in';
$width = 'orig';
$height = 'orig';
}
$url_parts = [
'scale' => $scale,
'size' => "{$width}x{$height}",
'filters' => null,
'smart' => null,
];
$thumbor_url = implode( '/', array_filter( $url_parts ) ) . '/' . urlencode( $image_url );
if ( defined( 'THUMBOR_SECRET_KEY' ) && ! empty( THUMBOR_SECRET_KEY ) ) {
$signature = hash_hmac( 'sha1', $thumbor_url, THUMBOR_SECRET_KEY, true );
$thumbor_url = rtrim( THUMBOR_URL, '/' ) . '/' . strtr( base64_encode( $signature ), '/+', '_-' ) . '/' . $thumbor_url;
} else {
$thumbor_url = rtrim( THUMBOR_URL, '/' ) . '/unsafe/' . $thumbor_url;
}
/**
* Allows a final modification of the generated Thumbor URL.
*
* @param string $thumbor_url The final Thumbor image URL including query args.
* @param string $image_url The image URL without query args.
* @param array $args A key value array of the query args appended to $image_url.
*/
$final_thumbor_url = apply_filters( 'thumbor_url', $thumbor_url, $image_url, $args );
// Cache result to save reruns
wp_cache_set( $cache_key, $final_thumbor_url, 'thumbor_url', $cache_ttl );
return $final_thumbor_url;
}