initial
This commit is contained in:
+334
@@ -0,0 +1,334 @@
|
||||
# Changelog
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [0.7.29] - 2026-06-15
|
||||
### Changed
|
||||
- Internal updates.
|
||||
|
||||
## [0.7.28] - 2026-06-08
|
||||
### Changed
|
||||
- Internal updates.
|
||||
|
||||
## [0.7.27] - 2026-05-25
|
||||
### Fixed
|
||||
- Phan: Address `PhanPluginDuplicateConditionalNullCoalescing` violations. [#48887]
|
||||
|
||||
## [0.7.26] - 2026-05-19
|
||||
### Changed
|
||||
- Internal updates.
|
||||
|
||||
## [0.7.25] - 2026-05-04
|
||||
### Changed
|
||||
- Internal: No longer require automattic/jetpack-changelogger as a per-project dev dependency. [#48225]
|
||||
|
||||
## [0.7.24] - 2025-11-24
|
||||
### Fixed
|
||||
- Phan: Address `PhanPossiblyUndeclaredVariable` violations. [#45911]
|
||||
|
||||
## [0.7.23] - 2025-11-10
|
||||
### Changed
|
||||
- Tests: Ensure PHP 8.5 compatibility. [#45769]
|
||||
|
||||
## [0.7.22] - 2025-10-20
|
||||
### Changed
|
||||
- Internal updates.
|
||||
|
||||
## [0.7.21] - 2025-09-19
|
||||
### Changed
|
||||
- Internal updates.
|
||||
|
||||
## [0.7.20] - 2025-09-15
|
||||
### Fixed
|
||||
- Ensure compatibility with images added via Breakdance blocks. [#45059]
|
||||
|
||||
## [0.7.19] - 2025-09-08
|
||||
### Changed
|
||||
- Internal updates.
|
||||
|
||||
## [0.7.18] - 2025-08-25
|
||||
### Fixed
|
||||
- Prevent an error when attempting to filter null. [#44874]
|
||||
|
||||
## [0.7.17] - 2025-08-18
|
||||
### Fixed
|
||||
- Add defensive check for `is_string` before trimming photon url. [#44822]
|
||||
|
||||
## [0.7.16] - 2025-08-14
|
||||
### Changed
|
||||
- Update package dependencies. [#44725]
|
||||
|
||||
## [0.7.15] - 2025-08-05
|
||||
### Changed
|
||||
- Add openlibrary.org CDN to ignore list. [#44627]
|
||||
|
||||
## [0.7.14] - 2025-07-21
|
||||
### Changed
|
||||
- Internal updates. [#39303]
|
||||
|
||||
## [0.7.13] - 2025-06-02
|
||||
### Changed
|
||||
- Internal updates.
|
||||
|
||||
## [0.7.12] - 2025-04-28
|
||||
### Changed
|
||||
- Internal updates.
|
||||
|
||||
## [0.7.11] - 2025-04-14
|
||||
### Changed
|
||||
- Internal updates.
|
||||
|
||||
## [0.7.10] - 2025-03-24
|
||||
### Changed
|
||||
- Internal updates.
|
||||
|
||||
## [0.7.9] - 2025-03-17
|
||||
### Changed
|
||||
- Internal updates.
|
||||
|
||||
## [0.7.8] - 2025-03-12
|
||||
### Changed
|
||||
- Internal updates.
|
||||
|
||||
## [0.7.7] - 2025-03-05
|
||||
### Changed
|
||||
- Internal updates.
|
||||
|
||||
## [0.7.6] - 2025-02-24
|
||||
### Changed
|
||||
- Internal updates.
|
||||
|
||||
## [0.7.5] - 2025-02-17
|
||||
### Fixed
|
||||
- Do not serve images using unsupported extensions with the cdn_url method. [#41760]
|
||||
|
||||
## [0.7.4] - 2025-02-03
|
||||
### Fixed
|
||||
- Code: Remove extra params on function calls. [#41263]
|
||||
|
||||
## [0.7.3] - 2025-01-20
|
||||
### Fixed
|
||||
- General: Ensure that double encoding doesn't happen. [#40886]
|
||||
|
||||
## [0.7.2] - 2024-12-16
|
||||
### Changed
|
||||
- Internal updates.
|
||||
|
||||
## [0.7.1] - 2024-11-25
|
||||
### Changed
|
||||
- Updated dependencies. [#40286]
|
||||
|
||||
## [0.7.0] - 2024-11-18
|
||||
### Removed
|
||||
- General: Update minimum PHP version to 7.2. [#40147]
|
||||
|
||||
## [0.6.0] - 2024-11-11
|
||||
### Changed
|
||||
- Resource Hint: use preconnect instead of dns-prefetch [#39883]
|
||||
|
||||
## [0.5.3] - 2024-11-04
|
||||
### Added
|
||||
- Enable test coverage. [#39961]
|
||||
|
||||
### Fixed
|
||||
- Fix PHPUnit coverage warnings. [#39989]
|
||||
|
||||
## [0.5.2] - 2024-10-29
|
||||
### Changed
|
||||
- Internal updates. [#39303]
|
||||
|
||||
## [0.5.1] - 2024-10-10
|
||||
### Fixed
|
||||
- Avoid deprecation notice when an image URL does not have an expected format. [#39685]
|
||||
- URL encode path parts of an image [#39560]
|
||||
|
||||
## [0.5.0] - 2024-10-07
|
||||
### Added
|
||||
- Add a public method to check if a URL is CDN url. [#39635]
|
||||
|
||||
## [0.4.9] - 2024-09-09
|
||||
### Changed
|
||||
- Update dependencies. [#39260]
|
||||
|
||||
## [0.4.8] - 2024-09-03
|
||||
### Fixed
|
||||
- Avoid a fatal error if an `<img>` tag has width or height that's not an integer or percentage.
|
||||
|
||||
## [0.4.7] - 2024-08-29
|
||||
### Changed
|
||||
- Rely on WordPress HTML API to parse HTML instead of Regex [#32700]
|
||||
|
||||
## [0.4.6] - 2024-08-26
|
||||
### Changed
|
||||
- Updated package dependencies. [#39004]
|
||||
|
||||
## [0.4.5] - 2024-08-19
|
||||
### Fixed
|
||||
- Lossless image optimization for images (should improve performance with no visible changes). [#38750]
|
||||
|
||||
## [0.4.4] - 2024-08-05
|
||||
### Changed
|
||||
- Do not serve media from Amazon CDN from Jetpack's CDN. [#38682]
|
||||
|
||||
## [0.4.3] - 2024-06-21
|
||||
### Changed
|
||||
- Image CDN: Added support for query strings in image URLs [#37931]
|
||||
- More closely match core behavior while downsizing images [#37946]
|
||||
|
||||
## [0.4.2] - 2024-06-11
|
||||
### Fixed
|
||||
- Add additional check to avoid PHP deprecation warnings. [#37788]
|
||||
|
||||
## [0.4.1] - 2024-05-20
|
||||
### Changed
|
||||
- Internal updates.
|
||||
|
||||
## [0.4.0] - 2024-05-06
|
||||
### Removed
|
||||
- Lazy Loading: Removed compatibility script for Jetpack Lazy Loading module. [#37069]
|
||||
|
||||
## [0.3.7] - 2024-04-29
|
||||
### Changed
|
||||
- Internal updates.
|
||||
|
||||
## [0.3.6] - 2024-04-25
|
||||
### Changed
|
||||
- Update dependencies. [#33960]
|
||||
|
||||
## [0.3.5] - 2024-04-22
|
||||
### Fixed
|
||||
- WP.com: Don't Photonize images on private WordPress.com sites. [#36876]
|
||||
|
||||
## [0.3.4] - 2024-04-08
|
||||
### Changed
|
||||
- Update filter docblock to match possible types. [#36731]
|
||||
|
||||
## [0.3.3] - 2024-03-15
|
||||
### Changed
|
||||
- Internal updates.
|
||||
|
||||
## [0.3.2] - 2023-12-03
|
||||
### Changed
|
||||
- Internal updates.
|
||||
|
||||
## [0.3.1] - 2023-11-24
|
||||
### Changed
|
||||
- Replaced usage of strpos() with str_contains(). [#34137]
|
||||
- Replaced usage of substr() with str_starts_with() and str_ends_with(). [#34207]
|
||||
|
||||
## [0.3.0] - 2023-11-20
|
||||
### Changed
|
||||
- Replaced usage of strpos() with str_starts_with(). [#34135]
|
||||
- The package now requires PHP >= 7.0. [#34192]
|
||||
|
||||
## [0.2.8] - 2023-11-03
|
||||
### Changed
|
||||
- Update dependencies. [#33946]
|
||||
|
||||
## [0.2.7] - 2023-10-16
|
||||
### Added
|
||||
- Added HEIC (`*.heic`) to list of images types allowed to be passed through Photon. [#33494]
|
||||
|
||||
## [0.2.6] - 2023-09-28
|
||||
### Fixed
|
||||
- Use WordPress `str_ends_with` polyfill. [#33288]
|
||||
|
||||
## [0.2.5] - 2023-09-19
|
||||
|
||||
- Minor internal updates.
|
||||
|
||||
## [0.2.4] - 2023-08-28
|
||||
### Changed
|
||||
- Updated package dependencies. [#32605]
|
||||
|
||||
## [0.2.3] - 2023-06-06
|
||||
### Fixed
|
||||
- Photon: fix potential bug where two "?" characters might be added to a url [#30865]
|
||||
|
||||
## [0.2.2] - 2023-05-15
|
||||
### Added
|
||||
- Add compatibility layer for the ActivityPub plugin [#30298]
|
||||
|
||||
## [0.2.1] - 2023-05-11
|
||||
### Added
|
||||
- Added `is_enabled()` method to check if image CDN is enabled by any plugin' [#30582]
|
||||
|
||||
## [0.2.0] - 2023-05-08
|
||||
### Added
|
||||
- Add Jetpack Autoloader package suggestion. [#29988]
|
||||
|
||||
### Changed
|
||||
- Update photon compatibility to allow using the package in Jetpack [#30050]
|
||||
|
||||
### Removed
|
||||
- Remove unused method used to update images in Open Graph Meta tags. [#30338]
|
||||
|
||||
## 0.1.0 - 2023-04-06
|
||||
### Added
|
||||
- Add image CDN package. [#29561]
|
||||
|
||||
[0.7.29]: https://github.com/Automattic/jetpack-image-cdn/compare/v0.7.28...v0.7.29
|
||||
[0.7.28]: https://github.com/Automattic/jetpack-image-cdn/compare/v0.7.27...v0.7.28
|
||||
[0.7.27]: https://github.com/Automattic/jetpack-image-cdn/compare/v0.7.26...v0.7.27
|
||||
[0.7.26]: https://github.com/Automattic/jetpack-image-cdn/compare/v0.7.25...v0.7.26
|
||||
[0.7.25]: https://github.com/Automattic/jetpack-image-cdn/compare/v0.7.24...v0.7.25
|
||||
[0.7.24]: https://github.com/Automattic/jetpack-image-cdn/compare/v0.7.23...v0.7.24
|
||||
[0.7.23]: https://github.com/Automattic/jetpack-image-cdn/compare/v0.7.22...v0.7.23
|
||||
[0.7.22]: https://github.com/Automattic/jetpack-image-cdn/compare/v0.7.21...v0.7.22
|
||||
[0.7.21]: https://github.com/Automattic/jetpack-image-cdn/compare/v0.7.20...v0.7.21
|
||||
[0.7.20]: https://github.com/Automattic/jetpack-image-cdn/compare/v0.7.19...v0.7.20
|
||||
[0.7.19]: https://github.com/Automattic/jetpack-image-cdn/compare/v0.7.18...v0.7.19
|
||||
[0.7.18]: https://github.com/Automattic/jetpack-image-cdn/compare/v0.7.17...v0.7.18
|
||||
[0.7.17]: https://github.com/Automattic/jetpack-image-cdn/compare/v0.7.16...v0.7.17
|
||||
[0.7.16]: https://github.com/Automattic/jetpack-image-cdn/compare/v0.7.15...v0.7.16
|
||||
[0.7.15]: https://github.com/Automattic/jetpack-image-cdn/compare/v0.7.14...v0.7.15
|
||||
[0.7.14]: https://github.com/Automattic/jetpack-image-cdn/compare/v0.7.13...v0.7.14
|
||||
[0.7.13]: https://github.com/Automattic/jetpack-image-cdn/compare/v0.7.12...v0.7.13
|
||||
[0.7.12]: https://github.com/Automattic/jetpack-image-cdn/compare/v0.7.11...v0.7.12
|
||||
[0.7.11]: https://github.com/Automattic/jetpack-image-cdn/compare/v0.7.10...v0.7.11
|
||||
[0.7.10]: https://github.com/Automattic/jetpack-image-cdn/compare/v0.7.9...v0.7.10
|
||||
[0.7.9]: https://github.com/Automattic/jetpack-image-cdn/compare/v0.7.8...v0.7.9
|
||||
[0.7.8]: https://github.com/Automattic/jetpack-image-cdn/compare/v0.7.7...v0.7.8
|
||||
[0.7.7]: https://github.com/Automattic/jetpack-image-cdn/compare/v0.7.6...v0.7.7
|
||||
[0.7.6]: https://github.com/Automattic/jetpack-image-cdn/compare/v0.7.5...v0.7.6
|
||||
[0.7.5]: https://github.com/Automattic/jetpack-image-cdn/compare/v0.7.4...v0.7.5
|
||||
[0.7.4]: https://github.com/Automattic/jetpack-image-cdn/compare/v0.7.3...v0.7.4
|
||||
[0.7.3]: https://github.com/Automattic/jetpack-image-cdn/compare/v0.7.2...v0.7.3
|
||||
[0.7.2]: https://github.com/Automattic/jetpack-image-cdn/compare/v0.7.1...v0.7.2
|
||||
[0.7.1]: https://github.com/Automattic/jetpack-image-cdn/compare/v0.7.0...v0.7.1
|
||||
[0.7.0]: https://github.com/Automattic/jetpack-image-cdn/compare/v0.6.0...v0.7.0
|
||||
[0.6.0]: https://github.com/Automattic/jetpack-image-cdn/compare/v0.5.3...v0.6.0
|
||||
[0.5.3]: https://github.com/Automattic/jetpack-image-cdn/compare/v0.5.2...v0.5.3
|
||||
[0.5.2]: https://github.com/Automattic/jetpack-image-cdn/compare/v0.5.1...v0.5.2
|
||||
[0.5.1]: https://github.com/Automattic/jetpack-image-cdn/compare/v0.5.0...v0.5.1
|
||||
[0.5.0]: https://github.com/Automattic/jetpack-image-cdn/compare/v0.4.9...v0.5.0
|
||||
[0.4.9]: https://github.com/Automattic/jetpack-image-cdn/compare/v0.4.8...v0.4.9
|
||||
[0.4.8]: https://github.com/Automattic/jetpack-image-cdn/compare/v0.4.7...v0.4.8
|
||||
[0.4.7]: https://github.com/Automattic/jetpack-image-cdn/compare/v0.4.6...v0.4.7
|
||||
[0.4.6]: https://github.com/Automattic/jetpack-image-cdn/compare/v0.4.5...v0.4.6
|
||||
[0.4.5]: https://github.com/Automattic/jetpack-image-cdn/compare/v0.4.4...v0.4.5
|
||||
[0.4.4]: https://github.com/Automattic/jetpack-image-cdn/compare/v0.4.3...v0.4.4
|
||||
[0.4.3]: https://github.com/Automattic/jetpack-image-cdn/compare/v0.4.2...v0.4.3
|
||||
[0.4.2]: https://github.com/Automattic/jetpack-image-cdn/compare/v0.4.1...v0.4.2
|
||||
[0.4.1]: https://github.com/Automattic/jetpack-image-cdn/compare/v0.4.0...v0.4.1
|
||||
[0.4.0]: https://github.com/Automattic/jetpack-image-cdn/compare/v0.3.7...v0.4.0
|
||||
[0.3.7]: https://github.com/Automattic/jetpack-image-cdn/compare/v0.3.6...v0.3.7
|
||||
[0.3.6]: https://github.com/Automattic/jetpack-image-cdn/compare/v0.3.5...v0.3.6
|
||||
[0.3.5]: https://github.com/Automattic/jetpack-image-cdn/compare/v0.3.4...v0.3.5
|
||||
[0.3.4]: https://github.com/Automattic/jetpack-image-cdn/compare/v0.3.3...v0.3.4
|
||||
[0.3.3]: https://github.com/Automattic/jetpack-image-cdn/compare/v0.3.2...v0.3.3
|
||||
[0.3.2]: https://github.com/Automattic/jetpack-image-cdn/compare/v0.3.1...v0.3.2
|
||||
[0.3.1]: https://github.com/Automattic/jetpack-image-cdn/compare/v0.3.0...v0.3.1
|
||||
[0.3.0]: https://github.com/Automattic/jetpack-image-cdn/compare/v0.2.8...v0.3.0
|
||||
[0.2.8]: https://github.com/Automattic/jetpack-image-cdn/compare/v0.2.7...v0.2.8
|
||||
[0.2.7]: https://github.com/Automattic/jetpack-image-cdn/compare/v0.2.6...v0.2.7
|
||||
[0.2.6]: https://github.com/Automattic/jetpack-image-cdn/compare/v0.2.5...v0.2.6
|
||||
[0.2.5]: https://github.com/Automattic/jetpack-image-cdn/compare/v0.2.4...v0.2.5
|
||||
[0.2.4]: https://github.com/Automattic/jetpack-image-cdn/compare/v0.2.3...v0.2.4
|
||||
[0.2.3]: https://github.com/Automattic/jetpack-image-cdn/compare/v0.2.2...v0.2.3
|
||||
[0.2.2]: https://github.com/Automattic/jetpack-image-cdn/compare/v0.2.1...v0.2.2
|
||||
[0.2.1]: https://github.com/Automattic/jetpack-image-cdn/compare/v0.2.0...v0.2.1
|
||||
[0.2.0]: https://github.com/Automattic/jetpack-image-cdn/compare/v0.1.0...v0.2.0
|
||||
+447
@@ -0,0 +1,447 @@
|
||||
<?php
|
||||
/**
|
||||
* Core Image CDN functionality.
|
||||
*
|
||||
* It should be available even if Image CDN is not active.
|
||||
*
|
||||
* @package automattic/jetpack-image-cdn
|
||||
*/
|
||||
|
||||
namespace Automattic\Jetpack\Image_CDN;
|
||||
|
||||
use Automattic\Jetpack\Status;
|
||||
use Automattic\Jetpack\Status\Host;
|
||||
|
||||
/**
|
||||
* A static class that provides core Image CDN functionality.
|
||||
*/
|
||||
class Image_CDN_Core {
|
||||
/**
|
||||
* Register hooks.
|
||||
*/
|
||||
public static function setup() {
|
||||
// Add photon compatibility.
|
||||
require_once __DIR__ . '/compatibility/photon.php';
|
||||
|
||||
// Add ActivityPub compatibility.
|
||||
require_once __DIR__ . '/compatibility/activitypub.php';
|
||||
|
||||
// Add Breakdance compatibility.
|
||||
require_once __DIR__ . '/compatibility/breakdance.php';
|
||||
|
||||
/**
|
||||
* Add an easy way to photon-ize a URL that is safe to call even if Jetpack isn't active.
|
||||
*
|
||||
* See: https://jetpack.com/2013/07/11/photon-and-themes/
|
||||
*/
|
||||
add_filter( 'jetpack_photon_url', array( __CLASS__, 'cdn_url' ), 10, 3 );
|
||||
|
||||
/**
|
||||
* WordPress.com
|
||||
*
|
||||
* If a cropped WP.com-hosted image is the source image, have Photon replicate the crop.
|
||||
*/
|
||||
add_filter( 'jetpack_photon_pre_args', array( __CLASS__, 'parse_wpcom_query_args' ), 10, 2 );
|
||||
|
||||
add_filter( 'jetpack_photon_skip_for_url', array( __CLASS__, 'banned_domains' ), 9, 2 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a Photon URL.
|
||||
*
|
||||
* @see https://developer.wordpress.com/docs/photon/
|
||||
*
|
||||
* @param string $image_url URL to the publicly accessible image you want to manipulate.
|
||||
* @param array|string $args An array of arguments, e.g. array( 'w' => '300', 'resize' => array( 123, 456 ) ), or in string form (w=123&h=456).
|
||||
* @param string|null $scheme URL protocol.
|
||||
* @return string The raw final URL. You should run this through esc_url() before displaying it.
|
||||
*/
|
||||
public static function cdn_url( $image_url, $args = array(), $scheme = null ) {
|
||||
if ( ! is_string( $image_url ) || empty( $image_url ) ) {
|
||||
return '';
|
||||
}
|
||||
$image_url = trim( $image_url );
|
||||
|
||||
if ( ! defined( 'IS_WPCOM' ) || ! \IS_WPCOM ) {
|
||||
/**
|
||||
* Disables Photon URL processing for local development
|
||||
*
|
||||
* @module photon
|
||||
*
|
||||
* @since 4.1.0
|
||||
*
|
||||
* @param bool false Result of Automattic\Jetpack\Status->is_offline_mode().
|
||||
*/
|
||||
if ( true === apply_filters( 'jetpack_photon_development_mode', ( new Status() )->is_offline_mode() ) ) {
|
||||
return $image_url;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow specific image URls to avoid going through Photon.
|
||||
*
|
||||
* @module photon
|
||||
*
|
||||
* @since 3.2.0
|
||||
*
|
||||
* @param bool false Should the image be returned as is, without going through Photon. Default to false.
|
||||
* @param string $image_url Image URL.
|
||||
* @param array|string $args Array of Photon arguments.
|
||||
* @param string|null $scheme Image scheme. Default to null.
|
||||
*/
|
||||
if ( false !== apply_filters( 'jetpack_photon_skip_for_url', false, $image_url, $args, $scheme ) ) {
|
||||
return $image_url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter the original image URL before it goes through Photon.
|
||||
*
|
||||
* @module photon
|
||||
*
|
||||
* @since 1.9.0
|
||||
*
|
||||
* @param string $image_url Image URL.
|
||||
* @param array|string $args Array of Photon arguments.
|
||||
* @param string|null $scheme Image scheme. Default to null.
|
||||
*/
|
||||
$image_url = apply_filters( 'jetpack_photon_pre_image_url', $image_url, $args, $scheme );
|
||||
/**
|
||||
* Filter the original Photon image parameters before Photon is applied to an image.
|
||||
*
|
||||
* @module photon
|
||||
*
|
||||
* @since 1.9.0
|
||||
*
|
||||
* @param array|string $args Array of Photon arguments.
|
||||
* @param string $image_url Image URL.
|
||||
* @param string|null $scheme Image scheme. Default to null.
|
||||
*/
|
||||
$args = apply_filters( 'jetpack_photon_pre_args', $args, $image_url, $scheme );
|
||||
|
||||
if ( empty( $image_url ) ) {
|
||||
return $image_url;
|
||||
}
|
||||
|
||||
$image_url_parts = wp_parse_url( $image_url );
|
||||
|
||||
// Unable to parse.
|
||||
if ( ! is_array( $image_url_parts ) || empty( $image_url_parts['host'] ) || empty( $image_url_parts['path'] ) ) {
|
||||
return $image_url;
|
||||
}
|
||||
|
||||
// Ensure image extension is acceptable.
|
||||
if (
|
||||
! in_array(
|
||||
strtolower( pathinfo( $image_url_parts['path'], PATHINFO_EXTENSION ) ),
|
||||
Image_CDN::get_supported_extensions(),
|
||||
true
|
||||
)
|
||||
) {
|
||||
return $image_url;
|
||||
}
|
||||
|
||||
if ( is_array( $args ) ) {
|
||||
// Convert values that are arrays into strings.
|
||||
foreach ( $args as $arg => $value ) {
|
||||
if ( is_array( $value ) ) {
|
||||
$args[ $arg ] = implode( ',', $value );
|
||||
}
|
||||
}
|
||||
|
||||
// Encode values.
|
||||
// See https://core.trac.wordpress.org/ticket/17923 .
|
||||
$args = rawurlencode_deep( $args );
|
||||
}
|
||||
|
||||
// Don't photon-ize WPCOM hosted images -- we can serve them up from wpcom directly.
|
||||
$is_wpcom_image = false;
|
||||
if ( self::ends_with( strtolower( $image_url_parts['host'] ), '.files.wordpress.com' ) ) {
|
||||
$is_wpcom_image = true;
|
||||
if ( isset( $args['ssl'] ) ) {
|
||||
// Do not send the ssl argument to prevent caching issues.
|
||||
unset( $args['ssl'] );
|
||||
}
|
||||
}
|
||||
|
||||
$is_wpcom_private_site = false;
|
||||
if ( ( new Host() )->is_wpcom_platform() && ( new Status() )->is_private_site() ) {
|
||||
$is_wpcom_private_site = true;
|
||||
if ( isset( $args['ssl'] ) ) {
|
||||
// Do not send the ssl argument to prevent caching issues.
|
||||
unset( $args['ssl'] );
|
||||
}
|
||||
}
|
||||
|
||||
// You can't run a Photon URL through Photon again because query strings are stripped.
|
||||
// So if the image is already a Photon URL, append the new arguments to the existing URL.
|
||||
// Alternately, if it's a *.files.wordpress.com url or an image on a private WordPress.com Simple site,
|
||||
// then keep the domain as is.
|
||||
if (
|
||||
self::is_cdn_url( $image_url )
|
||||
|| $is_wpcom_image
|
||||
|| $is_wpcom_private_site
|
||||
) {
|
||||
$photon_url = add_query_arg( $args, $image_url );
|
||||
return self::cdn_url_scheme( $photon_url, $scheme );
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow Photon to use query strings as well.
|
||||
* By default, Photon doesn't support query strings so we ignore them and look only at the path.
|
||||
* This setting is Photon Server dependent.
|
||||
*
|
||||
* @module photon
|
||||
*
|
||||
* @since 1.9.0
|
||||
*
|
||||
* @param bool false Should images using query strings go through Photon. Default is false.
|
||||
* @param string $image_url_parts['host'] Image URL's host.
|
||||
*/
|
||||
if ( ! apply_filters( 'jetpack_photon_any_extension_for_domain', false, $image_url_parts['host'] ) ) {
|
||||
// Photon doesn't support query strings so we ignore them and look only at the path.
|
||||
// However some source images are served via PHP so check the no-query-string extension.
|
||||
// For future proofing, this is an excluded list of common issues rather than an allow list.
|
||||
$extension = pathinfo( $image_url_parts['path'], PATHINFO_EXTENSION );
|
||||
if ( empty( $extension ) || in_array( $extension, array( 'php', 'ashx' ), true ) ) {
|
||||
return $image_url;
|
||||
}
|
||||
}
|
||||
|
||||
$image_host_path = $image_url_parts['host'] . static::escape_path( $image_url_parts['path'] );
|
||||
/**
|
||||
* Filters the domain used by the Photon module.
|
||||
*
|
||||
* @module photon
|
||||
*
|
||||
* @since 3.4.2
|
||||
*
|
||||
* @param string https://i0.wp.com Domain used by Photon.
|
||||
* @param string $image_url URL of the image to be photonized.
|
||||
*/
|
||||
$photon_domain = apply_filters( 'jetpack_photon_domain', 'https://i0.wp.com', $image_url );
|
||||
$photon_domain = trailingslashit( esc_url( $photon_domain ) );
|
||||
$photon_url = $photon_domain . $image_host_path;
|
||||
|
||||
/**
|
||||
* Add query strings to Photon URL.
|
||||
* By default, Photon doesn't support query strings so we ignore them.
|
||||
* This setting is Photon Server dependent.
|
||||
*
|
||||
* @module photon
|
||||
*
|
||||
* @since 1.9.0
|
||||
*
|
||||
* @param bool false Should query strings be added to the image URL. Default is false.
|
||||
* @param string $image_url_parts['host'] Image URL's host.
|
||||
*/
|
||||
if ( isset( $image_url_parts['query'] ) && apply_filters( 'jetpack_photon_add_query_string_to_domain', false, $image_url_parts['host'] ) ) {
|
||||
$photon_url .= '?q=' . rawurlencode( $image_url_parts['query'] );
|
||||
}
|
||||
|
||||
if ( $args ) {
|
||||
if ( is_array( $args ) ) {
|
||||
$photon_url = add_query_arg( $args, $photon_url );
|
||||
} elseif ( strpos( $photon_url, '?' ) !== false ) {
|
||||
$photon_url .= '&' . $args;
|
||||
} else {
|
||||
$photon_url .= '?' . $args;
|
||||
}
|
||||
}
|
||||
|
||||
if ( isset( $image_url_parts['scheme'] ) && 'https' === $image_url_parts['scheme'] ) {
|
||||
$photon_url = add_query_arg( array( 'ssl' => 1 ), $photon_url );
|
||||
}
|
||||
|
||||
return self::cdn_url_scheme( $photon_url, $scheme );
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a given URL is a Photon URL.
|
||||
*
|
||||
* @since 0.5.0
|
||||
* @param string $url The URL to check.
|
||||
* @return bool True if the URL is a Photon URL, false otherwise.
|
||||
*/
|
||||
public static function is_cdn_url( $url ) {
|
||||
$parsed_url = wp_parse_url( $url );
|
||||
|
||||
if ( ! $parsed_url ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// See usage in ::cdn_url for documentation of this filter
|
||||
$custom_photon_url = apply_filters( 'jetpack_photon_domain', '', $url );
|
||||
$custom_photon_url = esc_url( $custom_photon_url );
|
||||
|
||||
return in_array( $parsed_url['host'], array( 'i0.wp.com', 'i1.wp.com', 'i2.wp.com' ), true )
|
||||
|| wp_parse_url( $custom_photon_url, PHP_URL_HOST ) === $parsed_url['host'];
|
||||
}
|
||||
|
||||
/**
|
||||
* URL-encodes each path component.
|
||||
*
|
||||
* Example:
|
||||
* Input: "foo/bar baz/baz"
|
||||
* Output: "foo/bar%20baz/baz"
|
||||
*
|
||||
* @param string $path The path to escape.
|
||||
* @return string The escaped path.
|
||||
*/
|
||||
private static function escape_path( $path ) {
|
||||
$parts = explode( '/', $path );
|
||||
$parts = array_map( 'rawurldecode', $parts );
|
||||
$parts = array_map( 'rawurlencode', $parts );
|
||||
return implode( '/', $parts );
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses WP.com-hosted image args to replicate the crop.
|
||||
*
|
||||
* @param mixed $args Args set during Photon's processing.
|
||||
* @param string $image_url URL of the image.
|
||||
* @return array|string Args for Photon to use for the URL.
|
||||
*/
|
||||
public static function parse_wpcom_query_args( $args, $image_url ) {
|
||||
$parsed_url = wp_parse_url( $image_url );
|
||||
|
||||
if ( ! $parsed_url ) {
|
||||
return $args;
|
||||
}
|
||||
|
||||
$image_url_parts = wp_parse_args(
|
||||
$parsed_url,
|
||||
array(
|
||||
'host' => '',
|
||||
'query' => '',
|
||||
)
|
||||
);
|
||||
|
||||
if ( ! str_ends_with( $image_url_parts['host'], '.files.wordpress.com' ) ) {
|
||||
return $args;
|
||||
}
|
||||
|
||||
if ( empty( $image_url_parts['query'] ) ) {
|
||||
return $args;
|
||||
}
|
||||
|
||||
$wpcom_args = wp_parse_args( $image_url_parts['query'] );
|
||||
|
||||
if ( empty( $wpcom_args['w'] ) || empty( $wpcom_args['h'] ) ) {
|
||||
return $args;
|
||||
}
|
||||
|
||||
// Keep the crop by using "resize".
|
||||
if ( ! empty( $wpcom_args['crop'] ) ) {
|
||||
if ( is_array( $args ) ) {
|
||||
$args = array_merge( array( 'resize' => array( $wpcom_args['w'], $wpcom_args['h'] ) ), $args );
|
||||
} else {
|
||||
$args = 'resize=' . rawurlencode( absint( $wpcom_args['w'] ) . ',' . absint( $wpcom_args['h'] ) ) . '&' . $args;
|
||||
}
|
||||
} elseif ( is_array( $args ) ) {
|
||||
$args = array_merge( array( 'fit' => array( $wpcom_args['w'], $wpcom_args['h'] ) ), $args );
|
||||
} else {
|
||||
$args = 'fit=' . rawurlencode( absint( $wpcom_args['w'] ) . ',' . absint( $wpcom_args['h'] ) ) . '&' . $args;
|
||||
}
|
||||
|
||||
return $args;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the scheme for a URL
|
||||
*
|
||||
* @param string $url URL to set scheme.
|
||||
* @param string $scheme Scheme to use. Accepts http, https, network_path.
|
||||
*
|
||||
* @return string URL.
|
||||
*/
|
||||
public static function cdn_url_scheme( $url, $scheme ) {
|
||||
if ( ! in_array( $scheme, array( 'http', 'https', 'network_path' ), true ) ) {
|
||||
if ( preg_match( '#^(https?:)?//#', $url ) ) {
|
||||
return $url;
|
||||
}
|
||||
|
||||
$scheme = 'http';
|
||||
}
|
||||
|
||||
if ( 'network_path' === $scheme ) {
|
||||
$scheme_slashes = '//';
|
||||
} else {
|
||||
$scheme_slashes = "$scheme://";
|
||||
}
|
||||
|
||||
return preg_replace( '#^([a-z:]+)?//#i', $scheme_slashes, $url );
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to skip Photon for a known domain that shouldn't be Photonized.
|
||||
*
|
||||
* @param bool $skip If the image should be skipped by Photon.
|
||||
* @param string $image_url URL of the image.
|
||||
*
|
||||
* @return bool Should the image be skipped by Photon.
|
||||
*/
|
||||
public static function banned_domains( $skip, $image_url ) {
|
||||
$banned_host_patterns = array(
|
||||
'/^chart\.googleapis\.com$/',
|
||||
'/^chart\.apis\.google\.com$/',
|
||||
'/^graph\.facebook\.com$/',
|
||||
'/\.fbcdn\.net$/',
|
||||
'/\.paypalobjects\.com$/',
|
||||
'/\.dropbox\.com$/',
|
||||
'/\.cdninstagram\.com$/',
|
||||
'/^(commons|upload)\.wikimedia\.org$/',
|
||||
'/\.wikipedia\.org$/',
|
||||
'/^m\.media-amazon\.com$/',
|
||||
'/^covers\.openlibrary\.org$/',
|
||||
);
|
||||
|
||||
$host = wp_parse_url( $image_url, PHP_URL_HOST );
|
||||
if ( ! $host ) {
|
||||
return $skip;
|
||||
}
|
||||
|
||||
foreach ( $banned_host_patterns as $banned_host_pattern ) {
|
||||
if ( 1 === preg_match( $banned_host_pattern, $host ) ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return $skip;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether a string ends with a specific substring.
|
||||
*
|
||||
* @param string $haystack String we are filtering.
|
||||
* @param string $needle The substring we are looking for.
|
||||
* @return bool
|
||||
*/
|
||||
public static function ends_with( $haystack, $needle ) {
|
||||
if ( ! $haystack || ! $needle || ! is_scalar( $haystack ) || ! is_scalar( $needle ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$haystack = (string) $haystack;
|
||||
$needle = (string) $needle;
|
||||
|
||||
return str_ends_with( $haystack, $needle );
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a copy of Jetpack::get_content_width()
|
||||
* for backwards compatibility.
|
||||
*/
|
||||
public static function get_jetpack_content_width() {
|
||||
$content_width = ( isset( $GLOBALS['content_width'] ) && is_numeric( $GLOBALS['content_width'] ) )
|
||||
? $GLOBALS['content_width']
|
||||
: false;
|
||||
/**
|
||||
* Filter the Content Width value.
|
||||
*
|
||||
* @since 2.2.3
|
||||
*
|
||||
* @param string $content_width Content Width value.
|
||||
*/
|
||||
return apply_filters( 'jetpack_content_width', $content_width );
|
||||
}
|
||||
}
|
||||
+199
@@ -0,0 +1,199 @@
|
||||
<?php
|
||||
/**
|
||||
* The Image Sizes library.
|
||||
*
|
||||
* @package automattic/jetpack-image-cdn
|
||||
*/
|
||||
|
||||
namespace Automattic\Jetpack\Image_CDN;
|
||||
|
||||
/**
|
||||
* Class Image_CDN_Image_Sizes
|
||||
*
|
||||
* Manages image resizing via Jetpack CDN Service.
|
||||
*/
|
||||
class Image_CDN_Image_Sizes {
|
||||
|
||||
/**
|
||||
* Attachment metadata.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $data;
|
||||
|
||||
/**
|
||||
* Image to be resized.
|
||||
*
|
||||
* @var Image_CDN_Image
|
||||
*/
|
||||
public $image;
|
||||
|
||||
/**
|
||||
* Intermediate sizes.
|
||||
*
|
||||
* @var null|array
|
||||
*/
|
||||
public static $sizes = null;
|
||||
|
||||
/**
|
||||
* Construct new sizes meta
|
||||
*
|
||||
* @param int $attachment_id Attachment ID.
|
||||
* @param array $data Attachment metadata.
|
||||
*/
|
||||
public function __construct( $attachment_id, $data ) {
|
||||
$this->data = $data;
|
||||
$this->image = new Image_CDN_Image( $data, get_post_mime_type( $attachment_id ) );
|
||||
$this->generate_sizes();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate sizes for attachment.
|
||||
*
|
||||
* @return array Array of sizes; empty array as failure fallback.
|
||||
*/
|
||||
protected function generate_sizes() {
|
||||
|
||||
// There is no need to generate the sizes anew for every single image.
|
||||
if ( null !== self::$sizes ) {
|
||||
return self::$sizes;
|
||||
}
|
||||
|
||||
/*
|
||||
* The following logic is copied over from wp_generate_attachment_metadata
|
||||
*/
|
||||
$_wp_additional_image_sizes = wp_get_additional_image_sizes();
|
||||
|
||||
$sizes = array();
|
||||
|
||||
$intermediate_image_sizes = get_intermediate_image_sizes();
|
||||
|
||||
foreach ( $intermediate_image_sizes as $s ) {
|
||||
$sizes[ $s ] = array(
|
||||
'width' => '',
|
||||
'height' => '',
|
||||
'crop' => false,
|
||||
);
|
||||
if ( isset( $_wp_additional_image_sizes[ $s ]['width'] ) ) {
|
||||
// For theme-added sizes.
|
||||
$sizes[ $s ]['width'] = (int) $_wp_additional_image_sizes[ $s ]['width'];
|
||||
} else {
|
||||
// For default sizes set in options.
|
||||
$sizes[ $s ]['width'] = get_option( "{$s}_size_w" );
|
||||
}
|
||||
|
||||
if ( isset( $_wp_additional_image_sizes[ $s ]['height'] ) ) {
|
||||
// For theme-added sizes.
|
||||
$sizes[ $s ]['height'] = (int) $_wp_additional_image_sizes[ $s ]['height'];
|
||||
} else {
|
||||
// For default sizes set in options.
|
||||
$sizes[ $s ]['height'] = get_option( "{$s}_size_h" );
|
||||
}
|
||||
|
||||
if ( isset( $_wp_additional_image_sizes[ $s ]['crop'] ) ) {
|
||||
// For theme-added sizes.
|
||||
$sizes[ $s ]['crop'] = $_wp_additional_image_sizes[ $s ]['crop'];
|
||||
} else {
|
||||
// For default sizes set in options.
|
||||
$sizes[ $s ]['crop'] = get_option( "{$s}_crop" );
|
||||
}
|
||||
}
|
||||
|
||||
self::$sizes = $sizes;
|
||||
|
||||
return $sizes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add filtered sizes.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function filtered_sizes() {
|
||||
// Remove filter preventing the creation of advanced sizes.
|
||||
remove_filter(
|
||||
'intermediate_image_sizes_advanced',
|
||||
array( Image_CDN::class, 'filter_photon_noresize_intermediate_sizes' )
|
||||
);
|
||||
|
||||
// Compatibility fix: Ensure that Jetpack's inbuilt Photon does not get in the way.
|
||||
// No need to re-enable this filter if present, as its functionality will be handled
|
||||
// by the Image_CDN filter added below.
|
||||
remove_filter(
|
||||
'intermediate_image_sizes_advanced',
|
||||
array( 'Jetpack_Photon', 'filter_photon_noresize_intermediate_sizes' )
|
||||
);
|
||||
|
||||
/** This filter is documented in wp-admin/includes/image.php */
|
||||
$sizes = apply_filters( 'intermediate_image_sizes_advanced', self::$sizes, $this->data );
|
||||
|
||||
// Re-add the filter removed above.
|
||||
add_filter(
|
||||
'intermediate_image_sizes_advanced',
|
||||
array( Image_CDN::class, 'filter_photon_noresize_intermediate_sizes' )
|
||||
);
|
||||
|
||||
return (array) $sizes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Standardises and validates the size_data array.
|
||||
*
|
||||
* @param array $size_data Size data array - at least containing height or width key. Can contain crop as well.
|
||||
*
|
||||
* @return array Array with populated width, height and crop keys; empty array if no width and height are provided.
|
||||
*/
|
||||
public function standardize_size_data( $size_data ) {
|
||||
$has_at_least_width_or_height = ( isset( $size_data['width'] ) || isset( $size_data['height'] ) );
|
||||
if ( ! $has_at_least_width_or_height ) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$defaults = array(
|
||||
'width' => null,
|
||||
'height' => null,
|
||||
'crop' => false,
|
||||
);
|
||||
|
||||
return array_merge( $defaults, $size_data );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get sizes for attachment post meta.
|
||||
*
|
||||
* @return array ImageSizes for attachment postmeta.
|
||||
*/
|
||||
public function generate_sizes_meta() {
|
||||
|
||||
$metadata = array();
|
||||
|
||||
foreach ( $this->filtered_sizes() as $size => $size_data ) {
|
||||
|
||||
$size_data = $this->standardize_size_data( $size_data );
|
||||
|
||||
if ( empty( $size_data ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$resized_image = $this->resize( $size_data );
|
||||
|
||||
if ( is_array( $resized_image ) ) {
|
||||
$metadata[ $size ] = $resized_image;
|
||||
}
|
||||
}
|
||||
|
||||
return $metadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resize image.
|
||||
*
|
||||
* @param array $size_data Resize parameters.
|
||||
*
|
||||
* @return array|\WP_Error Array for usage in $metadata['sizes']; WP_Error on failure.
|
||||
*/
|
||||
protected function resize( $size_data ) {
|
||||
|
||||
return $this->image->get_size( $size_data );
|
||||
}
|
||||
}
|
||||
+267
@@ -0,0 +1,267 @@
|
||||
<?php
|
||||
/**
|
||||
* The Image Class.
|
||||
*
|
||||
* @package automattic/jetpack-image-cdn
|
||||
*/
|
||||
|
||||
namespace Automattic\Jetpack\Image_CDN;
|
||||
|
||||
use WP_Error;
|
||||
|
||||
/**
|
||||
* Represents a resizable image, exposing properties necessary for properly generating srcset.
|
||||
*/
|
||||
class Image_CDN_Image {
|
||||
|
||||
/**
|
||||
* Attachment's Filename.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $filename;
|
||||
|
||||
/**
|
||||
* Attachment's mime-type, WP_Error on failure when recalculating the dimensions.
|
||||
*
|
||||
* @var string|WP_Error
|
||||
*/
|
||||
private $mime_type;
|
||||
|
||||
/**
|
||||
* Image original width.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $original_width;
|
||||
|
||||
/**
|
||||
* Image original height.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $original_height;
|
||||
|
||||
/**
|
||||
* Current attachment's width.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $width;
|
||||
|
||||
/**
|
||||
* Current attachment's height.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $height;
|
||||
|
||||
/**
|
||||
* Whether the attachment has been resized yet, or not.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $is_resized = false;
|
||||
|
||||
/**
|
||||
* Constructs the image object.
|
||||
*
|
||||
* The $data array should provide at least
|
||||
* file : string Image file path
|
||||
* width : int Image width
|
||||
* height : int Image height
|
||||
*
|
||||
* @param array $data Array of attachment metadata, typically value of _wp_attachment_metadata postmeta.
|
||||
* @param string|WP_Error $mime_type Typically value returned from get_post_mime_type function.
|
||||
*/
|
||||
public function __construct( $data, $mime_type ) {
|
||||
$this->filename = $data['file'];
|
||||
$this->original_width = $data['width'];
|
||||
$this->original_height = $data['height'];
|
||||
$this->width = $this->original_width;
|
||||
$this->height = $this->original_height;
|
||||
$this->mime_type = $mime_type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resizes the image to given size.
|
||||
*
|
||||
* @param array $size_data Array of width, height, and crop properties of a size.
|
||||
*
|
||||
* @return bool|WP_Error True if resize was successful, WP_Error on failure.
|
||||
*/
|
||||
public function resize( $size_data ) {
|
||||
|
||||
$dimensions = $this->image_resize_dimensions( $size_data['width'], $size_data['height'], $size_data['crop'] );
|
||||
|
||||
if ( true === is_wp_error( $dimensions ) ) {
|
||||
return $dimensions; // Returns WP_Error.
|
||||
}
|
||||
|
||||
if ( true === is_wp_error( $this->mime_type ) ) {
|
||||
return $this->mime_type; // Returns WP_Error.
|
||||
}
|
||||
|
||||
$this->set_width_height( $dimensions );
|
||||
|
||||
$this->is_resized = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates size data for usage in $metadata['sizes'];.
|
||||
*
|
||||
* @param array $size_data Array of width, height, and crop properties of a size.
|
||||
*
|
||||
* @return array|WP_Error An array containing file, width, height, and mime-type keys and it's values. WP_Error on failure.
|
||||
*/
|
||||
public function get_size( $size_data ) {
|
||||
|
||||
$is_resized = $this->resize( $size_data );
|
||||
|
||||
if ( true === is_wp_error( $is_resized ) ) {
|
||||
return $is_resized;
|
||||
}
|
||||
|
||||
return array(
|
||||
'file' => $this->get_filename(),
|
||||
'width' => $this->get_width(),
|
||||
'height' => $this->get_height(),
|
||||
'mime-type' => $this->get_mime_type(),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the image to it's original dimensions.
|
||||
*
|
||||
* @return bool True on successful reset to original dimensions.
|
||||
*/
|
||||
public function reset_to_original() {
|
||||
$this->width = $this->original_width;
|
||||
$this->height = $this->original_height;
|
||||
$this->is_resized = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the basename filename. If the image has been resized, including
|
||||
* the resizing params for Jetpack CDN.
|
||||
*
|
||||
* @return string Basename of the filename.
|
||||
*/
|
||||
public function get_filename() {
|
||||
return wp_basename( $this->get_raw_filename() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the absolute filename. If the image has been resized, including
|
||||
* the resizing params for Jetpack CDN.
|
||||
*
|
||||
* @return string Filename.
|
||||
*/
|
||||
public function get_raw_filename() {
|
||||
return $this->is_resized() ? $this->get_resized_filename() : $this->filename;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns current image width. Either original, or after resize.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function get_width() {
|
||||
return (int) $this->width;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns current image height. Either original, or after resize.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function get_height() {
|
||||
return (int) $this->height;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns image mime type.
|
||||
*
|
||||
* @return string|WP_Error Image's mime type or WP_Error if it was not determined.
|
||||
*/
|
||||
public function get_mime_type() {
|
||||
return $this->mime_type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the resize status of the image.
|
||||
*
|
||||
* @return bool If the image has been resized.
|
||||
*/
|
||||
public function is_resized() {
|
||||
return ( true === $this->is_resized );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get filename with proper args for the Photon service.
|
||||
*
|
||||
* @return string Filename with query args for Photon service
|
||||
*/
|
||||
protected function get_resized_filename() {
|
||||
$query_args = array(
|
||||
'resize' => implode(
|
||||
',',
|
||||
array(
|
||||
$this->get_width(),
|
||||
$this->get_height(),
|
||||
)
|
||||
),
|
||||
);
|
||||
|
||||
return add_query_arg( $query_args, $this->filename );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get resize dimensions used for the Jetpack CDN service.
|
||||
*
|
||||
* Converts the list of values returned from `image_resize_dimensions()` to
|
||||
* associative array for the sake of more readable code no relying on index
|
||||
* nor `list`.
|
||||
*
|
||||
* @param int $max_width Maximum width.
|
||||
* @param int $max_height Maximum height.
|
||||
* @param bool|array $crop Cropping parameters.
|
||||
*
|
||||
* @return array|WP_Error Array of dimensions matching the parameters to imagecopyresampled. WP_Error on failure.
|
||||
*/
|
||||
protected function image_resize_dimensions( $max_width, $max_height, $crop ) {
|
||||
$dimensions = image_resize_dimensions( $this->original_width, $this->original_height, $max_width, $max_height, $crop );
|
||||
if ( ! $dimensions ) {
|
||||
return new WP_Error( 'error_getting_dimensions', __( 'Could not calculate resized image dimensions', 'jetpack-image-cdn' ), $this->filename );
|
||||
}
|
||||
|
||||
return array_combine(
|
||||
array(
|
||||
'dst_x',
|
||||
'dst_y',
|
||||
'src_x',
|
||||
'src_y',
|
||||
'dst_w',
|
||||
'dst_h',
|
||||
'src_w',
|
||||
'src_h',
|
||||
),
|
||||
$dimensions
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets proper width and height from dimensions.
|
||||
*
|
||||
* @param array $dimensions an array of image dimensions.
|
||||
* @return void
|
||||
*/
|
||||
protected function set_width_height( $dimensions ) {
|
||||
$this->width = (int) $dimensions['dst_w'];
|
||||
$this->height = (int) $dimensions['dst_h'];
|
||||
}
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
/**
|
||||
* Package description here
|
||||
*
|
||||
* @package automattic/jetpack-image-cdn
|
||||
*/
|
||||
|
||||
namespace Automattic\Jetpack\Image_CDN;
|
||||
|
||||
/**
|
||||
* Class description.
|
||||
*/
|
||||
class Image_CDN_Setup {
|
||||
|
||||
/**
|
||||
* Initialize Image CDN.
|
||||
*/
|
||||
public static function load() {
|
||||
\Automattic\Jetpack\Assets::add_resource_hint(
|
||||
array(
|
||||
'//i0.wp.com',
|
||||
),
|
||||
'preconnect'
|
||||
);
|
||||
|
||||
Image_CDN::instance();
|
||||
}
|
||||
}
|
||||
+1484
File diff suppressed because it is too large
Load Diff
+62
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
/**
|
||||
* Compatibility functions for the ActivityPub plugin.
|
||||
*
|
||||
* @since 0.2.2
|
||||
*
|
||||
* @package automattic/jetpack-image-cdn
|
||||
*/
|
||||
|
||||
namespace Automattic\Jetpack\Image_CDN\Compatibility;
|
||||
|
||||
use Automattic\Jetpack\Image_CDN\Image_CDN;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit( 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook the compatibility functions into ActivityPub filters if necessary.
|
||||
*
|
||||
* @since 0.2.2
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function load_activitypub_compat() {
|
||||
if (
|
||||
/**
|
||||
* Allow disabling Jetpack's image CDN for ActivityPub requests.
|
||||
*
|
||||
* @since 0.2.2
|
||||
*
|
||||
* @param bool $should_disable_photon Should the CDN be disabled for that request. Default to false.
|
||||
*/
|
||||
apply_filters( 'jetpack_activitypub_post_disable_cdn', false )
|
||||
) {
|
||||
add_action( 'activitypub_get_image_pre', __NAMESPACE__ . '\disable_photon' );
|
||||
add_action( 'activitypub_get_image_post', __NAMESPACE__ . '\enable_photon' );
|
||||
}
|
||||
}
|
||||
add_action( 'plugins_loaded', __NAMESPACE__ . '\load_activitypub_compat' );
|
||||
|
||||
/**
|
||||
* Disable Jetpack's Image CDN processing for this request.
|
||||
*
|
||||
* @see https://github.com/pfefferle/wordpress-activitypub/pull/309
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function disable_photon() {
|
||||
remove_filter( 'image_downsize', array( Image_CDN::instance(), 'filter_image_downsize' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-enable Jetpack's Image CDN processing after the request.
|
||||
*
|
||||
* @see https://github.com/pfefferle/wordpress-activitypub/pull/309
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function enable_photon() {
|
||||
add_filter( 'image_downsize', array( Image_CDN::instance(), 'filter_image_downsize' ), 10, 3 );
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
/**
|
||||
* Compatibility functions for the Breakdance plugin.
|
||||
*
|
||||
* @since 0.7.20
|
||||
*
|
||||
* @package automattic/jetpack-image-cdn
|
||||
*/
|
||||
|
||||
namespace Automattic\Jetpack\Image_CDN\Compatibility;
|
||||
|
||||
use Automattic\Jetpack\Image_CDN\Image_CDN;
|
||||
|
||||
/**
|
||||
* Hook the compatibility functions into Breakdance filters.
|
||||
*
|
||||
* @since 0.7.20
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function load_breakdance_compat() {
|
||||
add_filter( 'breakdance_singular_content', __NAMESPACE__ . '\use_image_cdn' );
|
||||
}
|
||||
add_action( 'plugins_loaded', __NAMESPACE__ . '\load_breakdance_compat' );
|
||||
|
||||
/**
|
||||
* Unless the 'Apply the_content filter to Breakdance content' option is enabled
|
||||
* in the Breakdance settings, the content will not be filtered by the_content filter.
|
||||
* This ensures that images are passed through Image CDN when it's enabled.
|
||||
*
|
||||
* @since 0.7.20
|
||||
*
|
||||
* @param string $content The content to filter.
|
||||
* @return string The filtered content.
|
||||
*/
|
||||
function use_image_cdn( $content ) {
|
||||
if ( Image_CDN::is_enabled() ) {
|
||||
$content = Image_CDN::filter_the_content( $content );
|
||||
}
|
||||
|
||||
return $content;
|
||||
}
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
/**
|
||||
* Compatibility for Photon
|
||||
*
|
||||
* Replace photon with image-cdn.
|
||||
*
|
||||
* @package automattic/jetpack-image-cdn
|
||||
*/
|
||||
|
||||
namespace Automattic\Jetpack\Image_CDN\Compatibility;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit( 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable the unpackaged photon version living in Jetpack.
|
||||
*
|
||||
* Before the package, Jetpack had the photon functionality within the plugin. To avoid double
|
||||
* activation, we need to disable the photon functionality in Jetpack to avoid potential conflicts.
|
||||
*
|
||||
* If this package is installed via a different plugin, e.g. Boost, Image CDN should be served instead
|
||||
* of the photon module in Jetpack.
|
||||
*/
|
||||
function jetpack_image_cdn_photon_compat() {
|
||||
/*
|
||||
* Photon used have different functions names. They are later replaced by methods in
|
||||
* Image_CDN_Core class. And the filters are now handled by the Image_CDN_Core class itself.
|
||||
*/
|
||||
remove_filter( 'jetpack_photon_url', 'jetpack_photon_url', 10 );
|
||||
remove_filter( 'jetpack_photon_pre_args', 'jetpack_photon_parse_wpcom_query_args', 10 );
|
||||
remove_filter( 'jetpack_photon_skip_for_url', 'jetpack_photon_banned_domains', 9 );
|
||||
remove_filter( 'widget_text', 'jetpack_photon_support_text_widgets' );
|
||||
|
||||
/*
|
||||
* If photon is active in an old version of Jetpack which is using the unpackaged photon
|
||||
* fake loading the module in Jetpack itself. This will prevent jetpack from loading
|
||||
* the photon module, and we will use the image CDN package instead.
|
||||
*
|
||||
* When this is happening, the package is likely being loaded from a different plugin, e.g. Boost.
|
||||
*/
|
||||
if ( class_exists( 'Jetpack' ) && defined( 'JETPACK__VERSION' ) && ( version_compare( JETPACK__VERSION, '12.1', '<=' ) ) ) {
|
||||
do_action( 'jetpack_module_loaded_photon' );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove the hooks that Jetpack uses to load photon and pretend that the module is already loaded.
|
||||
*
|
||||
* Jetpack hooks the filters as it loads. So, we can remove the filters when `plugins_loaded` fires.
|
||||
* This would make sure Jetpack has already loaded and hooked the filters.
|
||||
*/
|
||||
add_action( 'plugins_loaded', __NAMESPACE__ . '\jetpack_image_cdn_photon_compat' );
|
||||
Reference in New Issue
Block a user