Skip to content

Instantly share code, notes, and snippets.

@radist2s
Last active June 14, 2020 10:13
Show Gist options
  • Save radist2s/9bae3e22475d5b2dfabfdd47e9b98cc7 to your computer and use it in GitHub Desktop.
Save radist2s/9bae3e22475d5b2dfabfdd47e9b98cc7 to your computer and use it in GitHub Desktop.
WP Attachment Multiple Origin support plugin. Helps to override Sage`s `UPLOADS_URL` filter with proper origin.
# For production no filters will be applied
WP_ENV=development
WP_HOME=http://example.com
WP_SITEURL=${WP_HOME}/wp
# Should be defined for staging and development, has no effect for production
UPLOADS_URL='http://example.com/app/uploads'
# Should be defined for development, maybe skipped for staging if Bedrock used
UPLOADS_URL_STAGING='//stage.example.com/app/uploads'
# Maybe skipped for development if Bedrock used
UPLOADS_URL_DEVELOPMENT='//example.test/app/uploads'
<?php
/**
* @wordpress-plugin
* Plugin Name: Attachments Multiple Origins
* Description: Filters allowing to load attachments with different origin. Useful with "sage" `UPLOADS_URL` constant. Optionally maybe defined env-based constants: `UPLOADS_URL_DEVELOPMENT='http://dev/app/uploads'; UPLOADS_URL_STAGING='http://staging/app/uploads'`
* Author: Alex Batalov
* License: GPL-2.0+
*/
namespace WPAttachmentsMultipleOrigins;
function get_uploads_origin_id() {
if (!defined('WP_ENV')) {
return null;
}
return WP_ENV . '-' . wp_hash(WP_ENV);
}
/**
* Replace UPLOADS_URL by origin based url
*
* @param string $attachment_url
* @param int $post_id
* @return string
*/
function adjust_attachment_url_origin($attachment_url, $post_id) {
if (!defined('UPLOADS_URL') or !defined('WP_ENV')) {
return $attachment_url;
}
if (!$attachment_meta = wp_get_attachment_metadata($post_id)) {
return $attachment_url;
}
if (!$origin_meta = $attachment_meta['origin'] ?? false) {
return $attachment_url;
}
[$origin_env] = $origin = explode('-', $origin_meta);
// if origin_env and current env are same but different hash, possible from one of developer db, imported into stage
if ($origin_env === WP_ENV and $origin_meta !== get_uploads_origin_id()) {
return $attachment_url;
}
$uploads_url_constant_name = 'UPLOADS_URL_' . mb_strtoupper($origin_env);
// keep ability to modify constant name
$uploads_url_constant_name = apply_filters('uploads_origin/constant_name', $uploads_url_constant_name, $attachment_url, $post_id, $origin);
if (defined($uploads_url_constant_name)) {
if (!$uploads_url = constant($uploads_url_constant_name)) {
return $attachment_url;
}
}
else {
// this is stage possible and self uploads env not defined
if ($origin_env === WP_ENV and defined('WP_HOME')) {
// Bedrock hierarchy used as default
$uploads_url = untrailingslashit(WP_HOME) . '/app/uploads';
}
else {
return $attachment_url;
}
}
$uploads_url = apply_filters('uploads_origin/url', $uploads_url, $attachment_url, $post_id, $origin);
$attachment_url = $uploads_url . mb_substr($attachment_url, mb_strlen(UPLOADS_URL));
return $attachment_url;
}
function add_upload_origin_filters() {
if (!defined('UPLOADS_URL')) {
return;
}
/**
* Update images urls
*/
add_filter('pre_option_upload_url_path', function () {
return UPLOADS_URL;
});
add_filter('wp_get_attachment_url', function ($attachment_url, $post_id) {
return adjust_attachment_url_origin($attachment_url, $post_id);
}, 10, 2);
add_filter('wp_calculate_image_srcset', function ($sources, $size_array, $image_src, $image_meta, $attachment_id) {
foreach ($sources as &$source) {
$source['url'] = adjust_attachment_url_origin($source['url'], $attachment_id);
}
return $sources;
}, 10, 5);
add_filter('wp_update_attachment_metadata', function ($data) {
if (!defined('UPLOADS_URL') or !defined('WP_HOME')) {
return $data;
}
// If UPLOADS_URL seems as normal wp uploads url don't need to keep origin id DB.
// At this case we probably have no `production` (useful for stage env)
// or probably have no `stage` (useful for development env when one developer started project)
if (mb_strpos(UPLOADS_URL, WP_HOME) === 0) {
return $data;
}
// Store in format: `environment`-`hash`
// It allows to prevent multiple wp installs(dev) inconsistency
$data['origin'] = get_uploads_origin_id();
return $data;
});
}
if (defined('WP_ENV') and WP_ENV !== 'production' and defined('UPLOADS_URL')) {
add_upload_origin_filters();
}
<?php
/**
* In case WodPress is installed without using Bedrock, the following constants must be added
*
**/
// Environtment constant
define('WP_ENV', 'development');
// `UPLOADS_URL` should be defined for staging and development, has no effect for production
define('UPLOADS_URL', 'http://example.com/app/uploads');
// Environtment specific uploads URL
define('UPLOADS_URL_DEVELOPMENT', '//example.test/app/uploads');
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment