Version Description
= 1.1 = This is a major change, which ensures S3 URLs are no longer saved in post content. Instead, local URLs are filtered on page generation and replaced with the S3 version. If you depend on the S3 URLs being stored in post content you will need to make modifications to support this version.
= 0.6 = This version requires PHP 5.3.3+ and the Amazon Web Services plugin
Download this release
Release Info
Developer | deliciousbrains |
Plugin | WP Offload S3 Lite |
Version | 1.1.1 |
Comparing to | |
See all releases |
Code changes from version 1.0.5 to 1.1.1
- README.md +32 -13
- assets/css/attachment.css +1 -0
- assets/css/media.css +1 -0
- assets/js/media.js +160 -0
- assets/js/media.min.js +1 -0
- assets/js/modal.min.js +1 -1
- assets/js/script.min.js +1 -1
- assets/sass/attachment.scss +61 -0
- assets/sass/media.scss +26 -0
- classes/amazon-s3-and-cloudfront.php +615 -137
- classes/as3cf-filter.php +692 -0
- classes/as3cf-notices.php +12 -15
- classes/as3cf-plugin-compatibility.php +44 -80
- classes/as3cf-upgrade.php +140 -53
- classes/filters/as3cf-local-to-s3.php +197 -0
- classes/filters/as3cf-s3-to-local.php +208 -0
- classes/upgrades/as3cf-content-replace-urls.php +623 -0
- classes/upgrades/as3cf-edd-replace-urls.php +105 -0
- classes/upgrades/as3cf-file-sizes.php +10 -9
- classes/upgrades/as3cf-meta-wp-error.php +9 -8
- classes/upgrades/as3cf-region-meta.php +10 -9
- languages/amazon-s3-and-cloudfront-en.pot +170 -110
- readme.txt +32 -13
- view/attachment-metabox.php +56 -0
- view/settings.php +2 -9
- view/sidebar.php +0 -1
- wordpress-s3.php +8 -3
README.md
CHANGED
@@ -2,8 +2,8 @@
|
|
2 |
**Contributors:** bradt, deliciousbrains
|
3 |
**Tags:** uploads, amazon, s3, amazon s3, mirror, admin, media, cdn, cloudfront
|
4 |
**Requires at least:** 4.4
|
5 |
-
**Tested up to:** 4.6
|
6 |
-
**Stable tag:** 1.
|
7 |
**License:** GPLv3
|
8 |
|
9 |
Copies files to Amazon S3 as they are uploaded to the Media Library. Optionally configure Amazon CloudFront for faster delivery.
|
@@ -21,7 +21,6 @@ If you're adding this plugin to a site that's been around for a while, your exis
|
|
21 |
**PRO Upgrade with Email Support and More Features**
|
22 |
|
23 |
* Upload existing Media Library to Amazon S3
|
24 |
-
* Find & replace file URLs in content
|
25 |
* Control Amazon S3 files from the Media Library
|
26 |
* [Assets addon](https://deliciousbrains.com/wp-offload-s3/?utm_source=wordpress.org&utm_medium=web&utm_content=desc&utm_campaign=os3-free-plugin#assets-addon) - Serve your CSS & JS from Amazon S3/CloudFront
|
27 |
* [WooCommerce addon](https://deliciousbrains.com/wp-offload-s3/?utm_source=wordpress.org&utm_medium=web&utm_content=desc&utm_campaign=os3-free-plugin#woocommerce-addon)
|
@@ -62,25 +61,45 @@ You can see the minimum requirements [here](https://deliciousbrains.com/wp-offlo
|
|
62 |
|
63 |
## Upgrade Notice ##
|
64 |
|
|
|
|
|
|
|
65 |
### 0.6 ###
|
66 |
This version requires PHP 5.3.3+ and the Amazon Web Services plugin
|
67 |
|
68 |
## Changelog ##
|
69 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
70 |
### WP Offload S3 Lite 1.0.5 - 2016-09-01 ###
|
71 |
* New: Compatibility with WordPress 4.6
|
72 |
* Improvement: No longer delete plugin data on uninstall. Manual removal possible, as per this [doc](https://deliciousbrains.com/wp-offload-s3/doc/uninstall/)
|
73 |
|
74 |
### WP Offload S3 Lite 1.0.4 - 2016-05-30 ###
|
75 |
-
* New: Now using simpler Force HTTPS setting, removed redundant Always Use HTTP setting
|
76 |
-
* New: `as3cf_cloudfront_path_parts` filter allows changing served CloudFront path (useful when distribution pulls subdirectory)
|
77 |
-
* Improvement: Better compatibility with non-standard notices from other plugins and themes
|
78 |
-
* Improvement: Added basic auth and proxy info to diagnostic info
|
79 |
-
* Improvement: Added `allow_url_fopen` status to diagnostic info
|
80 |
-
* Improvement: Added memory usage to diagnostic info
|
81 |
-
* Improvement: Ensure notice text is 800px or less in width
|
82 |
-
* Improvement: Reduced database queries on settings screen
|
83 |
-
* Bug fix: Properly handle _wp_attachment_data metadata when it is a serialized WP_Error
|
84 |
|
85 |
### WP Offload S3 Lite 1.0.3 - 2016-03-23 ###
|
86 |
* Bug fix: Don't replace srcset URLs when Rewrite File URLs option disabled
|
@@ -101,7 +120,7 @@ This version requires PHP 5.3.3+ and the Amazon Web Services plugin
|
|
101 |
* Improvement: Far future expiration header set by default
|
102 |
* Improvement: Newly created bucket now immediately appears in the bucket list
|
103 |
* Improvement: Cleanup user meta on uninstall
|
104 |
-
* Improvement: WP Retina 2x integration
|
105 |
* Bug fix: Year/Month folder structure on S3 not created if the 'Organise my uploads into month and year-based folders' WordPress setting is disabled
|
106 |
* Bug fix: Responsive srcset PHP notices
|
107 |
* Bug fix: Compatibility addon notices displayed to non-admin users
|
2 |
**Contributors:** bradt, deliciousbrains
|
3 |
**Tags:** uploads, amazon, s3, amazon s3, mirror, admin, media, cdn, cloudfront
|
4 |
**Requires at least:** 4.4
|
5 |
+
**Tested up to:** 4.6.1
|
6 |
+
**Stable tag:** 1.1.1
|
7 |
**License:** GPLv3
|
8 |
|
9 |
Copies files to Amazon S3 as they are uploaded to the Media Library. Optionally configure Amazon CloudFront for faster delivery.
|
21 |
**PRO Upgrade with Email Support and More Features**
|
22 |
|
23 |
* Upload existing Media Library to Amazon S3
|
|
|
24 |
* Control Amazon S3 files from the Media Library
|
25 |
* [Assets addon](https://deliciousbrains.com/wp-offload-s3/?utm_source=wordpress.org&utm_medium=web&utm_content=desc&utm_campaign=os3-free-plugin#assets-addon) - Serve your CSS & JS from Amazon S3/CloudFront
|
26 |
* [WooCommerce addon](https://deliciousbrains.com/wp-offload-s3/?utm_source=wordpress.org&utm_medium=web&utm_content=desc&utm_campaign=os3-free-plugin#woocommerce-addon)
|
61 |
|
62 |
## Upgrade Notice ##
|
63 |
|
64 |
+
### 1.1 ###
|
65 |
+
This is a major change, which ensures S3 URLs are no longer saved in post content. Instead, local URLs are filtered on page generation and replaced with the S3 version. If you depend on the S3 URLs being stored in post content you will need to make modifications to support this version.
|
66 |
+
|
67 |
### 0.6 ###
|
68 |
This version requires PHP 5.3.3+ and the Amazon Web Services plugin
|
69 |
|
70 |
## Changelog ##
|
71 |
|
72 |
+
### WP Offload S3 Lite 1.1.1 - 2016-10-17 ###
|
73 |
+
* New: Filter post excerpts - S3 URLs will no longer be saved to the database
|
74 |
+
* Bug fix: PHP 5.3 Fatal error: Using $this when not in object context
|
75 |
+
* Bug fix: Query string parameters incorrectly encoded for Media Library items
|
76 |
+
|
77 |
+
### WP Offload S3 Lite 1.1 - 2016-09-29 ###
|
78 |
+
* New: Filter post content. S3 URLs will no longer be saved to the database
|
79 |
+
* New: Upgrade routine to replace all S3 URLs in content with local URLs
|
80 |
+
* New: Support for theme custom logos
|
81 |
+
* New: Control the ACL for intermediate image sizes using the `as3cf_upload_acl_sizes` filter
|
82 |
+
* Bug fix: File names containing special characters double encoded
|
83 |
+
* Bug fix: `srcset` not working for file names containing special characters
|
84 |
+
* Bug fix: Incorrect placeholder text for 'Path' option
|
85 |
+
* Bug fix: Objects in root of bucket not deleted when removed from the Media Library
|
86 |
+
* Bug fix: No longer use deprecated functions in WordPress 4.6
|
87 |
+
* Bug fix: Don't delete local file when 'Remove Files From Server' enabled and upload to S3 fails
|
88 |
+
|
89 |
### WP Offload S3 Lite 1.0.5 - 2016-09-01 ###
|
90 |
* New: Compatibility with WordPress 4.6
|
91 |
* Improvement: No longer delete plugin data on uninstall. Manual removal possible, as per this [doc](https://deliciousbrains.com/wp-offload-s3/doc/uninstall/)
|
92 |
|
93 |
### WP Offload S3 Lite 1.0.4 - 2016-05-30 ###
|
94 |
+
* New: Now using simpler Force HTTPS setting, removed redundant Always Use HTTP setting
|
95 |
+
* New: `as3cf_cloudfront_path_parts` filter allows changing served CloudFront path (useful when distribution pulls subdirectory)
|
96 |
+
* Improvement: Better compatibility with non-standard notices from other plugins and themes
|
97 |
+
* Improvement: Added basic auth and proxy info to diagnostic info
|
98 |
+
* Improvement: Added `allow_url_fopen` status to diagnostic info
|
99 |
+
* Improvement: Added memory usage to diagnostic info
|
100 |
+
* Improvement: Ensure notice text is 800px or less in width
|
101 |
+
* Improvement: Reduced database queries on settings screen
|
102 |
+
* Bug fix: Properly handle _wp_attachment_data metadata when it is a serialized WP_Error
|
103 |
|
104 |
### WP Offload S3 Lite 1.0.3 - 2016-03-23 ###
|
105 |
* Bug fix: Don't replace srcset URLs when Rewrite File URLs option disabled
|
120 |
* Improvement: Far future expiration header set by default
|
121 |
* Improvement: Newly created bucket now immediately appears in the bucket list
|
122 |
* Improvement: Cleanup user meta on uninstall
|
123 |
+
* Improvement: WP Retina 2x integration removed
|
124 |
* Bug fix: Year/Month folder structure on S3 not created if the 'Organise my uploads into month and year-based folders' WordPress setting is disabled
|
125 |
* Bug fix: Responsive srcset PHP notices
|
126 |
* Bug fix: Compatibility addon notices displayed to non-admin users
|
assets/css/attachment.css
ADDED
@@ -0,0 +1 @@
|
|
|
1 |
+
#s3-actions.postbox .inside{margin:0;padding:0}#s3-actions.postbox a,#s3-actions.postbox a:hover{text-decoration:none}#s3-actions.postbox .s3-details{padding:6px 0}#s3-actions.postbox .s3-details .misc-pub-section{clear:both;float:left;width:100%;-webkit-box-sizing:border-box;box-sizing:border-box}#s3-actions.postbox .s3-details .misc-pub-section .s3-key{float:left;width:20%}#s3-actions.postbox .s3-details .misc-pub-section .s3-value{font-weight:bold;float:left;width:80%}#s3-actions.postbox .s3-details .not-copied{color:#666666}#s3-actions.postbox .s3-actions{padding:10px;clear:both;border-top:1px solid #ddd;border-bottom:1px solid #ddd;background:#f5f5f5}#s3-actions.postbox .s3-actions .copy-action{text-align:right;float:right;line-height:23px}#s3-actions.postbox .s3-actions .remove-action{line-height:28px;vertical-align:middle;text-align:left;float:left}#s3-actions.postbox .s3-actions .remove-action a.local-warning{color:#a00}#s3-actions.postbox .s3-actions .remove-action a.local-warning:hover{color:#f00}
|
assets/css/media.css
ADDED
@@ -0,0 +1 @@
|
|
|
1 |
+
body.as3cf-pro .attachments-browser .media-toolbar-secondary{max-width:100%}.as3cfpro_remove a.local-warning{color:#a00}.as3cfpro_remove a.local-warning:hover{color:#f00;text-decoration:none;border:none}.media-modal a.local-warning{color:#bc0b0b}.media-modal a.local-warning:hover{color:red}.attachment-info .attachment-s3-details{font-weight:bold;margin-bottom:5px}
|
assets/js/media.js
ADDED
@@ -0,0 +1,160 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
var test = {};
|
2 |
+
|
3 |
+
(function( $, _ ) {
|
4 |
+
|
5 |
+
// Local reference to the WordPress media namespace.
|
6 |
+
var media = wp.media;
|
7 |
+
|
8 |
+
// Local instance of the Attachment Details TwoColumn used in the edit attachment modal view
|
9 |
+
var wpAttachmentDetailsTwoColumn = media.view.Attachment.Details.TwoColumn;
|
10 |
+
|
11 |
+
/**
|
12 |
+
* Add S3 details to attachment.
|
13 |
+
*/
|
14 |
+
media.view.Attachment.Details.TwoColumn = wpAttachmentDetailsTwoColumn.extend( {
|
15 |
+
events: function() {
|
16 |
+
return _.extend( {}, wpAttachmentDetailsTwoColumn.prototype.events, {
|
17 |
+
'click .local-warning': 'confirmS3Removal',
|
18 |
+
'click #as3cfpro-toggle-acl': 'toggleACL'
|
19 |
+
} );
|
20 |
+
},
|
21 |
+
|
22 |
+
render: function() {
|
23 |
+
// Retrieve the S3 details for the attachment
|
24 |
+
// before we render the view
|
25 |
+
this.fetchS3Details( this.model.get( 'id' ) );
|
26 |
+
},
|
27 |
+
|
28 |
+
fetchS3Details: function( id ) {
|
29 |
+
wp.ajax.send( 'as3cf_get_attachment_s3_details', {
|
30 |
+
data: {
|
31 |
+
_nonce: as3cf_media.nonces.get_attachment_s3_details,
|
32 |
+
id: id
|
33 |
+
}
|
34 |
+
} ).done( _.bind( this.renderView, this ) );
|
35 |
+
},
|
36 |
+
|
37 |
+
renderView: function( response ) {
|
38 |
+
// Render parent media.view.Attachment.Details
|
39 |
+
wpAttachmentDetailsTwoColumn.prototype.render.apply( this );
|
40 |
+
|
41 |
+
this.renderActionLinks( response );
|
42 |
+
this.renderS3Details( response );
|
43 |
+
},
|
44 |
+
|
45 |
+
renderActionLinks: function( response ) {
|
46 |
+
var links = ( response && response.links ) || [];
|
47 |
+
var $actionsHtml = this.$el.find( '.actions' );
|
48 |
+
var $s3Actions = $( '<div />', {
|
49 |
+
'class': 's3-actions'
|
50 |
+
} );
|
51 |
+
|
52 |
+
var s3Links = [];
|
53 |
+
_( links ).each( function( link ) {
|
54 |
+
s3Links.push( link );
|
55 |
+
} );
|
56 |
+
|
57 |
+
$s3Actions.append( s3Links.join( ' | ' ) );
|
58 |
+
$actionsHtml.append( $s3Actions );
|
59 |
+
},
|
60 |
+
|
61 |
+
renderS3Details: function( response ) {
|
62 |
+
if ( ! response || ! response.s3object ) {
|
63 |
+
return;
|
64 |
+
}
|
65 |
+
var $detailsHtml = this.$el.find( '.attachment-info .details' );
|
66 |
+
var html = this.generateDetails( response, [ 'bucket', 'key', 'region', 'acl' ] );
|
67 |
+
$detailsHtml.append( html );
|
68 |
+
},
|
69 |
+
|
70 |
+
generateDetails: function( response, keys ) {
|
71 |
+
var html = '';
|
72 |
+
var template = _.template( '<div class="<%= key %>"><strong><%= label %>:</strong> <%= value %></div>' );
|
73 |
+
|
74 |
+
_( keys ).each( function( key ) {
|
75 |
+
if ( response.s3object[ key ] ) {
|
76 |
+
var value = response.s3object[ key ];
|
77 |
+
|
78 |
+
if ( 'acl' === key ) {
|
79 |
+
value = response.s3object[ key ]['name'];
|
80 |
+
|
81 |
+
if ( response.acl_toggle ) {
|
82 |
+
var acl_template = _.template( '<a href="#" id="as3cfpro-toggle-acl" title="<%= title %>" data-currentACL="<%= acl %>"><%= value %></a>' );
|
83 |
+
|
84 |
+
value = acl_template( {
|
85 |
+
title: response.s3object[ key ][ 'title' ],
|
86 |
+
acl: response.s3object[ key ][ 'acl' ],
|
87 |
+
value: value
|
88 |
+
} );
|
89 |
+
}
|
90 |
+
}
|
91 |
+
|
92 |
+
html += template( {
|
93 |
+
key: key,
|
94 |
+
label: as3cf_media.strings[ key ],
|
95 |
+
value: value
|
96 |
+
} );
|
97 |
+
}
|
98 |
+
} );
|
99 |
+
|
100 |
+
return html;
|
101 |
+
},
|
102 |
+
|
103 |
+
confirmS3Removal: function( event ) {
|
104 |
+
if ( ! confirm( as3cfpro_media.strings.local_warning ) ) {
|
105 |
+
event.preventDefault();
|
106 |
+
event.stopImmediatePropagation();
|
107 |
+
return false;
|
108 |
+
}
|
109 |
+
},
|
110 |
+
|
111 |
+
toggleACL: function( event ) {
|
112 |
+
event.preventDefault();
|
113 |
+
|
114 |
+
var toggle = $( '#as3cfpro-toggle-acl' );
|
115 |
+
var currentACL = toggle.attr( 'data-currentACL' );
|
116 |
+
var newACL = as3cfpro_media.settings.private_acl;
|
117 |
+
|
118 |
+
toggle.hide();
|
119 |
+
toggle.after( '<span id="as3cfpro-updating">' + as3cfpro_media.strings.updating_acl + '</span>' );
|
120 |
+
|
121 |
+
if ( currentACL === as3cfpro_media.settings.private_acl ) {
|
122 |
+
newACL = as3cfpro_media.settings.default_acl;
|
123 |
+
}
|
124 |
+
|
125 |
+
wp.ajax.send( 'as3cfpro_update_acl', {
|
126 |
+
data: {
|
127 |
+
_nonce: as3cfpro_media.nonces.update_acl,
|
128 |
+
id: this.model.get( 'id' ),
|
129 |
+
acl: newACL
|
130 |
+
}
|
131 |
+
} )
|
132 |
+
.done( _.bind( this.updateACL, this ) )
|
133 |
+
.fail( _.bind( this.renderACLError, this ) );
|
134 |
+
},
|
135 |
+
|
136 |
+
renderACLError: function() {
|
137 |
+
$( '#as3cfpro-updating' ).remove();
|
138 |
+
$( '#as3cfpro-toggle-acl' ).show();
|
139 |
+
alert( as3cfpro_media.strings.change_acl_error );
|
140 |
+
},
|
141 |
+
|
142 |
+
updateACL: function( response ) {
|
143 |
+
if ( 'undefined' === typeof response.acl_display || 'undefined' === typeof response.title || 'undefined' === typeof response.acl ) {
|
144 |
+
this.renderACLError();
|
145 |
+
|
146 |
+
return;
|
147 |
+
}
|
148 |
+
|
149 |
+
var toggle = $( '#as3cfpro-toggle-acl' );
|
150 |
+
|
151 |
+
$( '#as3cfpro-updating' ).remove();
|
152 |
+
|
153 |
+
toggle.text( response.acl_display );
|
154 |
+
toggle.attr( 'title', response.title );
|
155 |
+
toggle.attr( 'data-currentACL', response.acl );
|
156 |
+
toggle.show();
|
157 |
+
}
|
158 |
+
} );
|
159 |
+
|
160 |
+
})( jQuery, _ );
|
assets/js/media.min.js
ADDED
@@ -0,0 +1 @@
|
|
|
1 |
+
var test={};!function(a,b){var c=wp.media,d=c.view.Attachment.Details.TwoColumn;c.view.Attachment.Details.TwoColumn=d.extend({events:function(){return b.extend({},d.prototype.events,{"click .local-warning":"confirmS3Removal","click #as3cfpro-toggle-acl":"toggleACL"})},render:function(){this.fetchS3Details(this.model.get("id"))},fetchS3Details:function(a){wp.ajax.send("as3cf_get_attachment_s3_details",{data:{_nonce:as3cf_media.nonces.get_attachment_s3_details,id:a}}).done(b.bind(this.renderView,this))},renderView:function(a){d.prototype.render.apply(this),this.renderActionLinks(a),this.renderS3Details(a)},renderActionLinks:function(c){var d=c&&c.links||[],e=this.$el.find(".actions"),f=a("<div />",{"class":"s3-actions"}),g=[];b(d).each(function(a){g.push(a)}),f.append(g.join(" | ")),e.append(f)},renderS3Details:function(a){if(a&&a.s3object){var b=this.$el.find(".attachment-info .details"),c=this.generateDetails(a,["bucket","key","region","acl"]);b.append(c)}},generateDetails:function(a,c){var d="",e=b.template('<div class="<%= key %>"><strong><%= label %>:</strong> <%= value %></div>');return b(c).each(function(c){if(a.s3object[c]){var f=a.s3object[c];if("acl"===c&&(f=a.s3object[c].name,a.acl_toggle)){var g=b.template('<a href="#" id="as3cfpro-toggle-acl" title="<%= title %>" data-currentACL="<%= acl %>"><%= value %></a>');f=g({title:a.s3object[c].title,acl:a.s3object[c].acl,value:f})}d+=e({key:c,label:as3cf_media.strings[c],value:f})}}),d},confirmS3Removal:function(a){return confirm(as3cfpro_media.strings.local_warning)?void 0:(a.preventDefault(),a.stopImmediatePropagation(),!1)},toggleACL:function(c){c.preventDefault();var d=a("#as3cfpro-toggle-acl"),e=d.attr("data-currentACL"),f=as3cfpro_media.settings.private_acl;d.hide(),d.after('<span id="as3cfpro-updating">'+as3cfpro_media.strings.updating_acl+"</span>"),e===as3cfpro_media.settings.private_acl&&(f=as3cfpro_media.settings.default_acl),wp.ajax.send("as3cfpro_update_acl",{data:{_nonce:as3cfpro_media.nonces.update_acl,id:this.model.get("id"),acl:f}}).done(b.bind(this.updateACL,this)).fail(b.bind(this.renderACLError,this))},renderACLError:function(){a("#as3cfpro-updating").remove(),a("#as3cfpro-toggle-acl").show(),alert(as3cfpro_media.strings.change_acl_error)},updateACL:function(b){if("undefined"==typeof b.acl_display||"undefined"==typeof b.title||"undefined"==typeof b.acl)return void this.renderACLError();var c=a("#as3cfpro-toggle-acl");a("#as3cfpro-updating").remove(),c.text(b.acl_display),c.attr("title",b.title),c.attr("data-currentACL",b.acl),c.show()}})}(jQuery,_);
|
assets/js/modal.min.js
CHANGED
@@ -1 +1 @@
|
|
1 |
-
var as3cfModal=function(a){function b(a){return a.replace(/[^a-z]/g,"")}var c={prefix:"as3cf",loading:!1},d={};return c.exists=function(c){var e=b(c);return void 0!==d[e]
|
1 |
+
var as3cfModal=function(a){function b(a){return a.replace(/[^a-z]/g,"")}var c={prefix:"as3cf",loading:!1},d={};return c.exists=function(c){var e=b(c);return void 0!==d[e]?!0:!!a(c).length},c.open=function(c,e,f){var g=b(c);a("body").append('<div id="as3cf-overlay"></div>');var h=a("#as3cf-overlay");h.append('<div id="as3cf-modal"><span class="close-as3cf-modal">×</span></div>');var i=a("#as3cf-modal");if(void 0===d[g]){var j=a(c);d[g]=j.clone(!0).css("display","block"),j.remove()}i.data("as3cf-modal-target",c).append(d[g]),void 0!==f&&i.addClass(f),"function"==typeof e&&e(c),a("body").addClass("as3cf-modal-open"),h.fadeIn(150),i.fadeIn(150),a("body").trigger("as3cf-modal-open",[c])},c.close=function(b){if(!c.loading){var d=a("#as3cf-modal").data("as3cf-modal-target");a("#as3cf-overlay").fadeOut(150,function(){"function"==typeof b&&b(d),a("body").removeClass("as3cf-modal-open"),a(this).remove()}),a("body").trigger("as3cf-modal-close",[d])}},c.setLoadingState=function(a){c.loading=a},a(document).ready(function(){a("body").on("click","[data-as3cf-modal]",function(b){b.preventDefault(),c.open(a(this).data("as3cf-modal")+"."+c.prefix)}),a("body").on("click","#as3cf-overlay, .close-as3cf-modal",function(a){return a.preventDefault(),a.target!==this?!1:void c.close()})}),c}(jQuery);
|
assets/js/script.min.js
CHANGED
@@ -1 +1 @@
|
|
1 |
-
!function(a,b){function c(b){return a("#"+b+" .as3cf-main-settings form").find("input:not(.no-compare)").serialize()}function d(a){var b=k.find("#"+a),c=b.find("input[type=checkbox]");b.toggleClass("on").find("span").toggleClass("checked");var d=b.find("span.on").hasClass("checked");c.attr("checked",d).trigger("change")}function e(b){var c=b.next(".as3cf-validation-error"),d=a("#"+k.attr("id")+' form button[type="submit"]'),e=/[^a-zA-Z0-9\.\-]/;e.test(b.val())?(c.show(),d.attr("disabled",!0)):(c.hide(),d.attr("disabled",!1))}function f(){var c=a("#"+b.prefix+"-bucket").val(),d=k.find('input[name="object-prefix"]'),e=d.val();""!==e&&(e="&prefix="+encodeURIComponent(e));var f=as3cf.aws_bucket_link+c+e;a("#"+b.prefix+"-view-bucket").attr("href",f)}function g(){a(".as3cf-url-preview").html("Generating...");var b={_nonce:as3cf.nonces.get_url_preview};a.each(a("#tab-"+as3cf.tabs.defaultTab+" .as3cf-main-settings form").serializeArray(),function(c,d){var e=d.name,f=d.value;e=e.replace("[]",""),b[e]=void 0===b[e]?f:a.isArray(b[e])?b[e].concat(f):[b[e],f]}),b.action="as3cf-get-url-preview",a.ajax({url:ajaxurl,type:"POST",dataType:"JSON",data:b,error:function(a,b,c){alert(as3cf.strings.get_url_preview_error+c)},success:function(b,c,d){"undefined"!=typeof b.success?a(".as3cf-url-preview").html(b.url):alert(as3cf.strings.get_url_preview_error+b.error)}})}function h(a){as3cf.buckets.bucketSelectLock=!1}function i(){a("#remove-local-file").is(":checked")&&a("#serve-from-s3").is(":not(:checked)")?a("#as3cf-lost-files-notice").show():a("#as3cf-lost-files-notice").hide()}function j(){a("#remove-local-file").is(":checked")?a("#as3cf-remove-local-notice").show():a("#as3cf-remove-local-notice").hide()}var k,l={},m=/[^a-z0-9.-]/,n=!1,o=a(".as3cf-tab");as3cf.tabs={defaultTab:"media",toggle:function(c,d){c=as3cf.tabs.sanitizeHash(c),o.hide(),k=a("#tab-"+c),k.show(),a(".nav-tab").removeClass("nav-tab-active"),a('a.nav-tab[data-tab="'+c+'"]').addClass("nav-tab-active"),a(".aws-main").attr("data-tab",c),k.attr("data-prefix")&&(b.prefix=k.attr("data-prefix")),d||a(".as3cf-updated").removeClass("show"),"support"===c&&as3cf.tabs.getDiagnosticInfo()},getDiagnosticInfo:function(){var b=a(".debug-log-textarea");b.html(as3cf.strings.get_diagnostic_info);var c={action:"as3cf-get-diagnostic-info",_nonce:as3cf.nonces.get_diagnostic_info};a.ajax({url:ajaxurl,type:"POST",dataType:"JSON",data:c,error:function(a,c,d){b.html(d)},success:function(a,c,d){"undefined"!=typeof a.success?b.html(a.diagnostic_info):(b.html(as3cf.strings.get_diagnostic_info_error),b.append(a.error))}})},sanitizeHash:function(b){var c=a("#tab-"+b);return 0===c.length&&(b=as3cf.tabs.defaultTab),b}},as3cf.buckets={validLength:3,bucketSelectLock:!1,loadList:function(c){"undefined"==typeof c&&(c=!1);var d=a(".as3cf-bucket-container."+b.prefix+" .as3cf-bucket-list"),e=a("#"+b.prefix+"-bucket").val();if(!1===c&&d.find("li").length>1)return a(".as3cf-bucket-list a").removeClass("selected"),a('.as3cf-bucket-list a[data-bucket="'+e+'"]').addClass("selected"),void this.scrollToSelected();d.html('<li class="loading">'+d.attr("data-working")+"</li>");var f={action:b.prefix+"-get-buckets",_nonce:window[b.prefix.replace(/-/g,"_")].nonces.get_buckets},g=this;a.ajax({url:ajaxurl,type:"POST",dataType:"JSON",data:f,error:function(a,b,c){d.html(""),g.showError(as3cf.strings.get_buckets_error,c,"as3cf-bucket-select")},success:function(b,c,f){d.html(""),"undefined"!=typeof b.success?(a(".as3cf-bucket-error").hide(),a(b.buckets).each(function(a,b){var c=b.Name===e?"selected":"";d.append('<li><a class="'+c+'" href="#" data-bucket="'+b.Name+'"><span class="bucket"><span class="dashicons dashicons-portfolio"></span> '+b.Name+'</span><span class="spinner"></span></span></a></li>')}),g.scrollToSelected()):g.showError(as3cf.strings.get_buckets_error,b.error,"as3cf-bucket-select")}})},scrollToSelected:function(){if(a(".as3cf-bucket-list a.selected").length){var b=a("ul.as3cf-bucket-list li").first().position().top+150;a(".as3cf-bucket-list").animate({scrollTop:a("ul.as3cf-bucket-list li a.selected").position().top-b})}},resetModal:function(){var c=a(".as3cf-bucket-container."+b.prefix);!1===k.hasClass("as3cf-has-bucket")||"manual"===a("#"+b.prefix+"-bucket-select").val()?(c.find(".as3cf-bucket-manual").show().siblings().hide(),c.find(".bucket-actions.manual").show().siblings(".bucket-actions").hide()):(c.find(".as3cf-bucket-select").show().siblings().hide(),c.find(".bucket-actions.select").show().siblings(".bucket-actions").hide(),this.loadList(n),n=!1),c.find(".as3cf-bucket-error").hide();var d=a("#"+b.prefix+"-bucket").val();c.find(".as3cf-bucket-manual .as3cf-bucket-name").val(d),this.bucketSelectLock=!1},saveManual:function(){var c=a(".as3cf-bucket-container."+b.prefix+" .as3cf-manual-save-bucket-form"),d=c.find(".as3cf-bucket-name"),e=c.find("button[type=submit]"),f=d.val(),g=e.first().text();if(f===a("#"+b.prefix+"-active-bucket").text())return a(".as3cf-bucket-error").hide(),k.addClass("as3cf-has-bucket"),void b.close();a(".as3cf-bucket-error").hide(),e.text(e.attr("data-working")),e.prop("disabled",!0);var h={action:b.prefix+"-manual-save-bucket",bucket_name:f,_nonce:window[b.prefix.replace(/-/g,"_")].nonces.manual_bucket},i=this;a.ajax({url:ajaxurl,type:"POST",dataType:"JSON",data:h,error:function(a,b,c){e.text(g),i.showError(as3cf.strings.save_bucket_error,c,"as3cf-bucket-manual")},success:function(c,d,h){e.text(g),e.prop("disabled",!1),"undefined"!=typeof c.success?(i.set(f,c.region,c.can_write),a("#"+b.prefix+"-bucket-select").val("manual"),a(".as3cf-bucket-list a").removeClass("selected").filter('[data-bucket="'+f+'"]').addClass("selected"),n=!0):i.showError(as3cf.strings.save_bucket_error,c.error,"as3cf-bucket-manual")}})},saveSelected:function(c){var d=a(".as3cf-bucket-list");if(!this.bucketSelectLock){if(this.bucketSelectLock=!0,c.hasClass("selected"))return k.addClass("as3cf-has-bucket"),void b.close();var e=a(".as3cf-bucket-list a.selected").attr("data-bucket");a(".as3cf-bucket-list a").removeClass("selected"),c.addClass("selected"),d.addClass("saving"),c.find(".spinner").show().css("visibility","visible");var f=c.attr("data-bucket"),g={action:b.prefix+"-save-bucket",bucket_name:f,_nonce:window[b.prefix.replace(/-/g,"_")].nonces.save_bucket},h=this;a.ajax({url:ajaxurl,type:"POST",dataType:"JSON",data:g,error:function(b,c,f){d.removeClass("saving"),h.showError(as3cf.strings.save_bucket_error,f,"as3cf-bucket-select"),a(".as3cf-bucket-list a").removeClass("selected"),a('.as3cf-bucket-list a[data-bucket="'+e+'"]').addClass("selected")},success:function(g,i,j){c.find(".spinner").hide().css("visibility","hidden"),d.removeClass("saving"),"undefined"!=typeof g.success?(h.set(f,g.region,g.can_write),a("#"+b.prefix+"-bucket-select").val("")):(h.showError(as3cf.strings.save_bucket_error,g.error,"as3cf-bucket-select"),a(".as3cf-bucket-list a").removeClass("selected"),a('.as3cf-bucket-list a[data-bucket="'+e+'"]').addClass("selected"))}})}},disabledButtons:function(){if(0!==a(".as3cf-bucket-container."+b.prefix+" .as3cf-create-bucket-form").length){var c=a(".as3cf-bucket-container."+b.prefix+" .as3cf-create-bucket-form"),d=a(".as3cf-bucket-container."+b.prefix+" .as3cf-manual-save-bucket-form");c.find(".as3cf-bucket-name").val().length<3?c.find("button[type=submit]").attr("disabled",!0):c.find("button[type=submit]").attr("disabled",!1),d.find(".as3cf-bucket-name").val().length<3?d.find("button[type=submit]").attr("disabled",!0):d.find("button[type=submit]").attr("disabled",!1)}},showError:function(b,c,d){var e=a(".as3cf-bucket-container").children(":visible"),f=e.find(".as3cf-bucket-error");d="undefined"==typeof d?null:d,d&&!e.hasClass(d)||(f.find("span.title").html(b+" —"),f.find("span.message").html(c),f.show(),this.bucketSelectLock=!1)},set:function(e,i,j){var m=a(".as3cf-bucket-container."+b.prefix+" .as3cf-manual-save-bucket-form"),n=a("#"+b.prefix+"-active-bucket");if("as3cf"===b.prefix&&0===n.text().trim().length){d("copy-to-s3-wrap"),d("serve-from-s3-wrap");var o=k.attr("id");l[o]=c(o)}a(".as3cf-error.fatal").hide(),n.text(e),m.find(".as3cf-bucket-name").val(e),a("#"+b.prefix+"-bucket").val(e),a("#"+b.prefix+"-region").val(i),a(".updated").not(".as3cf-notice").show(),k.addClass("as3cf-has-bucket"),k.find(".as3cf-can-write-error").toggle(!j),k.find(".as3cf-bucket-error").hide(),"as3cf"===b.prefix&&g(),f(),b.close(h)},create:function(){var c=a(".as3cf-bucket-container."+b.prefix+" .as3cf-create-bucket-form"),d=c.find(".as3cf-bucket-name"),e=c.find(".bucket-create-region"),f=c.find("button[type=submit]"),g=d.val(),h=f.text();a(".as3cf-bucket-error").hide(),f.text(f.attr("data-working")),f.prop("disabled",!0);var i={action:b.prefix+"-create-bucket",bucket_name:g,_nonce:window[b.prefix.replace(/-/g,"_")].nonces.create_bucket};e.val()&&(i.region=e.val());var j=this;a.ajax({url:ajaxurl,type:"POST",dataType:"JSON",data:i,error:function(a,b,c){f.text(h),j.showError(as3cf.strings.create_bucket_error,c,"as3cf-bucket-create")},success:function(b,c,e){f.text(h),f.prop("disabled",!1),"undefined"!=typeof b.success?(j.set(g,b.region,b.can_write),a(".as3cf-bucket-select-region").hide(),a(".as3cf-bucket-select-region").removeAttr("selected"),d.val(""),f.attr("disabled",!0),n=!0):j.showError(as3cf.strings.create_bucket_error,b.error,"as3cf-bucket-create")}})},isValidName:function(a){return!(a.length<3||a.length>63)&&!0!==m.test(a)},updateNameNotice:function(b){var c=null;!0===m.test(b)?c=as3cf.strings.create_bucket_invalid_chars:b.length<3?c=as3cf.strings.create_bucket_name_short:b.length>63&&(c=as3cf.strings.create_bucket_name_long),c&&b.length>0?a(".as3cf-invalid-bucket-name").html(c):a(".as3cf-invalid-bucket-name").html("")}},a(document).ready(function(){var h=a(".wrap.aws-main .nav-tab-wrapper");if(a(".aws-compatibility-notice, div.updated, div.error, div.notice").not(".below-h2, .inline").insertAfter(h),window.location.hash){var m=window.location.hash.substring(1);as3cf.tabs.toggle(m,!0)}else k=a("#tab-"+as3cf.tabs.defaultTab),a(".aws-main").attr("data-tab",as3cf.tabs.defaultTab);a(".aws-main").on("click",".nav-tab",function(b){if(b.preventDefault(),!a(this).hasClass("nav-tab-active")){var c=a(this).attr("data-tab");as3cf.tabs.toggle(c),"media"===c?(window.location.hash="","function"==typeof window.history.replaceState&&"#"===window.location.href.slice(-1)&&history.replaceState({},"",window.location.href.slice(0,-1))):window.location.hash=c}}),o.length&&o.each(function(a,b){l[b.id]=c(b.id)}),a(window).on("beforeunload.as3cf-settings",function(){if(!a.isEmptyObject(l)){var b=k.attr("id");return c(b)!==l[b]?as3cf.strings.save_alert:void 0}}),a(document).on("submit",".as3cf-main-settings form",function(b){a(window).off("beforeunload.as3cf-settings")}),a(".as3cf-switch").on("click",function(b){a(this).hasClass("disabled")||d(a(this).attr("id"))}),o.on("change",".sub-toggle",function(b){var c=a(this).attr("id");a(".as3cf-setting."+c).toggleClass("hide")}),a(".as3cf-domain").on("change",'input[type="radio"]',function(b){var c=a(this).closest('input:radio[name="domain"]:checked'),d=c.val(),e=a(this).parents(".as3cf-domain").find(".as3cf-setting.cloudfront"),f="cloudfront"===d;e.toggleClass("hide",!f)}),a(".url-preview").on("change","input",function(a){g()}),i(),a("#serve-from-s3,#remove-local-file").on("change",function(a){i()}),j(),a("#remove-local-file").on("change",function(a){j()}),a('.as3cf-setting input[type="text"]').keypress(function(a){if(13===a.which)return a.preventDefault(),!1}),a('input[name="cloudfront"]').on("keyup",function(b){e(a(this))}),a('input[name="domain"]').on("change",function(b){var c=a(this),d=a("#"+k.attr("id")+' form button[type="submit"]');"cloudfront"!==c.val()?d.attr("disabled",!1):e(c.next(".as3cf-setting").find('input[name="cloudfront"]'))}),a('input[name="object-prefix"]').on("change",function(a){f()}),a("#tab-media > .as3cf-bucket-error").detach().insertAfter(".as3cf-bucket-container h3"),a("body").on("click",".bucket-action-manual",function(c){c.preventDefault(),a(".as3cf-bucket-container."+b.prefix+" .as3cf-bucket-manual").show().siblings().hide()}),a("body").on("click",".bucket-action-browse",function(c){c.preventDefault(),a(".as3cf-bucket-container."+b.prefix+" .as3cf-bucket-select").show().siblings().hide(),as3cf.buckets.loadList(n),n=!1}),a("body").on("click",".bucket-action-create",function(c){c.preventDefault(),a(".as3cf-bucket-name").val(""),a(".as3cf-invalid-bucket-name").html(""),a(".as3cf-bucket-container."+b.prefix+" .as3cf-bucket-create").show().siblings().hide()}),a("body").on("click",".bucket-action-cancel",function(a){a.preventDefault(),as3cf.buckets.resetModal()}),a("body").on("click",".bucket-action-save",function(a){a.preventDefault(),as3cf.buckets.saveManual()}),a("body").on("click",'.as3cf-create-bucket-form button[type="submit"]',function(a){a.preventDefault(),as3cf.buckets.create()}),a("body").on("click",".bucket-action-refresh",function(a){a.preventDefault(),as3cf.buckets.loadList(!0)}),a("body").on("click",".as3cf-bucket-list a",function(b){b.preventDefault(),as3cf.buckets.saveSelected(a(this))}),a(".as3cf-bucket-container").on("click","a.js-link",function(b){return b.preventDefault(),window.open(a(this).attr("href")),!1}),a("body").on("as3cf-modal-open",function(c,d){if(".as3cf-bucket-container."+b.prefix===d){as3cf.buckets.resetModal();var e=a(".as3cf-bucket-manual h3").data("modal-title");a(".as3cf-bucket-manual h3").text(e),as3cf.buckets.disabledButtons()}}),as3cf.buckets.disabledButtons(),a("body").on("input keyup",".as3cf-create-bucket-form .as3cf-bucket-name",function(c){var d=a(this).val(),e=a(".as3cf-bucket-container."+b.prefix+" .as3cf-create-bucket-form");as3cf.buckets.isValidName(d)?e.find("button[type=submit]").removeAttr("disabled"):e.find("button[type=submit]").attr("disabled",!0),as3cf.buckets.updateNameNotice(d)}),a("body").on("input keyup",".as3cf-manual-save-bucket-form .as3cf-bucket-name",function(c){var d=a(".as3cf-bucket-container."+b.prefix+" .as3cf-manual-save-bucket-form");d.find(".as3cf-bucket-name").val().length<as3cf.buckets.validLength?d.find("button[type=submit]").attr("disabled",!0):d.find("button[type=submit]").removeAttr("disabled")})})}(jQuery,as3cfModal);
|
1 |
+
!function(a,b){function c(b){return a("#"+b+" .as3cf-main-settings form").find("input:not(.no-compare)").serialize()}function d(a){var b=k.find("#"+a),c=b.find("input[type=checkbox]");b.toggleClass("on").find("span").toggleClass("checked");var d=b.find("span.on").hasClass("checked");c.attr("checked",d).trigger("change")}function e(b){var c=b.next(".as3cf-validation-error"),d=a("#"+k.attr("id")+' form button[type="submit"]'),e=/[^a-zA-Z0-9\.\-]/;e.test(b.val())?(c.show(),d.attr("disabled",!0)):(c.hide(),d.attr("disabled",!1))}function f(){var c=a("#"+b.prefix+"-bucket").val(),d=k.find('input[name="object-prefix"]'),e=d.val();""!==e&&(e="&prefix="+encodeURIComponent(e));var f=as3cf.aws_bucket_link+c+e;a("#"+b.prefix+"-view-bucket").attr("href",f)}function g(){a(".as3cf-url-preview").html("Generating...");var b={_nonce:as3cf.nonces.get_url_preview};a.each(a("#tab-"+as3cf.tabs.defaultTab+" .as3cf-main-settings form").serializeArray(),function(c,d){var e=d.name,f=d.value;e=e.replace("[]",""),b[e]=void 0===b[e]?f:a.isArray(b[e])?b[e].concat(f):[b[e],f]}),b.action="as3cf-get-url-preview",a.ajax({url:ajaxurl,type:"POST",dataType:"JSON",data:b,error:function(a,b,c){alert(as3cf.strings.get_url_preview_error+c)},success:function(b,c,d){"undefined"!=typeof b.success?a(".as3cf-url-preview").html(b.url):alert(as3cf.strings.get_url_preview_error+b.error)}})}function h(a){as3cf.buckets.bucketSelectLock=!1}function i(){a("#remove-local-file").is(":checked")&&a("#serve-from-s3").is(":not(:checked)")?a("#as3cf-lost-files-notice").show():a("#as3cf-lost-files-notice").hide()}function j(){a("#remove-local-file").is(":checked")?a("#as3cf-remove-local-notice").show():a("#as3cf-remove-local-notice").hide()}var k,l={},m=/[^a-z0-9.-]/,n=!1,o=a(".as3cf-tab");as3cf.tabs={defaultTab:"media",toggle:function(c,d){c=as3cf.tabs.sanitizeHash(c),o.hide(),k=a("#tab-"+c),k.show(),a(".nav-tab").removeClass("nav-tab-active"),a('a.nav-tab[data-tab="'+c+'"]').addClass("nav-tab-active"),a(".aws-main").attr("data-tab",c),k.attr("data-prefix")&&(b.prefix=k.attr("data-prefix")),d||a(".as3cf-updated").removeClass("show"),"support"===c&&as3cf.tabs.getDiagnosticInfo()},getDiagnosticInfo:function(){var b=a(".debug-log-textarea");b.html(as3cf.strings.get_diagnostic_info);var c={action:"as3cf-get-diagnostic-info",_nonce:as3cf.nonces.get_diagnostic_info};a.ajax({url:ajaxurl,type:"POST",dataType:"JSON",data:c,error:function(a,c,d){b.html(d)},success:function(a,c,d){"undefined"!=typeof a.success?b.html(a.diagnostic_info):(b.html(as3cf.strings.get_diagnostic_info_error),b.append(a.error))}})},sanitizeHash:function(b){var c=a("#tab-"+b);return 0===c.length&&(b=as3cf.tabs.defaultTab),b}},as3cf.buckets={validLength:3,bucketSelectLock:!1,loadList:function(c){"undefined"==typeof c&&(c=!1);var d=a(".as3cf-bucket-container."+b.prefix+" .as3cf-bucket-list"),e=a("#"+b.prefix+"-bucket").val();if(!1===c&&d.find("li").length>1)return a(".as3cf-bucket-list a").removeClass("selected"),a('.as3cf-bucket-list a[data-bucket="'+e+'"]').addClass("selected"),void this.scrollToSelected();d.html('<li class="loading">'+d.attr("data-working")+"</li>");var f={action:b.prefix+"-get-buckets",_nonce:window[b.prefix.replace(/-/g,"_")].nonces.get_buckets},g=this;a.ajax({url:ajaxurl,type:"POST",dataType:"JSON",data:f,error:function(a,b,c){d.html(""),g.showError(as3cf.strings.get_buckets_error,c,"as3cf-bucket-select")},success:function(b,c,f){d.html(""),"undefined"!=typeof b.success?(a(".as3cf-bucket-error").hide(),a(b.buckets).each(function(a,b){var c=b.Name===e?"selected":"";d.append('<li><a class="'+c+'" href="#" data-bucket="'+b.Name+'"><span class="bucket"><span class="dashicons dashicons-portfolio"></span> '+b.Name+'</span><span class="spinner"></span></span></a></li>')}),g.scrollToSelected()):g.showError(as3cf.strings.get_buckets_error,b.error,"as3cf-bucket-select")}})},scrollToSelected:function(){if(a(".as3cf-bucket-list a.selected").length){var b=a("ul.as3cf-bucket-list li").first().position().top+150;a(".as3cf-bucket-list").animate({scrollTop:a("ul.as3cf-bucket-list li a.selected").position().top-b})}},resetModal:function(){var c=a(".as3cf-bucket-container."+b.prefix);!1===k.hasClass("as3cf-has-bucket")||"manual"===a("#"+b.prefix+"-bucket-select").val()?(c.find(".as3cf-bucket-manual").show().siblings().hide(),c.find(".bucket-actions.manual").show().siblings(".bucket-actions").hide()):(c.find(".as3cf-bucket-select").show().siblings().hide(),c.find(".bucket-actions.select").show().siblings(".bucket-actions").hide(),this.loadList(n),n=!1),c.find(".as3cf-bucket-error").hide();var d=a("#"+b.prefix+"-bucket").val();c.find(".as3cf-bucket-manual .as3cf-bucket-name").val(d),this.bucketSelectLock=!1},saveManual:function(){var c=a(".as3cf-bucket-container."+b.prefix+" .as3cf-manual-save-bucket-form"),d=c.find(".as3cf-bucket-name"),e=c.find("button[type=submit]"),f=d.val(),g=e.first().text();if(f===a("#"+b.prefix+"-active-bucket").text())return a(".as3cf-bucket-error").hide(),k.addClass("as3cf-has-bucket"),void b.close();a(".as3cf-bucket-error").hide(),e.text(e.attr("data-working")),e.prop("disabled",!0);var h={action:b.prefix+"-manual-save-bucket",bucket_name:f,_nonce:window[b.prefix.replace(/-/g,"_")].nonces.manual_bucket},i=this;a.ajax({url:ajaxurl,type:"POST",dataType:"JSON",data:h,error:function(a,b,c){e.text(g),i.showError(as3cf.strings.save_bucket_error,c,"as3cf-bucket-manual")},success:function(c,d,h){e.text(g),e.prop("disabled",!1),"undefined"!=typeof c.success?(i.set(f,c.region,c.can_write),a("#"+b.prefix+"-bucket-select").val("manual"),a(".as3cf-bucket-list a").removeClass("selected").filter('[data-bucket="'+f+'"]').addClass("selected"),n=!0):i.showError(as3cf.strings.save_bucket_error,c.error,"as3cf-bucket-manual")}})},saveSelected:function(c){var d=a(".as3cf-bucket-list");if(!this.bucketSelectLock){if(this.bucketSelectLock=!0,c.hasClass("selected"))return k.addClass("as3cf-has-bucket"),void b.close();var e=a(".as3cf-bucket-list a.selected").attr("data-bucket");a(".as3cf-bucket-list a").removeClass("selected"),c.addClass("selected"),d.addClass("saving"),c.find(".spinner").show().css("visibility","visible");var f=c.attr("data-bucket"),g={action:b.prefix+"-save-bucket",bucket_name:f,_nonce:window[b.prefix.replace(/-/g,"_")].nonces.save_bucket},h=this;a.ajax({url:ajaxurl,type:"POST",dataType:"JSON",data:g,error:function(b,c,f){d.removeClass("saving"),h.showError(as3cf.strings.save_bucket_error,f,"as3cf-bucket-select"),a(".as3cf-bucket-list a").removeClass("selected"),a('.as3cf-bucket-list a[data-bucket="'+e+'"]').addClass("selected")},success:function(g,i,j){c.find(".spinner").hide().css("visibility","hidden"),d.removeClass("saving"),"undefined"!=typeof g.success?(h.set(f,g.region,g.can_write),a("#"+b.prefix+"-bucket-select").val("")):(h.showError(as3cf.strings.save_bucket_error,g.error,"as3cf-bucket-select"),a(".as3cf-bucket-list a").removeClass("selected"),a('.as3cf-bucket-list a[data-bucket="'+e+'"]').addClass("selected"))}})}},disabledButtons:function(){if(0!==a(".as3cf-bucket-container."+b.prefix+" .as3cf-create-bucket-form").length){var c=a(".as3cf-bucket-container."+b.prefix+" .as3cf-create-bucket-form"),d=a(".as3cf-bucket-container."+b.prefix+" .as3cf-manual-save-bucket-form");c.find(".as3cf-bucket-name").val().length<3?c.find("button[type=submit]").attr("disabled",!0):c.find("button[type=submit]").attr("disabled",!1),d.find(".as3cf-bucket-name").val().length<3?d.find("button[type=submit]").attr("disabled",!0):d.find("button[type=submit]").attr("disabled",!1)}},showError:function(b,c,d){var e=a(".as3cf-bucket-container").children(":visible"),f=e.find(".as3cf-bucket-error");d="undefined"==typeof d?null:d,d&&!e.hasClass(d)||(f.find("span.title").html(b+" —"),f.find("span.message").html(c),f.show(),this.bucketSelectLock=!1)},set:function(e,i,j){var m=a(".as3cf-bucket-container."+b.prefix+" .as3cf-manual-save-bucket-form"),n=a("#"+b.prefix+"-active-bucket");if("as3cf"===b.prefix&&0===n.text().trim().length){d("copy-to-s3-wrap"),d("serve-from-s3-wrap");var o=k.attr("id");l[o]=c(o)}a(".as3cf-error.fatal").hide(),n.text(e),m.find(".as3cf-bucket-name").val(e),a("#"+b.prefix+"-bucket").val(e),a("#"+b.prefix+"-region").val(i),a(".updated").not(".as3cf-notice").show(),k.addClass("as3cf-has-bucket"),k.find(".as3cf-can-write-error").toggle(!j),k.find(".as3cf-bucket-error").hide(),"as3cf"===b.prefix&&g(),f(),b.close(h)},create:function(){var c=a(".as3cf-bucket-container."+b.prefix+" .as3cf-create-bucket-form"),d=c.find(".as3cf-bucket-name"),e=c.find(".bucket-create-region"),f=c.find("button[type=submit]"),g=d.val(),h=f.text();a(".as3cf-bucket-error").hide(),f.text(f.attr("data-working")),f.prop("disabled",!0);var i={action:b.prefix+"-create-bucket",bucket_name:g,_nonce:window[b.prefix.replace(/-/g,"_")].nonces.create_bucket};e.val()&&(i.region=e.val());var j=this;a.ajax({url:ajaxurl,type:"POST",dataType:"JSON",data:i,error:function(a,b,c){f.text(h),j.showError(as3cf.strings.create_bucket_error,c,"as3cf-bucket-create")},success:function(b,c,e){f.text(h),f.prop("disabled",!1),"undefined"!=typeof b.success?(j.set(g,b.region,b.can_write),a(".as3cf-bucket-select-region").hide(),a(".as3cf-bucket-select-region").removeAttr("selected"),d.val(""),f.attr("disabled",!0),n=!0):j.showError(as3cf.strings.create_bucket_error,b.error,"as3cf-bucket-create")}})},isValidName:function(a){return a.length<3||a.length>63?!1:!0!==m.test(a)},updateNameNotice:function(b){var c=null;!0===m.test(b)?c=as3cf.strings.create_bucket_invalid_chars:b.length<3?c=as3cf.strings.create_bucket_name_short:b.length>63&&(c=as3cf.strings.create_bucket_name_long),c&&b.length>0?a(".as3cf-invalid-bucket-name").html(c):a(".as3cf-invalid-bucket-name").html("")}},a(document).ready(function(){var h=a(".wrap.aws-main .nav-tab-wrapper");if(a(".aws-compatibility-notice, div.updated, div.error, div.notice").not(".below-h2, .inline").insertAfter(h),window.location.hash){var m=window.location.hash.substring(1);as3cf.tabs.toggle(m,!0)}else k=a("#tab-"+as3cf.tabs.defaultTab),a(".aws-main").attr("data-tab",as3cf.tabs.defaultTab);a(".aws-main").on("click",".nav-tab",function(b){if(b.preventDefault(),!a(this).hasClass("nav-tab-active")){var c=a(this).attr("data-tab");as3cf.tabs.toggle(c),"media"===c?(window.location.hash="","function"==typeof window.history.replaceState&&"#"===window.location.href.slice(-1)&&history.replaceState({},"",window.location.href.slice(0,-1))):window.location.hash=c}}),o.length&&o.each(function(a,b){l[b.id]=c(b.id)}),a(window).on("beforeunload.as3cf-settings",function(){if(!a.isEmptyObject(l)){var b=k.attr("id");return c(b)!==l[b]?as3cf.strings.save_alert:void 0}}),a(document).on("submit",".as3cf-main-settings form",function(b){a(window).off("beforeunload.as3cf-settings")}),a(".as3cf-switch").on("click",function(b){a(this).hasClass("disabled")||d(a(this).attr("id"))}),o.on("change",".sub-toggle",function(b){var c=a(this).attr("id");a(".as3cf-setting."+c).toggleClass("hide")}),a(".as3cf-domain").on("change",'input[type="radio"]',function(b){var c=a(this).closest('input:radio[name="domain"]:checked'),d=c.val(),e=a(this).parents(".as3cf-domain").find(".as3cf-setting.cloudfront"),f="cloudfront"===d;e.toggleClass("hide",!f)}),a(".url-preview").on("change","input",function(a){g()}),i(),a("#serve-from-s3,#remove-local-file").on("change",function(a){i()}),j(),a("#remove-local-file").on("change",function(a){j()}),a('.as3cf-setting input[type="text"]').keypress(function(a){return 13===a.which?(a.preventDefault(),!1):void 0}),a('input[name="cloudfront"]').on("keyup",function(b){e(a(this))}),a('input[name="domain"]').on("change",function(b){var c=a(this),d=a("#"+k.attr("id")+' form button[type="submit"]');"cloudfront"!==c.val()?d.attr("disabled",!1):e(c.next(".as3cf-setting").find('input[name="cloudfront"]'))}),a('input[name="object-prefix"]').on("change",function(a){f()}),a("#tab-media > .as3cf-bucket-error").detach().insertAfter(".as3cf-bucket-container h3"),a("body").on("click",".bucket-action-manual",function(c){c.preventDefault(),a(".as3cf-bucket-container."+b.prefix+" .as3cf-bucket-manual").show().siblings().hide()}),a("body").on("click",".bucket-action-browse",function(c){c.preventDefault(),a(".as3cf-bucket-container."+b.prefix+" .as3cf-bucket-select").show().siblings().hide(),as3cf.buckets.loadList(n),n=!1}),a("body").on("click",".bucket-action-create",function(c){c.preventDefault(),a(".as3cf-bucket-name").val(""),a(".as3cf-invalid-bucket-name").html(""),a(".as3cf-bucket-container."+b.prefix+" .as3cf-bucket-create").show().siblings().hide()}),a("body").on("click",".bucket-action-cancel",function(a){a.preventDefault(),as3cf.buckets.resetModal()}),a("body").on("click",".bucket-action-save",function(a){a.preventDefault(),as3cf.buckets.saveManual()}),a("body").on("click",'.as3cf-create-bucket-form button[type="submit"]',function(a){a.preventDefault(),as3cf.buckets.create()}),a("body").on("click",".bucket-action-refresh",function(a){a.preventDefault(),as3cf.buckets.loadList(!0)}),a("body").on("click",".as3cf-bucket-list a",function(b){b.preventDefault(),as3cf.buckets.saveSelected(a(this))}),a(".as3cf-bucket-container").on("click","a.js-link",function(b){return b.preventDefault(),window.open(a(this).attr("href")),!1}),a("body").on("as3cf-modal-open",function(c,d){if(".as3cf-bucket-container."+b.prefix===d){as3cf.buckets.resetModal();var e=a(".as3cf-bucket-manual h3").data("modal-title");a(".as3cf-bucket-manual h3").text(e),as3cf.buckets.disabledButtons()}}),as3cf.buckets.disabledButtons(),a("body").on("input keyup",".as3cf-create-bucket-form .as3cf-bucket-name",function(c){var d=a(this).val(),e=a(".as3cf-bucket-container."+b.prefix+" .as3cf-create-bucket-form");as3cf.buckets.isValidName(d)?e.find("button[type=submit]").removeAttr("disabled"):e.find("button[type=submit]").attr("disabled",!0),as3cf.buckets.updateNameNotice(d)}),a("body").on("input keyup",".as3cf-manual-save-bucket-form .as3cf-bucket-name",function(c){var d=a(".as3cf-bucket-container."+b.prefix+" .as3cf-manual-save-bucket-form");d.find(".as3cf-bucket-name").val().length<as3cf.buckets.validLength?d.find("button[type=submit]").attr("disabled",!0):d.find("button[type=submit]").removeAttr("disabled")})})}(jQuery,as3cfModal);
|
assets/sass/attachment.scss
ADDED
@@ -0,0 +1,61 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#s3-actions.postbox {
|
2 |
+
.inside {
|
3 |
+
margin: 0;
|
4 |
+
padding: 0;
|
5 |
+
}
|
6 |
+
a, a:hover {
|
7 |
+
text-decoration: none;
|
8 |
+
}
|
9 |
+
.s3-details {
|
10 |
+
padding: 6px 0;
|
11 |
+
|
12 |
+
.misc-pub-section {
|
13 |
+
clear: both;
|
14 |
+
float: left;
|
15 |
+
width: 100%;
|
16 |
+
-webkit-box-sizing: border-box;
|
17 |
+
-moz-box-sizing: border-box;
|
18 |
+
box-sizing: border-box;
|
19 |
+
|
20 |
+
.s3-key {
|
21 |
+
float: left;
|
22 |
+
width: 20%;
|
23 |
+
}
|
24 |
+
.s3-value {
|
25 |
+
font-weight: bold;
|
26 |
+
float: left;
|
27 |
+
width: 80%;
|
28 |
+
}
|
29 |
+
}
|
30 |
+
.not-copied {
|
31 |
+
color: #666666;
|
32 |
+
}
|
33 |
+
}
|
34 |
+
.s3-actions {
|
35 |
+
padding: 10px;
|
36 |
+
clear: both;
|
37 |
+
border-top: 1px solid #ddd;
|
38 |
+
border-bottom: 1px solid #ddd;
|
39 |
+
background: #f5f5f5;
|
40 |
+
|
41 |
+
.copy-action {
|
42 |
+
text-align: right;
|
43 |
+
float: right;
|
44 |
+
line-height: 23px;
|
45 |
+
}
|
46 |
+
|
47 |
+
.remove-action {
|
48 |
+
line-height: 28px;
|
49 |
+
vertical-align: middle;
|
50 |
+
text-align: left;
|
51 |
+
float: left;
|
52 |
+
|
53 |
+
a.local-warning {
|
54 |
+
color: #a00;
|
55 |
+
&:hover {
|
56 |
+
color: #f00;
|
57 |
+
}
|
58 |
+
}
|
59 |
+
}
|
60 |
+
}
|
61 |
+
}
|
assets/sass/media.scss
ADDED
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
body.as3cf-pro {
|
2 |
+
.attachments-browser .media-toolbar-secondary {
|
3 |
+
max-width: 100%;
|
4 |
+
}
|
5 |
+
}
|
6 |
+
|
7 |
+
.as3cfpro_remove a.local-warning {
|
8 |
+
color: #a00;
|
9 |
+
&:hover {
|
10 |
+
color: #f00;
|
11 |
+
text-decoration: none;
|
12 |
+
border: none;
|
13 |
+
}
|
14 |
+
}
|
15 |
+
|
16 |
+
.media-modal a.local-warning {
|
17 |
+
color: #bc0b0b;
|
18 |
+
&:hover {
|
19 |
+
color: red;
|
20 |
+
}
|
21 |
+
}
|
22 |
+
|
23 |
+
.attachment-info .attachment-s3-details {
|
24 |
+
font-weight: bold;
|
25 |
+
margin-bottom: 5px;
|
26 |
+
}
|
classes/amazon-s3-and-cloudfront.php
CHANGED
@@ -42,6 +42,16 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
|
|
42 |
*/
|
43 |
protected $default_tab = '';
|
44 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
45 |
/**
|
46 |
* @var AS3CF_Notices
|
47 |
*/
|
@@ -57,11 +67,6 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
|
|
57 |
*/
|
58 |
protected static $buckets_check = array();
|
59 |
|
60 |
-
/**
|
61 |
-
* @var array
|
62 |
-
*/
|
63 |
-
protected $encode_files = array();
|
64 |
-
|
65 |
/**
|
66 |
* @var AS3CF_Plugin_Compatibility
|
67 |
*/
|
@@ -75,6 +80,8 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
|
|
75 |
const SETTINGS_KEY = 'tantan_wordpress_s3';
|
76 |
const SETTINGS_CONSTANT = 'WPOS3_SETTINGS';
|
77 |
|
|
|
|
|
78 |
/**
|
79 |
* @param string $plugin_file_path
|
80 |
* @param Amazon_Web_Services $aws
|
@@ -86,7 +93,7 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
|
|
86 |
parent::__construct( $plugin_file_path );
|
87 |
|
88 |
$this->aws = $aws;
|
89 |
-
$this->notices = AS3CF_Notices::get_instance( $this
|
90 |
|
91 |
$this->init( $plugin_file_path );
|
92 |
}
|
@@ -104,7 +111,8 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
|
|
104 |
new AS3CF_Upgrade_Region_Meta( $this );
|
105 |
new AS3CF_Upgrade_File_Sizes( $this );
|
106 |
new AS3CF_Upgrade_Meta_WP_Error( $this );
|
107 |
-
$this
|
|
|
108 |
|
109 |
// Plugin setup
|
110 |
add_action( 'aws_admin_menu', array( $this, 'admin_menu' ) );
|
@@ -113,12 +121,18 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
|
|
113 |
// display a notice when either lite or pro is automatically deactivated
|
114 |
add_action( 'pre_current_active_plugins', array( $this, 'plugin_deactivated_notice' ) );
|
115 |
|
|
|
|
|
|
|
|
|
|
|
116 |
// UI AJAX
|
117 |
add_action( 'wp_ajax_as3cf-get-buckets', array( $this, 'ajax_get_buckets' ) );
|
118 |
add_action( 'wp_ajax_as3cf-save-bucket', array( $this, 'ajax_save_bucket' ) );
|
119 |
add_action( 'wp_ajax_as3cf-create-bucket', array( $this, 'ajax_create_bucket' ) );
|
120 |
add_action( 'wp_ajax_as3cf-manual-save-bucket', array( $this, 'ajax_save_bucket' ) );
|
121 |
add_action( 'wp_ajax_as3cf-get-url-preview', array( $this, 'ajax_get_url_preview' ) );
|
|
|
122 |
add_action( 'wp_ajax_as3cf-get-diagnostic-info', array( $this, 'ajax_get_diagnostic_info' ) );
|
123 |
|
124 |
// Rewriting URLs, doesn't depend on plugin being setup
|
@@ -135,6 +149,10 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
|
|
135 |
add_filter( 'delete_attachment', array( $this, 'delete_attachment' ), 20 );
|
136 |
add_filter( 'update_attached_file', array( $this, 'update_attached_file' ), 100, 2 );
|
137 |
|
|
|
|
|
|
|
|
|
138 |
// include compatibility code for other plugins
|
139 |
$this->plugin_compat = new AS3CF_Plugin_Compatibility( $this );
|
140 |
|
@@ -229,6 +247,16 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
|
|
229 |
return '1';
|
230 |
}
|
231 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
232 |
// Turn on object versioning by default
|
233 |
if ( 'object-versioning' == $key && ! isset( $settings['object-versioning'] ) ) {
|
234 |
return '1';
|
@@ -589,6 +617,26 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
|
|
589 |
}
|
590 |
}
|
591 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
592 |
/**
|
593 |
* Generate a preview of the URL of files uploaded to S3
|
594 |
*
|
@@ -610,7 +658,7 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
|
|
610 |
|
611 |
$url = $scheme . '://' . $domain . '/' . $path . $suffix;
|
612 |
|
613 |
-
//
|
614 |
if ( $escape ) {
|
615 |
$url = str_replace( '-', '‑', $url );
|
616 |
}
|
@@ -694,7 +742,7 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
|
|
694 |
* to cope with possible different regions
|
695 |
*/
|
696 |
function remove_attachment_files_from_s3( $post_id, $s3object, $remove_backup_sizes = true, $log_error = false, $return_on_error = false, $force_new_s3_client = false ) {
|
697 |
-
$prefix =
|
698 |
$bucket = $s3object['bucket'];
|
699 |
$region = $this->get_s3object_region( $s3object );
|
700 |
$paths = $this->get_attachment_file_paths( $post_id, false, false, $remove_backup_sizes );
|
@@ -836,8 +884,7 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
|
|
836 |
$acl = $old_s3object['acl'];
|
837 |
}
|
838 |
// use existing prefix
|
839 |
-
$prefix =
|
840 |
-
$prefix = ( '.' === $prefix ) ? '' : $prefix . '/';
|
841 |
// use existing bucket
|
842 |
$bucket = $old_s3object['bucket'];
|
843 |
// get existing region
|
@@ -904,9 +951,9 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
|
|
904 |
$files_to_remove = array();
|
905 |
|
906 |
if ( file_exists( $file_path ) ) {
|
907 |
-
$files_to_remove[] = $file_path;
|
908 |
try {
|
909 |
$s3client->putObject( $args );
|
|
|
910 |
} catch ( Exception $e ) {
|
911 |
$error_msg = sprintf( __( 'Error uploading %s to S3: %s', 'amazon-s3-and-cloudfront' ), $file_path, $e->getMessage() );
|
912 |
|
@@ -940,14 +987,21 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
|
|
940 |
}
|
941 |
}
|
942 |
|
943 |
-
|
|
|
|
|
944 |
if ( ! in_array( $file_path, $files_to_remove ) ) {
|
|
|
|
|
945 |
$additional_images[] = array(
|
946 |
'Key' => $prefix . basename( $file_path ),
|
947 |
'SourceFile' => $file_path,
|
|
|
948 |
);
|
949 |
|
950 |
-
$
|
|
|
|
|
951 |
|
952 |
if ( $remove_local_files_setting ) {
|
953 |
// Record the file size for the additional image
|
@@ -961,9 +1015,9 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
|
|
961 |
|
962 |
foreach ( $additional_images as $image ) {
|
963 |
try {
|
964 |
-
$args
|
965 |
-
$args['ACL'] = self::DEFAULT_ACL;
|
966 |
$s3client->putObject( $args );
|
|
|
967 |
} catch ( Exception $e ) {
|
968 |
AS3CF_Error::log( 'Error uploading ' . $args['SourceFile'] . ' to S3: ' . $e->getMessage() );
|
969 |
}
|
@@ -975,7 +1029,6 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
|
|
975 |
$files_to_remove = apply_filters( 'as3cf_upload_attachment_local_files_to_remove', $files_to_remove, $post_id, $file_path );
|
976 |
// Remove duplicates
|
977 |
$files_to_remove = array_unique( $files_to_remove );
|
978 |
-
|
979 |
// Delete the files
|
980 |
$this->remove_local_files( $files_to_remove );
|
981 |
}
|
@@ -1001,6 +1054,12 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
|
|
1001 |
}
|
1002 |
}
|
1003 |
|
|
|
|
|
|
|
|
|
|
|
|
|
1004 |
do_action( 'wpos3_post_upload_attachment', $post_id, $s3object );
|
1005 |
|
1006 |
if ( ! is_null( $return_metadata ) ) {
|
@@ -1337,26 +1396,6 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
|
|
1337 |
return $filename;
|
1338 |
}
|
1339 |
|
1340 |
-
/**
|
1341 |
-
* Get attachment url
|
1342 |
-
*
|
1343 |
-
* @param string $url
|
1344 |
-
* @param int $post_id
|
1345 |
-
*
|
1346 |
-
* @return bool|mixed|void|WP_Error
|
1347 |
-
*/
|
1348 |
-
function wp_get_attachment_url( $url, $post_id ) {
|
1349 |
-
$new_url = $this->get_attachment_url( $post_id );
|
1350 |
-
if ( false === $new_url ) {
|
1351 |
-
return $url;
|
1352 |
-
}
|
1353 |
-
|
1354 |
-
$new_url = apply_filters( 'wps3_get_attachment_url', $new_url, $post_id, $this ); // Old naming convention, will be deprecated soon
|
1355 |
-
$new_url = apply_filters( 'as3cf_wp_get_attachment_url', $new_url, $post_id );
|
1356 |
-
|
1357 |
-
return $new_url;
|
1358 |
-
}
|
1359 |
-
|
1360 |
/**
|
1361 |
* Get attachment s3 info
|
1362 |
*
|
@@ -1364,7 +1403,7 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
|
|
1364 |
*
|
1365 |
* @return mixed
|
1366 |
*/
|
1367 |
-
function get_attachment_s3_info( $post_id ) {
|
1368 |
return apply_filters( 'as3cf_get_attachment_s3_info', get_post_meta( $post_id, 'amazonS3_info', true ), $post_id );
|
1369 |
}
|
1370 |
|
@@ -1570,25 +1609,101 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
|
|
1570 |
*
|
1571 |
* @return bool|mixed|void|WP_Error
|
1572 |
*/
|
1573 |
-
function get_attachment_url( $post_id, $expires = null, $size = null, $meta = null, $headers = array(), $skip_rewrite_check = false ) {
|
1574 |
if ( ! ( $s3object = $this->is_attachment_served_by_s3( $post_id, $skip_rewrite_check ) ) ) {
|
1575 |
return false;
|
1576 |
}
|
1577 |
|
1578 |
-
|
|
|
|
|
1579 |
}
|
1580 |
|
1581 |
/**
|
1582 |
-
* Get
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1583 |
*
|
1584 |
* @param int $post_id
|
1585 |
-
* @param
|
1586 |
-
* @param null|int $expires
|
1587 |
-
* @param null|string $size
|
1588 |
-
* @param null|array $meta
|
1589 |
-
* @param array $headers
|
1590 |
*
|
1591 |
-
* @return
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1592 |
*/
|
1593 |
public function get_attachment_s3_url( $post_id, $s3object, $expires = null, $size = null, $meta = null, $headers = array() ) {
|
1594 |
$scheme = $this->get_s3_url_scheme();
|
@@ -1601,12 +1716,20 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
|
|
1601 |
$region = '';
|
1602 |
}
|
1603 |
|
1604 |
-
|
1605 |
-
if ( is_null( $expires ) && isset( $s3object['acl'] ) && self::PRIVATE_ACL == $s3object['acl'] ) {
|
1606 |
-
$expires = self::DEFAULT_EXPIRES;
|
1607 |
-
}
|
1608 |
|
1609 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1610 |
|
1611 |
if ( ! is_null( $size ) ) {
|
1612 |
if ( is_null( $meta ) ) {
|
@@ -1617,7 +1740,7 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
|
|
1617 |
return $meta;
|
1618 |
}
|
1619 |
|
1620 |
-
if ( isset( $meta['sizes'][ $size ]['file'] ) ) {
|
1621 |
$size_prefix = dirname( $s3object['key'] );
|
1622 |
$size_file_prefix = ( '.' === $size_prefix ) ? '' : $size_prefix . '/';
|
1623 |
|
@@ -1638,12 +1761,34 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
|
|
1638 |
|
1639 |
$s3object['key'] = $this->maybe_update_cloudfront_path( $s3object['key'] );
|
1640 |
|
1641 |
-
$
|
1642 |
-
$
|
|
|
1643 |
|
1644 |
return apply_filters( 'as3cf_get_attachment_url', $url, $s3object, $post_id, $expires, $headers );
|
1645 |
}
|
1646 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1647 |
/**
|
1648 |
* Maybe encode attachment URLs when retrieving the image tag
|
1649 |
*
|
@@ -1657,7 +1802,8 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
|
|
1657 |
* @return string
|
1658 |
*/
|
1659 |
public function maybe_encode_get_image_tag( $html, $id, $alt, $title, $align, $size ) {
|
1660 |
-
if ( ! $this->is_attachment_served_by_s3( $id ) ) {
|
|
|
1661 |
return $html;
|
1662 |
}
|
1663 |
|
@@ -1669,9 +1815,10 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
|
|
1669 |
}
|
1670 |
|
1671 |
$img_src = $matches[1];
|
1672 |
-
$
|
|
|
1673 |
|
1674 |
-
return str_replace( $img_src, $
|
1675 |
}
|
1676 |
|
1677 |
/**
|
@@ -1685,12 +1832,16 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
|
|
1685 |
* @return array
|
1686 |
*/
|
1687 |
public function maybe_encode_wp_get_attachment_image_src( $image, $attachment_id, $size, $icon ) {
|
1688 |
-
if ( ! $this->is_attachment_served_by_s3( $attachment_id ) ) {
|
|
|
1689 |
return $image;
|
1690 |
}
|
1691 |
|
1692 |
if ( isset( $image[0] ) ) {
|
1693 |
-
$
|
|
|
|
|
|
|
1694 |
}
|
1695 |
|
1696 |
return $image;
|
@@ -1706,17 +1857,21 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
|
|
1706 |
* @return array
|
1707 |
*/
|
1708 |
public function maybe_encode_wp_prepare_attachment_for_js( $response, $attachment, $meta ) {
|
1709 |
-
if ( ! $this->is_attachment_served_by_s3( $attachment->ID ) ) {
|
|
|
1710 |
return $response;
|
1711 |
}
|
1712 |
|
1713 |
if ( isset( $response['url'] ) ) {
|
1714 |
-
$response['url'] = $this->encode_filename_in_path( $response['url']
|
1715 |
}
|
1716 |
|
1717 |
if ( isset( $response['sizes'] ) && is_array( $response['sizes'] ) ) {
|
1718 |
-
foreach ( $response['sizes'] as $
|
1719 |
-
$
|
|
|
|
|
|
|
1720 |
}
|
1721 |
}
|
1722 |
|
@@ -1733,17 +1888,110 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
|
|
1733 |
* @return array
|
1734 |
*/
|
1735 |
public function maybe_encode_image_get_intermediate_size( $data, $post_id, $size ) {
|
1736 |
-
if ( ! $this->is_attachment_served_by_s3( $post_id ) ) {
|
|
|
1737 |
return $data;
|
1738 |
}
|
1739 |
|
1740 |
if ( isset( $data['url'] ) ) {
|
1741 |
-
$
|
|
|
|
|
|
|
1742 |
}
|
1743 |
|
1744 |
return $data;
|
1745 |
}
|
1746 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1747 |
/**
|
1748 |
* Is attachment served by S3.
|
1749 |
*
|
@@ -1770,12 +2018,11 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
|
|
1770 |
* Encode file names according to RFC 3986 when generating urls
|
1771 |
* As per Amazon https://forums.aws.amazon.com/thread.jspa?threadID=55746#jive-message-244233
|
1772 |
*
|
1773 |
-
* @param string
|
1774 |
-
* @param null|int $attachment_id
|
1775 |
*
|
1776 |
-
* @return string Encoded filename
|
1777 |
*/
|
1778 |
-
function encode_filename_in_path( $file
|
1779 |
$url = parse_url( $file );
|
1780 |
|
1781 |
if ( ! isset( $url['path'] ) ) {
|
@@ -1783,61 +2030,48 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
|
|
1783 |
return $file;
|
1784 |
}
|
1785 |
|
1786 |
-
|
1787 |
-
|
|
|
|
|
1788 |
return $file;
|
1789 |
}
|
1790 |
|
1791 |
-
$file_path = dirname( $file );
|
1792 |
-
$file_path = ( '.' !== $file_path ) ? trailingslashit( $file_path ) : '';
|
1793 |
-
$file_name = basename( $url['path'] );
|
1794 |
$encoded_file_name = rawurlencode( $file_name );
|
1795 |
-
$encoded_file_path = $file_path . $encoded_file_name;
|
1796 |
|
1797 |
if ( $file_name === $encoded_file_name ) {
|
1798 |
// File name doesn't need encoding, return original
|
1799 |
return $file;
|
1800 |
}
|
1801 |
|
1802 |
-
$normalized_file_path = $this->normalize_file_path( $encoded_file_path, $attachment_id );
|
1803 |
-
|
1804 |
-
if ( ! in_array( $normalized_file_path, $this->encode_files ) ) {
|
1805 |
-
$this->encode_files[] = $normalized_file_path;
|
1806 |
-
}
|
1807 |
-
|
1808 |
return str_replace( $file_name, $encoded_file_name, $file );
|
1809 |
}
|
1810 |
|
1811 |
/**
|
1812 |
-
*
|
1813 |
*
|
1814 |
-
* @param string
|
1815 |
-
* @param null|int $attachment_id
|
1816 |
*
|
1817 |
-
* @return string
|
1818 |
*/
|
1819 |
-
public function
|
1820 |
-
$url = parse_url( $
|
1821 |
|
1822 |
-
if ( isset( $url['
|
1823 |
-
|
1824 |
-
|
1825 |
-
|
1826 |
|
1827 |
-
|
1828 |
-
// Attempt to remove bucket from path using amazonS3_info key
|
1829 |
-
$s3info = $this->get_attachment_s3_info( $attachment_id );
|
1830 |
-
$bucket = $s3info['bucket'];
|
1831 |
-
} else {
|
1832 |
-
// Attempt to remove bucket from path using tantan key
|
1833 |
-
$bucket = $this->get_setting( 'bucket' );
|
1834 |
-
}
|
1835 |
|
1836 |
-
|
1837 |
-
|
|
|
1838 |
}
|
1839 |
|
1840 |
-
|
|
|
|
|
1841 |
}
|
1842 |
|
1843 |
/**
|
@@ -2783,6 +3017,7 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
|
|
2783 |
if ( $acl == self::DEFAULT_ACL ) {
|
2784 |
unset( $s3object['acl'] );
|
2785 |
}
|
|
|
2786 |
update_post_meta( $post_id, 'amazonS3_info', $s3object );
|
2787 |
} catch ( Exception $e ) {
|
2788 |
$msg = 'Error setting ACL to ' . $acl . ' for ' . $s3object['key'] . ': ' . $e->getMessage();
|
@@ -3132,7 +3367,10 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
|
|
3132 |
$output .= "\r\n";
|
3133 |
$output .= "\r\n";
|
3134 |
|
3135 |
-
$output .=
|
|
|
|
|
|
|
3136 |
$output .= $this->get_url_preview( $escape );
|
3137 |
$output .= "\r\n";
|
3138 |
$output .= "\r\n";
|
@@ -3433,13 +3671,13 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
|
|
3433 |
}
|
3434 |
|
3435 |
// Original file
|
3436 |
-
$paths[] = $original_file;
|
3437 |
|
3438 |
// Sizes
|
3439 |
if ( isset( $meta['sizes'] ) ) {
|
3440 |
-
foreach ( $meta['sizes'] as $size ) {
|
3441 |
-
if ( isset( $
|
3442 |
-
$paths[] = str_replace( $file_name, $
|
3443 |
}
|
3444 |
}
|
3445 |
}
|
@@ -3578,7 +3816,7 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
|
|
3578 |
* true - Attachments only uploaded to S3
|
3579 |
* false - Attachments not uploaded to S3
|
3580 |
*
|
3581 |
-
* @return
|
3582 |
*/
|
3583 |
public function count_attachments( $prefix, $uploaded_to_s3 = null ) {
|
3584 |
global $wpdb;
|
@@ -3599,7 +3837,7 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
|
|
3599 |
|
3600 |
$sql .= ' ' . $where;
|
3601 |
|
3602 |
-
return $wpdb->get_var( $sql );
|
3603 |
}
|
3604 |
|
3605 |
/**
|
@@ -3737,11 +3975,12 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
|
|
3737 |
* @param string $variable
|
3738 |
* @param int $type
|
3739 |
* @param int $filter
|
|
|
3740 |
*
|
3741 |
* @return mixed
|
3742 |
*/
|
3743 |
-
public function filter_input( $variable, $type = INPUT_GET, $filter = FILTER_DEFAULT ) {
|
3744 |
-
return filter_input( $type, $variable, $filter );
|
3745 |
}
|
3746 |
|
3747 |
/**
|
@@ -3790,31 +4029,6 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
|
|
3790 |
return $domain;
|
3791 |
}
|
3792 |
|
3793 |
-
/**
|
3794 |
-
* Display a notice if using the retina hidpi setting when
|
3795 |
-
* we removed support for it in 1.1.
|
3796 |
-
*/
|
3797 |
-
protected function maybe_display_deprecated_retina_notice() {
|
3798 |
-
if ( ! $this->get_setting( 'hidpi-images' ) ) {
|
3799 |
-
// Not using setting, abort
|
3800 |
-
return;
|
3801 |
-
}
|
3802 |
-
|
3803 |
-
$notice_args = array(
|
3804 |
-
'type' => 'notice-info',
|
3805 |
-
'only_show_to_user' => false,
|
3806 |
-
'flash' => false,
|
3807 |
-
);
|
3808 |
-
|
3809 |
-
$doc_url = 'https://deliciousbrains.com/wp-offload-s3/doc/copy-hidpi-2x-images-support/';
|
3810 |
-
$doc_link = $this->dbrains_link( $doc_url, __( 'this doc' ) );
|
3811 |
-
|
3812 |
-
$message = sprintf( '<strong>%s</strong> — ', __( 'WP Offload S3 Feature Removed', 'amazon-s3-and-cloudfront' ) );
|
3813 |
-
$message .= sprintf( __( 'The "Copy HiDPI (@2x) Images" feature has been removed as of version 1.1 of WP Offload S3. It looks like you had this feature turned on. Please see %s for why we removed this feature and how you can continue copying @2x images to S3.', 'amazon-s3-and-cloudfront' ), $doc_link );
|
3814 |
-
|
3815 |
-
$this->notices->add_notice( $message, $notice_args );
|
3816 |
-
}
|
3817 |
-
|
3818 |
/**
|
3819 |
* Display a notice if using setting to force HTTP as url scheme, removed in 1.3.
|
3820 |
*/
|
@@ -3856,4 +4070,268 @@ class Amazon_S3_And_CloudFront extends AWS_Plugin_Base {
|
|
3856 |
|
3857 |
return $path;
|
3858 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3859 |
}
|
42 |
*/
|
43 |
protected $default_tab = '';
|
44 |
|
45 |
+
/**
|
46 |
+
* @var AS3CF_Local_To_S3
|
47 |
+
*/
|
48 |
+
public $filter_local;
|
49 |
+
|
50 |
+
/**
|
51 |
+
* @var AS3CF_S3_To_Local
|
52 |
+
*/
|
53 |
+
public $filter_s3;
|
54 |
+
|
55 |
/**
|
56 |
* @var AS3CF_Notices
|
57 |
*/
|
67 |
*/
|
68 |
protected static $buckets_check = array();
|
69 |
|
|
|
|
|
|
|
|
|
|
|
70 |
/**
|
71 |
* @var AS3CF_Plugin_Compatibility
|
72 |
*/
|
80 |
const SETTINGS_KEY = 'tantan_wordpress_s3';
|
81 |
const SETTINGS_CONSTANT = 'WPOS3_SETTINGS';
|
82 |
|
83 |
+
const LATEST_UPGRADE_ROUTINE = 5;
|
84 |
+
|
85 |
/**
|
86 |
* @param string $plugin_file_path
|
87 |
* @param Amazon_Web_Services $aws
|
93 |
parent::__construct( $plugin_file_path );
|
94 |
|
95 |
$this->aws = $aws;
|
96 |
+
$this->notices = AS3CF_Notices::get_instance( $this );
|
97 |
|
98 |
$this->init( $plugin_file_path );
|
99 |
}
|
111 |
new AS3CF_Upgrade_Region_Meta( $this );
|
112 |
new AS3CF_Upgrade_File_Sizes( $this );
|
113 |
new AS3CF_Upgrade_Meta_WP_Error( $this );
|
114 |
+
new AS3CF_Upgrade_Content_Replace_URLs( $this );
|
115 |
+
new AS3CF_Upgrade_EDD_Replace_URLs( $this );
|
116 |
|
117 |
// Plugin setup
|
118 |
add_action( 'aws_admin_menu', array( $this, 'admin_menu' ) );
|
121 |
// display a notice when either lite or pro is automatically deactivated
|
122 |
add_action( 'pre_current_active_plugins', array( $this, 'plugin_deactivated_notice' ) );
|
123 |
|
124 |
+
// Attachment screens/modals
|
125 |
+
add_action( 'load-upload.php', array( $this, 'load_media_assets' ), 11 );
|
126 |
+
add_action( 'admin_enqueue_scripts', array( $this, 'load_attachment_assets' ), 11 );
|
127 |
+
add_action( 'add_meta_boxes', array( $this, 'attachment_s3_meta_box' ) );
|
128 |
+
|
129 |
// UI AJAX
|
130 |
add_action( 'wp_ajax_as3cf-get-buckets', array( $this, 'ajax_get_buckets' ) );
|
131 |
add_action( 'wp_ajax_as3cf-save-bucket', array( $this, 'ajax_save_bucket' ) );
|
132 |
add_action( 'wp_ajax_as3cf-create-bucket', array( $this, 'ajax_create_bucket' ) );
|
133 |
add_action( 'wp_ajax_as3cf-manual-save-bucket', array( $this, 'ajax_save_bucket' ) );
|
134 |
add_action( 'wp_ajax_as3cf-get-url-preview', array( $this, 'ajax_get_url_preview' ) );
|
135 |
+
add_action( 'wp_ajax_as3cf_get_attachment_s3_details', array( $this, 'ajax_get_attachment_s3_details' ) );
|
136 |
add_action( 'wp_ajax_as3cf-get-diagnostic-info', array( $this, 'ajax_get_diagnostic_info' ) );
|
137 |
|
138 |
// Rewriting URLs, doesn't depend on plugin being setup
|
149 |
add_filter( 'delete_attachment', array( $this, 'delete_attachment' ), 20 );
|
150 |
add_filter( 'update_attached_file', array( $this, 'update_attached_file' ), 100, 2 );
|
151 |
|
152 |
+
// Content filtering
|
153 |
+
$this->filter_local = new AS3CF_Local_To_S3( $this );
|
154 |
+
$this->filter_s3 = new AS3CF_S3_To_Local( $this );
|
155 |
+
|
156 |
// include compatibility code for other plugins
|
157 |
$this->plugin_compat = new AS3CF_Plugin_Compatibility( $this );
|
158 |
|
247 |
return '1';
|
248 |
}
|
249 |
|
250 |
+
// Don't run upgrade routines on fresh install
|
251 |
+
if ( 'post_meta_version' === $key && ! isset( $settings['post_meta_version'] ) ) {
|
252 |
+
$routine = self::LATEST_UPGRADE_ROUTINE;
|
253 |
+
|
254 |
+
$this->set_setting( 'post_meta_version', $routine );
|
255 |
+
$this->save_settings();
|
256 |
+
|
257 |
+
return $routine;
|
258 |
+
}
|
259 |
+
|
260 |
// Turn on object versioning by default
|
261 |
if ( 'object-versioning' == $key && ! isset( $settings['object-versioning'] ) ) {
|
262 |
return '1';
|
617 |
}
|
618 |
}
|
619 |
|
620 |
+
/**
|
621 |
+
* Get local URL preview.
|
622 |
+
*
|
623 |
+
* @param bool $escape
|
624 |
+
* @param string $suffix
|
625 |
+
*
|
626 |
+
* @return string
|
627 |
+
*/
|
628 |
+
protected function get_local_url_preview( $escape = true, $suffix = 'photo.jpg' ) {
|
629 |
+
$uploads = wp_upload_dir();
|
630 |
+
$url = trailingslashit( $uploads['url'] ) . $suffix;
|
631 |
+
|
632 |
+
// Replace hyphens with non breaking hyphens for formatting
|
633 |
+
if ( $escape ) {
|
634 |
+
$url = str_replace( '-', '‑', $url );
|
635 |
+
}
|
636 |
+
|
637 |
+
return $url;
|
638 |
+
}
|
639 |
+
|
640 |
/**
|
641 |
* Generate a preview of the URL of files uploaded to S3
|
642 |
*
|
658 |
|
659 |
$url = $scheme . '://' . $domain . '/' . $path . $suffix;
|
660 |
|
661 |
+
// Replace hyphens with non breaking hyphens for formatting
|
662 |
if ( $escape ) {
|
663 |
$url = str_replace( '-', '‑', $url );
|
664 |
}
|
742 |
* to cope with possible different regions
|
743 |
*/
|
744 |
function remove_attachment_files_from_s3( $post_id, $s3object, $remove_backup_sizes = true, $log_error = false, $return_on_error = false, $force_new_s3_client = false ) {
|
745 |
+
$prefix = $this->normalize_object_prefix( $s3object['key'] );
|
746 |
$bucket = $s3object['bucket'];
|
747 |
$region = $this->get_s3object_region( $s3object );
|
748 |
$paths = $this->get_attachment_file_paths( $post_id, false, false, $remove_backup_sizes );
|
884 |
$acl = $old_s3object['acl'];
|
885 |
}
|
886 |
// use existing prefix
|
887 |
+
$prefix = $this->normalize_object_prefix( $old_s3object['key'] );
|
|
|
888 |
// use existing bucket
|
889 |
$bucket = $old_s3object['bucket'];
|
890 |
// get existing region
|
951 |
$files_to_remove = array();
|
952 |
|
953 |
if ( file_exists( $file_path ) ) {
|
|
|
954 |
try {
|
955 |
$s3client->putObject( $args );
|
956 |
+
$files_to_remove[] = $file_path;
|
957 |
} catch ( Exception $e ) {
|
958 |
$error_msg = sprintf( __( 'Error uploading %s to S3: %s', 'amazon-s3-and-cloudfront' ), $file_path, $e->getMessage() );
|
959 |
|
987 |
}
|
988 |
}
|
989 |
|
990 |
+
$s3object_sizes = array();
|
991 |
+
|
992 |
+
foreach ( $file_paths as $size => $file_path ) {
|
993 |
if ( ! in_array( $file_path, $files_to_remove ) ) {
|
994 |
+
$acl = apply_filters( 'as3cf_upload_acl_sizes', self::DEFAULT_ACL, $size, $post_id, $data );
|
995 |
+
|
996 |
$additional_images[] = array(
|
997 |
'Key' => $prefix . basename( $file_path ),
|
998 |
'SourceFile' => $file_path,
|
999 |
+
'ACL' => $acl,
|
1000 |
);
|
1001 |
|
1002 |
+
if ( self::DEFAULT_ACL !== $acl ) {
|
1003 |
+
$s3object_sizes[ $size ]['acl'] = $acl;
|
1004 |
+
}
|
1005 |
|
1006 |
if ( $remove_local_files_setting ) {
|
1007 |
// Record the file size for the additional image
|
1015 |
|
1016 |
foreach ( $additional_images as $image ) {
|
1017 |
try {
|
1018 |
+
$args = array_merge( $args, $image );
|
|
|
1019 |
$s3client->putObject( $args );
|
1020 |
+
$files_to_remove[] = $image['SourceFile'];
|
1021 |
} catch ( Exception $e ) {
|
1022 |
AS3CF_Error::log( 'Error uploading ' . $args['SourceFile'] . ' to S3: ' . $e->getMessage() );
|
1023 |
}
|
1029 |
$files_to_remove = apply_filters( 'as3cf_upload_attachment_local_files_to_remove', $files_to_remove, $post_id, $file_path );
|
1030 |
// Remove duplicates
|
1031 |
$files_to_remove = array_unique( $files_to_remove );
|
|
|
1032 |
// Delete the files
|
1033 |
$this->remove_local_files( $files_to_remove );
|
1034 |
}
|
1054 |
}
|
1055 |
}
|
1056 |
|
1057 |
+
if ( ! empty( $s3object_sizes ) ) {
|
1058 |
+
// Additional image sizes have custom ACLs, update meta
|
1059 |
+
$s3object['sizes'] = $s3object_sizes;
|
1060 |
+
update_post_meta( $post_id, 'amazonS3_info', $s3object );
|
1061 |
+
}
|
1062 |
+
|
1063 |
do_action( 'wpos3_post_upload_attachment', $post_id, $s3object );
|
1064 |
|
1065 |
if ( ! is_null( $return_metadata ) ) {
|
1396 |
return $filename;
|
1397 |
}
|
1398 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1399 |
/**
|
1400 |
* Get attachment s3 info
|
1401 |
*
|
1403 |
*
|
1404 |
* @return mixed
|
1405 |
*/
|
1406 |
+
public function get_attachment_s3_info( $post_id ) {
|
1407 |
return apply_filters( 'as3cf_get_attachment_s3_info', get_post_meta( $post_id, 'amazonS3_info', true ), $post_id );
|
1408 |
}
|
1409 |
|
1609 |
*
|
1610 |
* @return bool|mixed|void|WP_Error
|
1611 |
*/
|
1612 |
+
public function get_attachment_url( $post_id, $expires = null, $size = null, $meta = null, $headers = array(), $skip_rewrite_check = false ) {
|
1613 |
if ( ! ( $s3object = $this->is_attachment_served_by_s3( $post_id, $skip_rewrite_check ) ) ) {
|
1614 |
return false;
|
1615 |
}
|
1616 |
|
1617 |
+
$url = $this->get_attachment_s3_url( $post_id, $s3object, $expires, $size, $meta, $headers );
|
1618 |
+
|
1619 |
+
return apply_filters( 'as3cf_wp_get_attachment_url', $url, $post_id );
|
1620 |
}
|
1621 |
|
1622 |
/**
|
1623 |
+
* Get attachment local URL.
|
1624 |
+
*
|
1625 |
+
* This is a direct copy of wp_get_attachment_url() from /wp-includes/post.php
|
1626 |
+
* as we filter the URL in AS3CF and can't remove this filter using the current implementation
|
1627 |
+
* of globals for class instances.
|
1628 |
+
*
|
1629 |
+
* @param int $post_id
|
1630 |
+
*
|
1631 |
+
* @return string|false Attachment URL, otherwise false.
|
1632 |
+
*/
|
1633 |
+
public function get_attachment_local_url( $post_id ) {
|
1634 |
+
$url = '';
|
1635 |
+
|
1636 |
+
// Get attached file.
|
1637 |
+
if ( $file = get_post_meta( $post_id, '_wp_attached_file', true ) ) {
|
1638 |
+
// Get upload directory.
|
1639 |
+
if ( ( $uploads = wp_upload_dir() ) && false === $uploads['error'] ) {
|
1640 |
+
// Check that the upload base exists in the file location.
|
1641 |
+
if ( 0 === strpos( $file, $uploads['basedir'] ) ) {
|
1642 |
+
// Replace file location with url location.
|
1643 |
+
$url = str_replace( $uploads['basedir'], $uploads['baseurl'], $file );
|
1644 |
+
} elseif ( false !== strpos( $file, 'wp-content/uploads' ) ) {
|
1645 |
+
$url = $uploads['baseurl'] . substr( $file, strpos( $file, 'wp-content/uploads' ) + 18 );
|
1646 |
+
} else {
|
1647 |
+
// It's a newly-uploaded file, therefore $file is relative to the basedir.
|
1648 |
+
$url = $uploads['baseurl'] . "/$file";
|
1649 |
+
}
|
1650 |
+
}
|
1651 |
+
}
|
1652 |
+
|
1653 |
+
if ( empty( $url ) ) {
|
1654 |
+
return false;
|
1655 |
+
}
|
1656 |
+
|
1657 |
+
// Set correct domain on multisite subdomain installs
|
1658 |
+
if ( is_multisite() ) {
|
1659 |
+
$siteurl = trailingslashit( get_option( 'siteurl' ) );
|
1660 |
+
$network_siteurl = trailingslashit( network_site_url() );
|
1661 |
+
|
1662 |
+
if ( 0 !== strpos( $url, $siteurl ) ) {
|
1663 |
+
// URL already using site URL, no replacement needed
|
1664 |
+
$url = str_replace( $network_siteurl, $siteurl, $url );
|
1665 |
+
}
|
1666 |
+
}
|
1667 |
+
|
1668 |
+
return $url;
|
1669 |
+
}
|
1670 |
+
|
1671 |
+
/**
|
1672 |
+
* Get attachment local URL size.
|
1673 |
*
|
1674 |
* @param int $post_id
|
1675 |
+
* @param string|null $size
|
|
|
|
|
|
|
|
|
1676 |
*
|
1677 |
+
* @return false|string
|
1678 |
+
*/
|
1679 |
+
public function get_attachment_local_url_size( $post_id, $size = null ) {
|
1680 |
+
$url = $this->get_attachment_local_url( $post_id );
|
1681 |
+
|
1682 |
+
if ( empty( $size ) ) {
|
1683 |
+
return $url;
|
1684 |
+
}
|
1685 |
+
|
1686 |
+
$meta = get_post_meta( $post_id, '_wp_attachment_metadata', true );
|
1687 |
+
|
1688 |
+
if ( empty( $meta['sizes'][ $size ]['file'] ) ) {
|
1689 |
+
// No alternative sizes available, return
|
1690 |
+
return $url;
|
1691 |
+
}
|
1692 |
+
|
1693 |
+
return str_replace( wp_basename( $url ), $meta['sizes'][ $size ]['file'], $url );
|
1694 |
+
}
|
1695 |
+
|
1696 |
+
/**
|
1697 |
+
* Get the S3 URL for an attachment
|
1698 |
+
*
|
1699 |
+
* @param int $post_id
|
1700 |
+
* @param array $s3object
|
1701 |
+
* @param null|int $expires
|
1702 |
+
* @param null|string|array $size
|
1703 |
+
* @param null|array $meta
|
1704 |
+
* @param array $headers
|
1705 |
+
*
|
1706 |
+
* @return mixed|WP_Error
|
1707 |
*/
|
1708 |
public function get_attachment_s3_url( $post_id, $s3object, $expires = null, $size = null, $meta = null, $headers = array() ) {
|
1709 |
$scheme = $this->get_s3_url_scheme();
|
1716 |
$region = '';
|
1717 |
}
|
1718 |
|
1719 |
+
$size = $this->maybe_convert_size_to_string( $post_id, $size );
|
|
|
|
|
|
|
1720 |
|
1721 |
+
// Force use of secured URL when ACL has been set to private
|
1722 |
+
if ( is_null( $expires ) ) {
|
1723 |
+
if ( is_null( $size ) && isset( $s3object['acl'] ) && self::PRIVATE_ACL === $s3object['acl'] ) {
|
1724 |
+
// Full size URL private
|
1725 |
+
$expires = self::DEFAULT_EXPIRES;
|
1726 |
+
}
|
1727 |
+
|
1728 |
+
if ( ! is_null( $size ) && isset( $s3object['sizes'][ $size ]['acl'] ) && self::PRIVATE_ACL === $s3object['sizes'][ $size ]['acl'] ) {
|
1729 |
+
// Alternative size URL private
|
1730 |
+
$expires = self::DEFAULT_EXPIRES;
|
1731 |
+
}
|
1732 |
+
}
|
1733 |
|
1734 |
if ( ! is_null( $size ) ) {
|
1735 |
if ( is_null( $meta ) ) {
|
1740 |
return $meta;
|
1741 |
}
|
1742 |
|
1743 |
+
if ( ! empty( $meta ) && isset( $meta['sizes'][ $size ]['file'] ) ) {
|
1744 |
$size_prefix = dirname( $s3object['key'] );
|
1745 |
$size_file_prefix = ( '.' === $size_prefix ) ? '' : $size_prefix . '/';
|
1746 |
|
1761 |
|
1762 |
$s3object['key'] = $this->maybe_update_cloudfront_path( $s3object['key'] );
|
1763 |
|
1764 |
+
$domain_bucket = $this->get_s3_url_domain( $s3object['bucket'], $region, $expires );
|
1765 |
+
$file = $this->encode_filename_in_path( $s3object['key'] );
|
1766 |
+
$url = $scheme . '://' . $domain_bucket . '/' . $file;
|
1767 |
|
1768 |
return apply_filters( 'as3cf_get_attachment_url', $url, $s3object, $post_id, $expires, $headers );
|
1769 |
}
|
1770 |
|
1771 |
+
/**
|
1772 |
+
* Get attachment url
|
1773 |
+
*
|
1774 |
+
* @param string $url
|
1775 |
+
* @param int $post_id
|
1776 |
+
*
|
1777 |
+
* @return bool|mixed|void|WP_Error
|
1778 |
+
*/
|
1779 |
+
public function wp_get_attachment_url( $url, $post_id ) {
|
1780 |
+
$new_url = $this->get_attachment_url( $post_id );
|
1781 |
+
|
1782 |
+
if ( false === $new_url ) {
|
1783 |
+
return $url;
|
1784 |
+
}
|
1785 |
+
|
1786 |
+
$new_url = apply_filters( 'wps3_get_attachment_url', $new_url, $post_id, $this ); // Old naming convention, will be deprecated soon
|
1787 |
+
$new_url = apply_filters( 'as3cf_wp_get_attachment_url', $new_url, $post_id );
|
1788 |
+
|
1789 |
+
return $new_url;
|
1790 |
+
}
|
1791 |
+
|
1792 |
/**
|
1793 |
* Maybe encode attachment URLs when retrieving the image tag
|
1794 |
*
|
1802 |
* @return string
|
1803 |
*/
|
1804 |
public function maybe_encode_get_image_tag( $html, $id, $alt, $title, $align, $size ) {
|
1805 |
+
if ( ! ( $s3object = $this->is_attachment_served_by_s3( $id ) ) ) {
|
1806 |
+
// Not served by S3, return
|
1807 |
return $html;
|
1808 |
}
|
1809 |
|
1815 |
}
|
1816 |
|
1817 |
$img_src = $matches[1];
|
1818 |
+
$new_img_src = $this->maybe_sign_intermediate_size( $img_src, $id, $size, $s3object );
|
1819 |
+
$new_img_src = $this->encode_filename_in_path( $new_img_src );
|
1820 |
|
1821 |
+
return str_replace( $img_src, $new_img_src, $html );
|
1822 |
}
|
1823 |
|
1824 |
/**
|
1832 |
* @return array
|
1833 |
*/
|
1834 |
public function maybe_encode_wp_get_attachment_image_src( $image, $attachment_id, $size, $icon ) {
|
1835 |
+
if ( ! ( $s3object = $this->is_attachment_served_by_s3( $attachment_id ) ) ) {
|
1836 |
+
// Not served by S3, return
|
1837 |
return $image;
|
1838 |
}
|
1839 |
|
1840 |
if ( isset( $image[0] ) ) {
|
1841 |
+
$url = $this->maybe_sign_intermediate_size( $image[0], $attachment_id, $size, $s3object );
|
1842 |
+
$url = $this->encode_filename_in_path( $url );
|
1843 |
+
|
1844 |
+
$image[0] = $url;
|
1845 |
}
|
1846 |
|
1847 |
return $image;
|
1857 |
* @return array
|
1858 |
*/
|
1859 |
public function maybe_encode_wp_prepare_attachment_for_js( $response, $attachment, $meta ) {
|
1860 |
+
if ( ! ( $s3object = $this->is_attachment_served_by_s3( $attachment->ID ) ) ) {
|
1861 |
+
// Not served by S3, return
|
1862 |
return $response;
|
1863 |
}
|
1864 |
|
1865 |
if ( isset( $response['url'] ) ) {
|
1866 |
+
$response['url'] = $this->encode_filename_in_path( $response['url'] );
|
1867 |
}
|
1868 |
|
1869 |
if ( isset( $response['sizes'] ) && is_array( $response['sizes'] ) ) {
|
1870 |
+
foreach ( $response['sizes'] as $size => $value ) {
|
1871 |
+
$url = $this->maybe_sign_intermediate_size( $value['url'], $attachment->ID, $size, $s3object );
|
1872 |
+
$url = $this->encode_filename_in_path( $url );
|
1873 |
+
|
1874 |
+
$response['sizes'][ $size ]['url'] = $url;
|
1875 |
}
|
1876 |
}
|
1877 |
|
1888 |
* @return array
|
1889 |
*/
|
1890 |
public function maybe_encode_image_get_intermediate_size( $data, $post_id, $size ) {
|
1891 |
+
if ( ! ( $s3object = $this->is_attachment_served_by_s3( $post_id ) ) ) {
|
1892 |
+
// Not served by S3, return
|
1893 |
return $data;
|
1894 |
}
|
1895 |
|
1896 |
if ( isset( $data['url'] ) ) {
|
1897 |
+
$url = $this->maybe_sign_intermediate_size( $data['url'], $post_id, $size, $s3object );
|
1898 |
+
$url = $this->encode_filename_in_path( $url );
|
1899 |
+
|
1900 |
+
$data['url'] = $url;
|
1901 |
}
|
1902 |
|
1903 |
return $data;
|
1904 |
}
|
1905 |
|
1906 |
+
/**
|
1907 |
+
* Sign intermediate size.
|
1908 |
+
*
|
1909 |
+
* @param string $url
|
1910 |
+
* @param int $attachment_id
|
1911 |
+
* @param string|array $size
|
1912 |
+
* @param bool|array $s3object
|
1913 |
+
*
|
1914 |
+
* @return mixed|WP_Error
|
1915 |
+
*/
|
1916 |
+
protected function maybe_sign_intermediate_size( $url, $attachment_id, $size, $s3object = false ) {
|
1917 |
+
if ( ! $s3object ) {
|
1918 |
+
$s3object = $this->get_attachment_s3_info( $attachment_id );
|
1919 |
+
}
|
1920 |
+
|
1921 |
+
$size = $this->maybe_convert_size_to_string( $attachment_id, $size );
|
1922 |
+
|
1923 |
+
if ( isset( $s3object['sizes'][ $size ] ) ) {
|
1924 |
+
// Private file, add AWS signature if required
|
1925 |
+
return $this->get_attachment_s3_url( $attachment_id, $s3object, null, $size );
|
1926 |
+
}
|
1927 |
+
|
1928 |
+
return $url;
|
1929 |
+
}
|
1930 |
+
|
1931 |
+
/**
|
1932 |
+
* Convert dimensions to size
|
1933 |
+
*
|
1934 |
+
* @param int $attachment_id
|
1935 |
+
* @param array $dimensions
|
1936 |
+
*
|
1937 |
+
* @return null|string
|
1938 |
+
*/
|
1939 |
+
protected function convert_dimensions_to_size_name( $attachment_id, $dimensions ) {
|
1940 |
+
$w = $dimensions[0];
|
1941 |
+
$h = $dimensions[1];
|
1942 |
+
$original_aspect_ratio = $w / $h;
|
1943 |
+
$meta = wp_get_attachment_metadata( $attachment_id );
|
1944 |
+
|
1945 |
+
if ( ! isset( $meta['sizes'] ) || empty( $meta['sizes'] ) ) {
|
1946 |
+
return null;
|
1947 |
+
}
|
1948 |
+
|
1949 |
+
$sizes = $meta['sizes'];
|
1950 |
+
uasort( $sizes, function( $a, $b ) {
|
1951 |
+
// Order by image area
|
1952 |
+
return ( $a['width'] * $a['height'] ) - ( $b['width'] * $b['height'] );
|
1953 |
+
} );
|
1954 |
+
|
1955 |
+
$nearest_matches = array();
|
1956 |
+
|
1957 |
+
foreach ( $sizes as $size => $value ) {
|
1958 |
+
if ( $w > $value['width'] || $h > $value['height'] ) {
|
1959 |
+
continue;
|
1960 |
+
}
|
1961 |
+
|
1962 |
+
$aspect_ratio = $value['width'] / $value['height'];
|
1963 |
+
|
1964 |
+
if ( $aspect_ratio === $original_aspect_ratio ) {
|
1965 |
+
return $size;
|
1966 |
+
}
|
1967 |
+
|
1968 |
+
$nearest_matches[] = $size;
|
1969 |
+
}
|
1970 |
+
|
1971 |
+
// Return nearest match
|
1972 |
+
if ( ! empty( $nearest_matches ) ) {
|
1973 |
+
return $nearest_matches[0];
|
1974 |
+
}
|
1975 |
+
|
1976 |
+
return null;
|
1977 |
+
}
|
1978 |
+
|
1979 |
+
/**
|
1980 |
+
* Maybe convert size to string
|
1981 |
+
*
|
1982 |
+
* @param int $attachment_id
|
1983 |
+
* @param mixed $size
|
1984 |
+
*
|
1985 |
+
* @return null|string
|
1986 |
+
*/
|
1987 |
+
protected function maybe_convert_size_to_string( $attachment_id, $size ) {
|
1988 |
+
if ( is_array( $size ) ) {
|
1989 |
+
return $this->convert_dimensions_to_size_name( $attachment_id, $size );
|
1990 |
+
}
|
1991 |
+
|
1992 |
+
return $size;
|
1993 |
+
}
|
1994 |
+
|
1995 |
/**
|
1996 |
* Is attachment served by S3.
|
1997 |
*
|
2018 |
* Encode file names according to RFC 3986 when generating urls
|
2019 |
* As per Amazon https://forums.aws.amazon.com/thread.jspa?threadID=55746#jive-message-244233
|
2020 |
*
|
2021 |
+
* @param string $file
|
|
|
2022 |
*
|
2023 |
+
* @return string Encoded filename
|
2024 |
*/
|
2025 |
+
public function encode_filename_in_path( $file ) {
|
2026 |
$url = parse_url( $file );
|
2027 |
|
2028 |
if ( ! isset( $url['path'] ) ) {
|
2030 |
return $file;
|
2031 |
}
|
2032 |
|
2033 |
+
$file_name = basename( $url['path'] );
|
2034 |
+
|
2035 |
+
if ( false !== strpos( $file_name, '%' ) ) {
|
2036 |
+
// File name already encoded, return original
|
2037 |
return $file;
|
2038 |
}
|
2039 |
|
|
|
|
|
|
|
2040 |
$encoded_file_name = rawurlencode( $file_name );
|
|
|
2041 |
|
2042 |
if ( $file_name === $encoded_file_name ) {
|
2043 |
// File name doesn't need encoding, return original
|
2044 |
return $file;
|
2045 |
}
|
2046 |
|
|
|
|
|
|
|
|
|
|
|
|
|
2047 |
return str_replace( $file_name, $encoded_file_name, $file );
|
2048 |
}
|
2049 |
|
2050 |
/**
|
2051 |
+
* Decode file name.
|
2052 |
*
|
2053 |
+
* @param string $file
|
|
|
2054 |
*
|
2055 |
+
* @return string
|
2056 |
*/
|
2057 |
+
public function decode_filename_in_path( $file ) {
|
2058 |
+
$url = parse_url( $file );
|
2059 |
|
2060 |
+
if ( ! isset( $url['path'] ) ) {
|
2061 |
+
// Can't determine path, return original
|
2062 |
+
return $file;
|
2063 |
+
}
|
2064 |
|
2065 |
+
$file_name = basename( $url['path'] );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2066 |
|
2067 |
+
if ( false === strpos( $file_name, '%' ) ) {
|
2068 |
+
// File name not encoded, return original
|
2069 |
+
return $file;
|
2070 |
}
|
2071 |
|
2072 |
+
$decoded_file_name = rawurldecode( $file_name );
|
2073 |
+
|
2074 |
+
return str_replace( $file_name, $decoded_file_name, $file );
|
2075 |
}
|
2076 |
|
2077 |
/**
|
3017 |
if ( $acl == self::DEFAULT_ACL ) {
|
3018 |
unset( $s3object['acl'] );
|
3019 |
}
|
3020 |
+
|
3021 |
update_post_meta( $post_id, 'amazonS3_info', $s3object );
|
3022 |
} catch ( Exception $e ) {
|
3023 |
$msg = 'Error setting ACL to ' . $acl . ' for ' . $s3object['key'] . ': ' . $e->getMessage();
|
3367 |
$output .= "\r\n";
|
3368 |
$output .= "\r\n";
|
3369 |
|
3370 |
+
$output .= "Local URL:\r\n";
|
3371 |
+
$output .= $this->get_local_url_preview( $escape );
|
3372 |
+
$output .= "\r\n";
|
3373 |
+
$output .= "S3 URL:\r\n";
|
3374 |
$output .= $this->get_url_preview( $escape );
|
3375 |
$output .= "\r\n";
|
3376 |
$output .= "\r\n";
|
3671 |
}
|
3672 |
|
3673 |
// Original file
|
3674 |
+
$paths['full'] = $original_file;
|
3675 |
|
3676 |
// Sizes
|
3677 |
if ( isset( $meta['sizes'] ) ) {
|
3678 |
+
foreach ( $meta['sizes'] as $size => $file ) {
|
3679 |
+
if ( isset( $file['file'] ) ) {
|
3680 |
+
$paths[ $size ] = str_replace( $file_name, $file['file'], $file_path );
|
3681 |
}
|
3682 |
}
|
3683 |
}
|
3816 |
* true - Attachments only uploaded to S3
|
3817 |
* false - Attachments not uploaded to S3
|
3818 |
*
|
3819 |
+
* @return int
|
3820 |
*/
|
3821 |
public function count_attachments( $prefix, $uploaded_to_s3 = null ) {
|
3822 |
global $wpdb;
|
3837 |
|
3838 |
$sql .= ' ' . $where;
|
3839 |
|
3840 |
+
return (int) $wpdb->get_var( $sql );
|
3841 |
}
|
3842 |
|
3843 |
/**
|
3975 |
* @param string $variable
|
3976 |
* @param int $type
|
3977 |
* @param int $filter
|
3978 |
+
* @param mixed $options
|
3979 |
*
|
3980 |
* @return mixed
|
3981 |
*/
|
3982 |
+
public function filter_input( $variable, $type = INPUT_GET, $filter = FILTER_DEFAULT, $options = array() ) {
|
3983 |
+
return filter_input( $type, $variable, $filter, $options );
|
3984 |
}
|
3985 |
|
3986 |
/**
|
4029 |
return $domain;
|
4030 |
}
|
4031 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4032 |
/**
|
4033 |
* Display a notice if using setting to force HTTP as url scheme, removed in 1.3.
|
4034 |
*/
|
4070 |
|
4071 |
return $path;
|
4072 |
}
|
4073 |
+
|
4074 |
+
/**
|
4075 |
+
* Add the S3 meta box to the attachment screen
|
4076 |
+
*/
|
4077 |
+
public function attachment_s3_meta_box() {
|
4078 |
+
add_meta_box( 's3-actions', __( 'Amazon S3', 'amazon-s3-and-cloudfront' ), array( $this, 'attachment_s3_actions_meta_box' ), 'attachment', 'side', 'core' );
|
4079 |
+
}
|
4080 |
+
|
4081 |
+
/**
|
4082 |
+
* Check we can do the media actions
|
4083 |
+
*
|
4084 |
+
* @return bool
|
4085 |
+
*/
|
4086 |
+
public function verify_media_actions() {
|
4087 |
+
return false;
|
4088 |
+
}
|
4089 |
+
|
4090 |
+
/**
|
4091 |
+
* Render the S3 attachment meta box
|
4092 |
+
*/
|
4093 |
+
public function attachment_s3_actions_meta_box() {
|
4094 |
+
global $post;
|
4095 |
+
$file = get_attached_file( $post->ID, true );
|
4096 |
+
|
4097 |
+
$args = array(
|
4098 |
+
's3object' => $this->get_formatted_s3_info( $post->ID ),
|
4099 |
+
'post' => $post,
|
4100 |
+
'local_file_exists' => file_exists( $file ),
|
4101 |
+
'user_can_perform_actions' => $this->verify_media_actions(),
|
4102 |
+
'sendback' => 'post.php?post=' . $post->ID . '&action=edit',
|
4103 |
+
);
|
4104 |
+
|
4105 |
+
$this->render_view( 'attachment-metabox', $args );
|
4106 |
+
}
|
4107 |
+
|
4108 |
+
/**
|
4109 |
+
* Get ACL value string.
|
4110 |
+
*
|
4111 |
+
* @param array $acl
|
4112 |
+
*
|
4113 |
+
* @return string
|
4114 |
+
*/
|
4115 |
+
protected function get_acl_value_string( $acl ) {
|
4116 |
+
return $acl['name'];
|
4117 |
+
}
|
4118 |
+
|
4119 |
+
/**
|
4120 |
+
* Return a formatted S3 info with display friendly defaults
|
4121 |
+
*
|
4122 |
+
* @param int $id
|
4123 |
+
* @param array|null $s3object
|
4124 |
+
*
|
4125 |
+
* @return array
|
4126 |
+
*/
|
4127 |
+
public function get_formatted_s3_info( $id, $s3object = null ) {
|
4128 |
+
if ( is_null( $s3object ) ) {
|
4129 |
+
if ( ! ( $s3object = $this->get_attachment_s3_info( $id ) ) ) {
|
4130 |
+
return false;
|
4131 |
+
}
|
4132 |
+
}
|
4133 |
+
|
4134 |
+
$s3object['url'] = $this->get_attachment_s3_url( $id, $s3object );
|
4135 |
+
|
4136 |
+
$acl = ( isset( $s3object['acl'] ) ) ? $s3object['acl'] : self::DEFAULT_ACL;
|
4137 |
+
$acl_info = array(
|
4138 |
+
'acl' => $acl,
|
4139 |
+
'name' => $this->get_acl_display_name( $acl ),
|
4140 |
+
'title' => $this->get_media_action_strings( 'change_to_private' ),
|
4141 |
+
);
|
4142 |
+
|
4143 |
+
if ( self::PRIVATE_ACL === $acl ) {
|
4144 |
+
$acl_info['title'] = $this->get_media_action_strings( 'change_to_public' );
|
4145 |
+
}
|
4146 |
+
|
4147 |
+
$s3object['acl'] = $acl_info;
|
4148 |
+
|
4149 |
+
$regions = $this->get_aws_regions();
|
4150 |
+
|
4151 |
+
if ( isset( $s3object['region'] ) && '' == $s3object['region'] ) {
|
4152 |
+
$s3object['region'] = self::DEFAULT_REGION;
|
4153 |
+
}
|
4154 |
+
|
4155 |
+
if ( isset( $regions[ $s3object['region'] ] ) ) {
|
4156 |
+
$s3object['region'] = $regions[ $s3object['region'] ];
|
4157 |
+
}
|
4158 |
+
|
4159 |
+
return $s3object;
|
4160 |
+
}
|
4161 |
+
|
4162 |
+
/**
|
4163 |
+
* Get all strings or a specific string used for the media actions
|
4164 |
+
*
|
4165 |
+
* @param null|string $string
|
4166 |
+
*
|
4167 |
+
* @return array|string
|
4168 |
+
*/
|
4169 |
+
public function get_media_action_strings( $string = null ) {
|
4170 |
+
$strings = apply_filters( 'as3cf_media_action_strings', array(
|
4171 |
+
'amazon_s3' => __( 'Amazon S3', 'amazon-s3-and-cloudfront' ),
|
4172 |
+
'bucket' => _x( 'Bucket', 'Amazon S3 bucket', 'amazon-s3-and-cloudfront' ),
|
4173 |
+
'key' => _x( 'Path', 'Path to file on Amazon S3', 'amazon-s3-and-cloudfront' ),
|
4174 |
+
'region' => _x( 'Region', 'Location of Amazon S3 bucket', 'amazon-s3-and-cloudfront' ),
|
4175 |
+
'acl' => _x( 'Access', 'Access control list of the file on Amazon S3', 'amazon-s3-and-cloudfront' ),
|
4176 |
+
'url' => __( 'URL', 'amazon-s3-and-cloudfront' ),
|
4177 |
+
) );
|
4178 |
+
|
4179 |
+
if ( ! is_null( $string ) ) {
|
4180 |
+
return isset( $strings[ $string ] ) ? $strings[ $string ] : '';
|
4181 |
+
}
|
4182 |
+
|
4183 |
+
return $strings;
|
4184 |
+
}
|
4185 |
+
|
4186 |
+
/**
|
4187 |
+
* Load media assets.
|
4188 |
+
*/
|
4189 |
+
public function load_media_assets() {
|
4190 |
+
$version = $this->get_asset_version();
|
4191 |
+
$suffix = $this->get_asset_suffix();
|
4192 |
+
|
4193 |
+
$src = plugins_url( 'assets/css/media.css', $this->plugin_file_path );
|
4194 |
+
wp_enqueue_style( 'as3cf-media-styles', $src, array( 'as3cf-modal' ), $version );
|
4195 |
+
|
4196 |
+
$src = plugins_url( 'assets/js/media' . $suffix . '.js', $this->plugin_file_path );
|
4197 |
+
wp_enqueue_script( 'as3cf-media-script', $src, array( 'jquery', 'media-views', 'media-grid', 'wp-util' ), $version, true );
|
4198 |
+
|
4199 |
+
wp_localize_script( 'as3cf-media-script',
|
4200 |
+
'as3cf_media',
|
4201 |
+
array(
|
4202 |
+
'strings' => $this->get_media_action_strings(),
|
4203 |
+
'nonces' => array(
|
4204 |
+
'get_attachment_s3_details' => wp_create_nonce( 'get-attachment-s3-details' ),
|
4205 |
+
)
|
4206 |
+
)
|
4207 |
+
);
|
4208 |
+
}
|
4209 |
+
|
4210 |
+
/**
|
4211 |
+
* Handle retieving the S3 details for attachment modals.
|
4212 |
+
*/
|
4213 |
+
public function ajax_get_attachment_s3_details() {
|
4214 |
+
if ( ! isset( $_POST['id'] ) ) {
|
4215 |
+
return;
|
4216 |
+
}
|
4217 |
+
|
4218 |
+
check_ajax_referer( 'get-attachment-s3-details', '_nonce' );
|
4219 |
+
|
4220 |
+
$id = intval( $_POST['id'] );
|
4221 |
+
|
4222 |
+
// get the actions available for the attachment
|
4223 |
+
$data = array(
|
4224 |
+
'links' => $this->add_media_row_actions( array(), $id ),
|
4225 |
+
's3object' => $this->get_formatted_s3_info( $id ),
|
4226 |
+
'acl_toggle' => $this->verify_media_actions(),
|
4227 |
+
);
|
4228 |
+
|
4229 |
+
wp_send_json_success( $data );
|
4230 |
+
}
|
4231 |
+
|
4232 |
+
/**
|
4233 |
+
* Conditionally adds copy, remove and download S3 action links for an
|
4234 |
+
* attachment on the Media library list view
|
4235 |
+
*
|
4236 |
+
* @param array $actions
|
4237 |
+
* @param WP_Post|int $post
|
4238 |
+
*
|
4239 |
+
* @return array
|
4240 |
+
*/
|
4241 |
+
function add_media_row_actions( $actions = array(), $post ) {
|
4242 |
+
return $actions;
|
4243 |
+
}
|
4244 |
+
|
4245 |
+
/**
|
4246 |
+
* Load the attachment assets only when editing an attachment
|
4247 |
+
*
|
4248 |
+
* @param $hook_suffix
|
4249 |
+
*/
|
4250 |
+
public function load_attachment_assets( $hook_suffix ) {
|
4251 |
+
$version = $this->get_asset_version();
|
4252 |
+
$suffix = $this->get_asset_suffix();
|
4253 |
+
|
4254 |
+
global $post;
|
4255 |
+
if ( 'post.php' != $hook_suffix || 'attachment' != $post->post_type ) {
|
4256 |
+
return;
|
4257 |
+
}
|
4258 |
+
|
4259 |
+
$src = plugins_url( 'assets/css/attachment.css', $this->plugin_file_path );
|
4260 |
+
wp_enqueue_style( 'as3cf-pro-attachment-styles', $src, array( 'as3cf-modal' ), $version );
|
4261 |
+
|
4262 |
+
do_action( 'as3cf_load_attachment_assets', $version, $suffix );
|
4263 |
+
}
|
4264 |
+
|
4265 |
+
/**
|
4266 |
+
* Maybe remove query string from URL.
|
4267 |
+
*
|
4268 |
+
* @param string $url
|
4269 |
+
*
|
4270 |
+
* @return string
|
4271 |
+
*/
|
4272 |
+
public function maybe_remove_query_string( $url ) {
|
4273 |
+
$parts = explode( '?', $url );
|
4274 |
+
|
4275 |
+
return reset( $parts );
|
4276 |
+
}
|
4277 |
+
|
4278 |
+
/**
|
4279 |
+
* Normalize object prefix.
|
4280 |
+
*
|
4281 |
+
* @param string $prefix
|
4282 |
+
*
|
4283 |
+
* @return string
|
4284 |
+
*/
|
4285 |
+
protected function normalize_object_prefix( $prefix ) {
|
4286 |
+
$directory = dirname( $prefix );
|
4287 |
+
|
4288 |
+
return ( '.' === $directory ) ? '' : $directory . '/';
|
4289 |
+
}
|
4290 |
+
|
4291 |
+
/**
|
4292 |
+
* Remove scheme from URL.
|
4293 |
+
*
|
4294 |
+
* @param string $url
|
4295 |
+
*
|
4296 |
+
* @return string
|
4297 |
+
*/
|
4298 |
+
public function remove_scheme( $url ) {
|
4299 |
+
return preg_replace( '/^(?:http|https):/', '', $url );
|
4300 |
+
}
|
4301 |
+
|
4302 |
+
/**
|
4303 |
+
* Remove size from filename (image[-100x100].jpeg).
|
4304 |
+
*
|
4305 |
+
* @param string $url
|
4306 |
+
* @param bool $remove_extension
|
4307 |
+
*
|
4308 |
+
* @return string
|
4309 |
+
*/
|
4310 |
+
public function remove_size_from_filename( $url, $remove_extension = false ) {
|
4311 |
+
$url = preg_replace( '/^(\S+)-[0-9]{1,4}x[0-9]{1,4}(\.[a-zA-Z0-9\.]{2,})?/', '$1$2', $url );
|
4312 |
+
|
4313 |
+
if ( $remove_extension ) {
|
4314 |
+
$parts = pathinfo( $url );
|
4315 |
+
$url = str_replace( '.' . $parts['extension'], '', $url );
|
4316 |
+
}
|
4317 |
+
|
4318 |
+
return $url;
|
4319 |
+
}
|
4320 |
+
|
4321 |
+
/**
|
4322 |
+
* Update site option.
|
4323 |
+
*
|
4324 |
+
* @param string $option
|
4325 |
+
* @param mixed $value
|
4326 |
+
* @param bool $autoload
|
4327 |
+
*
|
4328 |
+
* @return bool
|
4329 |
+
*/
|
4330 |
+
public function update_site_option( $option, $value, $autoload = true ) {
|
4331 |
+
if ( is_multisite() ) {
|
4332 |
+
return update_site_option( $option, $value );
|
4333 |
+
}
|
4334 |
+
|
4335 |
+
return update_option( $option, $value, $autoload );
|
4336 |
+
}
|
4337 |
}
|
classes/as3cf-filter.php
ADDED
@@ -0,0 +1,692 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
abstract class AS3CF_Filter {
|
4 |
+
|
5 |
+
/**
|
6 |
+
* @var Amazon_S3_And_CloudFront
|
7 |
+
*/
|
8 |
+
protected $as3cf;
|
9 |
+
|
10 |
+
/**
|
11 |
+
* @var array
|
12 |
+
*/
|
13 |
+
protected $query_cache = array();
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Constructor
|
17 |
+
*
|
18 |
+
* @param Amazon_S3_And_CloudFront $as3cf
|
19 |
+
*/
|
20 |
+
public function __construct( $as3cf ) {
|
21 |
+
$this->as3cf = $as3cf;
|
22 |
+
|
23 |
+
// Purge on attachment delete
|
24 |
+
add_action( 'delete_attachment', array( $this, 'purge_cache_on_attachment_delete' ) );
|
25 |
+
|
26 |
+
$this->init();
|
27 |
+
}
|
28 |
+
|
29 |
+
/**
|
30 |
+
* Filter EDD download files.
|
31 |
+
*
|
32 |
+
* @param array $value
|
33 |
+
*
|
34 |
+
* @return array
|
35 |
+
*/
|
36 |
+
public function filter_edd_download_files( $value ) {
|
37 |
+
if ( ! $this->should_filter_content() ) {
|
38 |
+
// Not filtering content, return
|
39 |
+
return $value;
|
40 |
+
}
|
41 |
+
|
42 |
+
if ( empty( $value ) ) {
|
43 |
+
// Nothing to filter, return
|
44 |
+
return $value;
|
45 |
+
}
|
46 |
+
|
47 |
+
foreach ( $value as $key => $attachment ) {
|
48 |
+
$url = $this->get_url( $attachment['attachment_id'] );
|
49 |
+
|
50 |
+
if ( $url ) {
|
51 |
+
$value[ $key ]['file'] = $this->get_url( $attachment['attachment_id'] );
|
52 |
+
}
|
53 |
+
}
|
54 |
+
|
55 |
+
return $value;
|
56 |
+
}
|
57 |
+
|
58 |
+
/**
|
59 |
+
* Filter customizer image.
|
60 |
+
*
|
61 |
+
* @param string $value
|
62 |
+
* @param bool|string $old_value
|
63 |
+
*
|
64 |
+
* @return string
|
65 |
+
*/
|
66 |
+
public function filter_customizer_image( $value, $old_value = false ) {
|
67 |
+
if ( empty( $value ) || is_a( $value, 'stdClass' ) ) {
|
68 |
+
return $value;
|
69 |
+
}
|
70 |
+
|
71 |
+
$cache = $this->get_option_cache();
|
72 |
+
$to_cache = array();
|
73 |
+
$value = $this->process_content( $value, $cache, $to_cache );
|
74 |
+
|
75 |
+
$this->maybe_update_option_cache( $to_cache );
|
76 |
+
|
77 |
+
return $value;
|
78 |
+
}
|
79 |
+
|
80 |
+
/**
|
81 |
+
* Filter header image data.
|
82 |
+
*
|
83 |
+
* @param stdClass $value
|
84 |
+
* @param bool|stdClass $old_value
|
85 |
+
*
|
86 |
+
* @return stdClass
|
87 |
+
*/
|
88 |
+
public function filter_header_image_data( $value, $old_value = false ) {
|
89 |
+
$url = $this->get_url( $value->attachment_id );
|
90 |
+
|
91 |
+
if ( $url ) {
|
92 |
+
$value->url = $url;
|
93 |
+
$value->thumbnail_url = $url;
|
94 |
+
}
|
95 |
+
|
96 |
+
return $value;
|
97 |
+
}
|
98 |
+
|
99 |
+
/**
|
100 |
+
* Filter post.
|
101 |
+
*
|
102 |
+
* @param string $content
|
103 |
+
*
|
104 |
+
* @return string
|
105 |
+
*/
|
106 |
+
public function filter_post( $content ) {
|
107 |
+
if ( empty( $content ) ) {
|
108 |
+
// Nothing to filter, continue
|
109 |
+
return $content;
|
110 |
+
}
|
111 |
+
|
112 |
+
$cache = $this->get_post_cache();
|
113 |
+
$to_cache = array();
|
114 |
+
$content = $this->process_content( $content, $cache, $to_cache );
|
115 |
+
|
116 |
+
$this->maybe_update_post_cache( $to_cache );
|
117 |
+
|
118 |
+
return $content;
|
119 |
+
}
|
120 |
+
|
121 |
+
/**
|
122 |
+
* Process content.
|
123 |
+
*
|
124 |
+
* @param string $content
|
125 |
+
* @param array $cache
|
126 |
+
* @param array $to_cache
|
127 |
+
*
|
128 |
+
* @return mixed
|
129 |
+
*/
|
130 |
+
protected function process_content( $content, $cache, &$to_cache ) {
|
131 |
+
if ( ! $this->should_filter_content() ) {
|
132 |
+
// Not filtering content, return
|
133 |
+
return $content;
|
134 |
+
}
|
135 |
+
|
136 |
+
$content = $this->pre_replace_content( $content );
|
137 |
+
|
138 |
+
// Find URLs from img src
|
139 |
+
$url_pairs = $this->get_urls_from_img_src( $content, $to_cache );
|
140 |
+
$content = $this->replace_urls( $content, $url_pairs );
|
141 |
+
|
142 |
+
// Find leftover URLs
|
143 |
+
$content = $this->find_urls_and_replace( $content, $cache, $to_cache );
|
144 |
+
|
145 |
+
// Perform post processing if required
|
146 |
+
$content = $this->post_process_content( $content );
|
147 |
+
|
148 |
+
return $content;
|
149 |
+
}
|
150 |
+
|
151 |
+
/**
|
152 |
+
* Find URLs and replace.
|
153 |
+
*
|
154 |
+
* @param string $value
|
155 |
+
* @param array $cache
|
156 |
+
* @param array $to_cache
|
157 |
+
*
|
158 |
+
* @return string
|
159 |
+
*/
|
160 |
+
protected function find_urls_and_replace( $value, $cache, &$to_cache ) {
|
161 |
+
if ( ! $this->should_filter_content() ) {
|
162 |
+
// Not filtering content, return
|
163 |
+
return $value;
|
164 |
+
}
|
165 |
+
|
166 |
+
$url_pairs = $this->get_urls_from_content( $value, $cache, $to_cache );
|
167 |
+
$value = $this->replace_urls( $value, $url_pairs );
|
168 |
+
|
169 |
+
return $value;
|
170 |
+
}
|
171 |
+
|
172 |
+
/**
|
173 |
+
* Get URLs from img src.
|
174 |
+
*
|
175 |
+
* @param string $content
|
176 |
+
* @param array $to_cache
|
177 |
+
*
|
178 |
+
* @return array
|
179 |
+
*/
|
180 |
+
protected function get_urls_from_img_src( $content, &$to_cache ) {
|
181 |
+
$url_pairs = array();
|
182 |
+
|
183 |
+
if ( ! preg_match_all( '/<img [^>]+>/', $content, $matches ) || ! isset( $matches[0] ) ) {
|
184 |
+
// No img tags found, return
|
185 |
+
return $url_pairs;
|
186 |
+
}
|
187 |
+
|
188 |
+
$matches = array_unique( $matches[0] );
|
189 |
+
$attachment_ids = array();
|
190 |
+
|
191 |
+
foreach ($matches as $image) {
|
192 |
+
if ( ! preg_match( '/src=\\\?["\']+([^"\'\\\]+)/', $image, $src ) || ! isset( $src[1] ) ) {
|
193 |
+
// Can't determine URL, skip
|
194 |
+
continue;
|
195 |
+
}
|
196 |
+
|
197 |
+
$url = $src[1];
|
198 |
+
|
199 |
+
if ( ! $this->url_needs_replacing( $url ) ) {
|
200 |
+
// URL already correct, skip
|
201 |
+
continue;
|
202 |
+
}
|
203 |
+
|
204 |
+
if ( ! preg_match( '/wp-image-([0-9]+)/i', $image, $class_id ) || ! isset( $class_id[1] ) ) {
|
205 |
+
// Can't determine ID from class, skip
|
206 |
+
continue;
|
207 |
+
}
|
208 |
+
|
209 |
+
$attachment_ids[ absint( $class_id[1] ) ] = $url;
|
210 |
+
}
|
211 |
+
|
212 |
+
if ( count( $attachment_ids ) > 1 ) {
|
213 |
+
/*
|
214 |
+
* Warm object cache for use with 'get_post_meta()'.
|
215 |
+
*
|
216 |
+
* To avoid making a database call for each image, a single query
|
217 |
+
* warms the object cache with the meta information for all images.
|
218 |
+
*/
|
219 |
+
update_meta_cache( 'post', array_keys( $attachment_ids ) );
|
220 |
+
}
|
221 |
+
|
222 |
+
foreach ( $attachment_ids as $attachment_id => $url ) {
|
223 |
+
if ( ! $this->attachment_id_matches_src( $attachment_id, $url ) ) {
|
224 |
+
// Path doesn't match attachment, skip
|
225 |
+
continue;
|
226 |
+
}
|
227 |
+
|
228 |
+
$this->push_to_url_pairs( $url_pairs, $attachment_id, $url, $to_cache );
|
229 |
+
}
|
230 |
+
|
231 |
+
return $url_pairs;
|
232 |
+
}
|
233 |
+
|
234 |
+
/**
|
235 |
+
* Get URLs from content.
|
236 |
+
*
|
237 |
+
* @param string $content
|
238 |
+
* @param array $cache
|
239 |
+
* @param array $to_cache
|
240 |
+
*
|
241 |
+
* @return array
|
242 |
+
*/
|
243 |
+
protected function get_urls_from_content( $content, $cache, &$to_cache ) {
|
244 |
+
$url_pairs = array();
|
245 |
+
|
246 |
+
if ( ! preg_match_all( '/(http|https)?:?\/\/[^"\'\s<>\\\]*/', $content, $matches ) || ! isset( $matches[0] ) ) {
|
247 |
+
// No URLs found, return
|
248 |
+
return $url_pairs;
|
249 |
+
}
|
250 |
+
|
251 |
+
$matches = array_unique( $matches[0] );
|
252 |
+
|
253 |
+
foreach ($matches as $url) {
|
254 |
+
if ( ! $this->url_needs_replacing( $url ) ) {
|
255 |
+
// URL already correct, skip
|
256 |
+
continue;
|
257 |
+
}
|
258 |
+
|
259 |
+
$parts = parse_url( $url );
|
260 |
+
|
261 |
+
if ( ! isset( $parts['path'] ) ) {
|
262 |
+
// URL doesn't have a path, continue
|
263 |
+
continue;
|
264 |
+
}
|
265 |
+
|
266 |
+
$info = pathinfo( $parts['path'] );
|
267 |
+
|
268 |
+
if ( ! isset( $info['extension'] ) ) {
|
269 |
+
// URL doesn't have a file extension, continue
|
270 |
+
continue;
|
271 |
+
}
|
272 |
+
|
273 |
+
$attachment_id = null;
|
274 |
+
|
275 |
+
if ( isset( $cache[ $this->as3cf->maybe_remove_query_string( $url ) ] ) ) {
|
276 |
+
$cached_id = $cache[ $this->as3cf->maybe_remove_query_string( $url ) ];
|
277 |
+
|
278 |
+
if ( $this->is_failure( $cached_id ) ) {
|
279 |
+
// Attachment ID failure, continue
|
280 |
+
continue;
|
281 |
+
}
|
282 |
+
|
283 |
+
// Attachment ID cached
|
284 |
+
$attachment_id = $cached_id;
|
285 |
+
}
|
286 |
+
|
287 |
+
if ( is_null( $attachment_id ) || is_array( $attachment_id ) ) {
|
288 |
+
// Attachment ID not cached
|
289 |
+
$attachment_id = $this->get_attachment_id_from_url( $url );
|
290 |
+
}
|
291 |
+
|
292 |
+
if ( ! $attachment_id ) {
|
293 |
+
// Can't determine attachment ID, continue
|
294 |
+
$this->url_cache_failure( $url, $to_cache );
|
295 |
+
|
296 |
+
continue;
|
297 |
+
}
|
298 |
+
|
299 |
+
$this->push_to_url_pairs( $url_pairs, $attachment_id, $url, $to_cache );
|
300 |
+
}
|
301 |
+
|
302 |
+
return $url_pairs;
|
303 |
+
}
|
304 |
+
|
305 |
+
/**
|
306 |
+
* Is failure?
|
307 |
+
*
|
308 |
+
* @param mixed $value
|
309 |
+
*
|
310 |
+
* @return bool
|
311 |
+
*/
|
312 |
+
protected function is_failure( $value ) {
|
313 |
+
if ( ! is_array( $value ) || ! isset( $value['timestamp'] ) ) {
|
314 |
+
return false;
|
315 |
+
}
|
316 |
+
|
317 |
+
$expires = time() - ( 15 * MINUTE_IN_SECONDS );
|
318 |
+
|
319 |
+
if ( $expires >= $value['timestamp'] ) {
|
320 |
+
return false;
|
321 |
+
}
|
322 |
+
|
323 |
+
return true;
|
324 |
+
}
|
325 |
+
|
326 |
+
/**
|
327 |
+
* Does attachment ID match src?
|
328 |
+
*
|
329 |
+
* @param int $attachment_id
|
330 |
+
* @param string $url
|
331 |
+
*
|
332 |
+
* @return bool
|
333 |
+
*/
|
334 |
+
protected function attachment_id_matches_src( $attachment_id, $url ) {
|
335 |
+
$base_urls = array();
|
336 |
+
$meta = get_post_meta( $attachment_id, '_wp_attachment_metadata', true );
|
337 |
+
|
338 |
+
if ( ! isset( $meta['sizes'] ) ) {
|
339 |
+
// No sizes found, return
|
340 |
+
return false;
|
341 |
+
}
|
342 |
+
|
343 |
+
$base_url = $this->as3cf->remove_scheme( $this->as3cf->maybe_remove_query_string( $this->get_base_url( $attachment_id ) ) );
|
344 |
+
$basename = wp_basename( $base_url );
|
345 |
+
$url = $this->as3cf->remove_scheme( $this->as3cf->maybe_remove_query_string( $url ) );
|
346 |
+
|
347 |
+
// Add full size URL
|
348 |
+
$base_urls[] = $base_url;
|
349 |
+
|
350 |
+
// Add additional image size URLs
|
351 |
+
foreach ( $meta['sizes'] as $size ) {
|
352 |
+
$base_urls[] = str_replace( $basename, $size['file'], $base_url );
|
353 |
+
}
|
354 |
+
|
355 |
+
if ( in_array( $this->as3cf->remove_scheme( $url ), $base_urls ) ) {
|
356 |
+
// Match found, return true
|
357 |
+
return true;
|
358 |
+
}
|
359 |
+
|
360 |
+
return false;
|
361 |
+
}
|
362 |
+
|
363 |
+
/**
|
364 |
+
* Push to URL pairs.
|
365 |
+
*
|
366 |
+
* @param array $url_pairs
|
367 |
+
* @param int $attachment_id
|
368 |
+
* @param string $find
|
369 |
+
* @param array $to_cache
|
370 |
+
*/
|
371 |
+
protected function push_to_url_pairs( &$url_pairs, $attachment_id, $find, &$to_cache ) {
|
372 |
+
$replace_full = $this->get_url( $attachment_id );
|
373 |
+
|
374 |
+
if ( ! $replace_full ) {
|
375 |
+
// Replacement URL can't be found, return
|
376 |
+
return;
|
377 |
+
}
|
378 |
+
|
379 |
+
$size = $this->get_size_string_from_url( $attachment_id, $find );
|
380 |
+
$replace_size = $this->get_url( $attachment_id, $size );
|
381 |
+
$parts = parse_url( $find );
|
382 |
+
|
383 |
+
if ( ! isset( $parts['scheme'] ) ) {
|
384 |
+
$replace_full = $this->as3cf->remove_scheme( $replace_full );
|
385 |
+
$replace_size = $this->as3cf->remove_scheme( $replace_size );
|
386 |
+
}
|
387 |
+
|
388 |
+
$find_full = $this->as3cf->remove_size_from_filename( $find );
|
389 |
+
$find_full = $this->normalize_find_value( $this->as3cf->maybe_remove_query_string( $find_full ) );
|
390 |
+
$find_size = $this->normalize_find_value( $this->as3cf->maybe_remove_query_string( $find ) );
|
391 |
+
|
392 |
+
// Find and replace full version
|
393 |
+
$url_pairs[ $find_full ] = $replace_full;
|
394 |
+
$to_cache[ $find_full ] = $attachment_id;
|
395 |
+
|
396 |
+
// Find and replace sized version
|
397 |
+
if ( wp_basename( $find_full ) !== wp_basename( $find_size ) ) {
|
398 |
+
$url_pairs[ $find_size ] = $replace_size;
|
399 |
+
$to_cache[ $find_size ] = $attachment_id;
|
400 |
+
}
|
401 |
+
|
402 |
+
// Prime cache, when filtering the opposite way
|
403 |
+
$replace_full = $this->as3cf->maybe_remove_query_string( $replace_full );
|
404 |
+
$replace_size = $this->as3cf->maybe_remove_query_string( $replace_size );
|
405 |
+
|
406 |
+
$to_cache[ $this->normalize_find_value( $replace_full ) ] = $attachment_id;
|
407 |
+
$to_cache[ $this->normalize_find_value( $replace_size ) ] = $attachment_id;
|
408 |
+
}
|
409 |
+
|
410 |
+
/**
|
411 |
+
* Get size string from URL.
|
412 |
+
*
|
413 |
+
* @param int $attachment_id
|
414 |
+
* @param string $url
|
415 |
+
*
|
416 |
+
* @return null|string
|
417 |
+
*/
|
418 |
+
protected function get_size_string_from_url( $attachment_id, $url ) {
|
419 |
+
$meta = get_post_meta( $attachment_id, '_wp_attachment_metadata', true );
|
420 |
+
$basename = wp_basename( $this->as3cf->maybe_remove_query_string( $url ) );
|
421 |
+
|
422 |
+
if ( empty( $meta['sizes'] ) ) {
|
423 |
+
// No alternative sizes available, return
|
424 |
+
return null;
|
425 |
+
}
|
426 |
+
|
427 |
+
foreach ( $meta['sizes'] as $size => $file ) {
|
428 |
+
if ( $basename === $file['file'] ) {
|
429 |
+
return $size;
|
430 |
+
}
|
431 |
+
}
|
432 |
+
|
433 |
+
return null;
|
434 |
+
}
|
435 |
+
|
436 |
+
/**
|
437 |
+
* URL cache failure.
|
438 |
+
*
|
439 |
+
* @param string $url
|
440 |
+
* @param array $to_cache
|
441 |
+
*/
|
442 |
+
protected function url_cache_failure( $url, &$to_cache ) {
|
443 |
+
$full = $this->as3cf->remove_size_from_filename( $url );
|
444 |
+
$failure = array(
|
445 |
+
'timestamp' => time(),
|
446 |
+
);
|
447 |
+
|
448 |
+
$to_cache[ $full ] = $failure;
|
449 |
+
|
450 |
+
if ( $full !== $url ) {
|
451 |
+
$to_cache[ $url ] = $failure;
|
452 |
+
}
|
453 |
+
}
|
454 |
+
|
455 |
+
/**
|
456 |
+
* Replace URLs.
|
457 |
+
*
|
458 |
+
* @param string $content
|
459 |
+
* @param array $url_pairs
|
460 |
+
*
|
461 |
+
* @return string
|
462 |
+
*/
|
463 |
+
protected function replace_urls( $content, $url_pairs ) {
|
464 |
+
if ( empty( $url_pairs ) ) {
|
465 |
+
// No URLs to replace return
|
466 |
+
return $content;
|
467 |
+
}
|
468 |
+
|
469 |
+
foreach ( $url_pairs as $find => $replace ) {
|
470 |
+
$replace = $this->normalize_replace_value( $replace );
|
471 |
+
$content = str_replace( $find, $replace, $content );
|
472 |
+
}
|
473 |
+
|
474 |
+
return $content;
|
475 |
+
}
|
476 |
+
|
477 |
+
/**
|
478 |
+
* Get post cache
|
479 |
+
*
|
480 |
+
* @return array
|
481 |
+
*/
|
482 |
+
protected function get_post_cache() {
|
483 |
+
global $post;
|
484 |
+
|
485 |
+
if ( ! isset( $post->ID ) ) {
|
486 |
+
// Post ID not found, return empty cache
|
487 |
+
return array();
|
488 |
+
}
|
489 |
+
|
490 |
+
$cache = get_post_meta( $post->ID, 'amazonS3_cache', true );
|
491 |
+
|
492 |
+
if ( empty( $cache ) ) {
|
493 |
+
$cache = array();
|
494 |
+
}
|
495 |
+
|
496 |
+
return $cache;
|
497 |
+
}
|
498 |
+
|
499 |
+
/**
|
500 |
+
* Maybe update post cache
|
501 |
+
*
|
502 |
+
* @param array $to_cache
|
503 |
+
*/
|
504 |
+
protected function maybe_update_post_cache( $to_cache ) {
|
505 |
+
global $post;
|
506 |
+
|
507 |
+
if ( ! isset( $post->ID ) || empty( $to_cache ) ) {
|
508 |
+
return;
|
509 |
+
}
|
510 |
+
|
511 |
+
$urls = array_merge( $this->get_post_cache(), $to_cache );
|
512 |
+
|
513 |
+
update_post_meta( $post->ID, 'amazonS3_cache', $urls );
|
514 |
+
}
|
515 |
+
|
516 |
+
/**
|
517 |
+
* Get option cache.
|
518 |
+
*
|
519 |
+
* @return array
|
520 |
+
*/
|
521 |
+
protected function get_option_cache() {
|
522 |
+
return get_option( 'amazonS3_cache', array() );
|
523 |
+
}
|
524 |
+
|
525 |
+
/**
|
526 |
+
* Maybe update option cache.
|
527 |
+
*
|
528 |
+
* @param array $to_cache
|
529 |
+
*/
|
530 |
+
protected function maybe_update_option_cache( $to_cache ) {
|
531 |
+
if ( empty( $to_cache ) ) {
|
532 |
+
return;
|
533 |
+
}
|
534 |
+
|
535 |
+
$urls = array_merge( $this->get_option_cache(), $to_cache );
|
536 |
+
|
537 |
+
update_option( 'amazonS3_cache', $urls );
|
538 |
+
}
|
539 |
+
|
540 |
+
/**
|
541 |
+
* Purge attachment from cache on delete.
|
542 |
+
*
|
543 |
+
* @param int $post_id
|
544 |
+
*/
|
545 |
+
public function purge_cache_on_attachment_delete( $post_id ) {
|
546 |
+
$this->purge_from_cache( $this->get_url( $post_id ) );
|
547 |
+
}
|
548 |
+
|
549 |
+
/**
|
550 |
+
* Purge URL from cache
|
551 |
+
*
|
552 |
+
* @param string $url
|
553 |
+
* @param bool|int $blog_id
|
554 |
+
*/
|
555 |
+
public function purge_from_cache( $url, $blog_id = false ) {
|
556 |
+
global $wpdb;
|
557 |
+
|
558 |
+
if ( false !== $blog_id ) {
|
559 |
+
$this->as3cf->switch_to_blog( $blog_id );
|
560 |
+
}
|
561 |
+
|
562 |
+
// Purge postmeta cache
|
563 |
+
$sql = $wpdb->prepare( "
|
564 |
+
DELETE FROM {$wpdb->postmeta}
|
565 |
+
WHERE meta_key = %s
|
566 |
+
AND meta_value LIKE %s;
|
567 |
+
", 'amazonS3_cache', '%"' . $url . '"%' );
|
568 |
+
|
569 |
+
$wpdb->query( $sql );
|
570 |
+
|
571 |
+
// Purge option cache
|
572 |
+
$sql = $wpdb->prepare( "
|
573 |
+
DELETE FROM {$wpdb->options}
|
574 |
+
WHERE option_name = %s
|
575 |
+
AND option_value LIKE %s;
|
576 |
+
", 'amazonS3_cache', '%"' . $url . '"%' );
|
577 |
+
|
578 |
+
$wpdb->query( $sql );
|
579 |
+
|
580 |
+
if ( false !== $blog_id ) {
|
581 |
+
$this->as3cf->restore_current_blog();
|
582 |
+
}
|
583 |
+
}
|
584 |
+
|
585 |
+
/**
|
586 |
+
* Should filter content.
|
587 |
+
*
|
588 |
+
* @return bool
|
589 |
+
*/
|
590 |
+
protected function should_filter_content() {
|
591 |
+
if ( ! $this->as3cf->is_plugin_setup() || ! $this->as3cf->get_setting( 'serve-from-s3' ) ) {
|
592 |
+
return false;
|
593 |
+
}
|
594 |
+
|
595 |
+
return true;
|
596 |
+
}
|
597 |
+
|
598 |
+
/**
|
599 |
+
* Remove AWS query strings.
|
600 |
+
*
|
601 |
+
* @param string $content
|
602 |
+
*
|
603 |
+
* @return string
|
604 |
+
*/
|
605 |
+
protected function remove_aws_query_strings( $content ) {
|
606 |
+
if ( ! preg_match_all( '/\?[^\s"<\?]*X-Amz-Algorithm[^\s"<\?]+/', $content, $matches ) || ! isset( $matches[0] ) ) {
|
607 |
+
// No query strings found, return
|
608 |
+
return $content;
|
609 |
+
}
|
610 |
+
|
611 |
+
$matches = array_unique( $matches[0] );
|
612 |
+
|
613 |
+
foreach ( $matches as $match ) {
|
614 |
+
$content = str_replace( $match, '', $content );
|
615 |
+
}
|
616 |
+
|
617 |
+
return $content;
|
618 |
+
}
|
619 |
+
|
620 |
+
/**
|
621 |
+
* Does URL need replacing?
|
622 |
+
*
|
623 |
+
* @param string $url
|
624 |
+
*
|
625 |
+
* @return bool
|
626 |
+
*/
|
627 |
+
abstract protected function url_needs_replacing( $url );
|
628 |
+
|
629 |
+
/**
|
630 |
+
* Get URL.
|
631 |
+
*
|
632 |
+
* @param int $attachment_id
|
633 |
+
* @param null|string $size
|
634 |
+
*
|
635 |
+
* @return bool|string
|
636 |
+
*/
|
637 |
+
abstract protected function get_url( $attachment_id, $size = null );
|
638 |
+
|
639 |
+
/**
|
640 |
+
* Get base URL.
|
641 |
+
*
|
642 |
+
* @param int $attachment_id
|
643 |
+
*
|
644 |
+
* @return string|false
|
645 |
+
*/
|
646 |
+
abstract protected function get_base_url( $attachment_id );
|
647 |
+
|
648 |
+
/**
|
649 |
+
* Get attachment ID from URL.
|
650 |
+
*
|
651 |
+
* @param string $url
|
652 |
+
*
|
653 |
+
* @return bool|int
|
654 |
+
*/
|
655 |
+
abstract protected function get_attachment_id_from_url( $url );
|
656 |
+
|
657 |
+
/**
|
658 |
+
* Normalize find value.
|
659 |
+
*
|
660 |
+
* @param string $url
|
661 |
+
*
|
662 |
+
* @return string
|
663 |
+
*/
|
664 |
+
abstract protected function normalize_find_value( $url );
|
665 |
+
|
666 |
+
/**
|
667 |
+
* Normalize replace value.
|
668 |
+
*
|
669 |
+
* @param string $url
|
670 |
+
*
|
671 |
+
* @return string
|
672 |
+
*/
|
673 |
+
abstract protected function normalize_replace_value( $url );
|
674 |
+
|
675 |
+
/**
|
676 |
+
* Post process content.
|
677 |
+
*
|
678 |
+
* @param string $content
|
679 |
+
*
|
680 |
+
* @return string
|
681 |
+
*/
|
682 |
+
abstract protected function post_process_content( $content );
|
683 |
+
|
684 |
+
/**
|
685 |
+
* Pre replace content.
|
686 |
+
*
|
687 |
+
* @param string $content
|
688 |
+
*
|
689 |
+
* @return string
|
690 |
+
*/
|
691 |
+
abstract protected function pre_replace_content( $content );
|
692 |
+
}
|
classes/as3cf-notices.php
CHANGED
@@ -12,24 +12,18 @@ class AS3CF_Notices {
|
|
12 |
*/
|
13 |
private $as3cf;
|
14 |
|
15 |
-
/**
|
16 |
-
* @var string
|
17 |
-
*/
|
18 |
-
private $plugin_file_path;
|
19 |
-
|
20 |
/**
|
21 |
* Make this class a singleton
|
22 |
*
|
23 |
* Use this instead of __construct()
|
24 |
*
|
25 |
* @param Amazon_S3_And_CloudFront $as3cf
|
26 |
-
* @param string $plugin_file_path
|
27 |
*
|
28 |
* @return AS3CF_Notices
|
29 |
*/
|
30 |
-
public static function get_instance( $as3cf
|
31 |
if ( ! isset( static::$instance ) ) {
|
32 |
-
static::$instance = new static( $as3cf
|
33 |
}
|
34 |
|
35 |
return static::$instance;
|
@@ -39,11 +33,9 @@ class AS3CF_Notices {
|
|
39 |
* Constructor
|
40 |
*
|
41 |
* @param Amazon_S3_And_CloudFront $as3cf
|
42 |
-
* @param string $plugin_file_path
|
43 |
*/
|
44 |
-
protected function __construct( $as3cf
|
45 |
-
$this->as3cf
|
46 |
-
$this->plugin_file_path = $plugin_file_path;
|
47 |
|
48 |
add_action( 'admin_notices', array( $this, 'admin_notices' ) );
|
49 |
add_action( 'network_admin_notices', array( $this, 'admin_notices' ) );
|
@@ -83,6 +75,7 @@ class AS3CF_Notices {
|
|
83 |
'show_callback' => false, // Callback to display extra info on notices. Passing a callback automatically handles show/hide toggle.
|
84 |
'callback_args' => array(), // Arguments to pass to the callback.
|
85 |
'lock_key' => '', // If lock key set, do not show message until lock released.
|
|
|
86 |
);
|
87 |
|
88 |
$notice = array_intersect_key( array_merge( $defaults, $args ), $defaults );
|
@@ -386,6 +379,10 @@ class AS3CF_Notices {
|
|
386 |
$notice['type'] = 'notice-info';
|
387 |
}
|
388 |
|
|
|
|
|
|
|
|
|
389 |
$this->as3cf->render_view( 'notice', $notice );
|
390 |
|
391 |
if ( $notice['flash'] ) {
|
@@ -430,10 +427,10 @@ class AS3CF_Notices {
|
|
430 |
$suffix = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '' : '.min';
|
431 |
|
432 |
// Enqueue notice.css & notice.js globally as some notices can be shown & dismissed on any admin page.
|
433 |
-
$src = plugins_url( 'assets/css/notice.css', $this->
|
434 |
wp_enqueue_style( 'as3cf-notice', $src, array(), $version );
|
435 |
-
|
436 |
-
$src = plugins_url( 'assets/js/notice' . $suffix . '.js', $this->
|
437 |
wp_enqueue_script( 'as3cf-notice', $src, array( 'jquery' ), $version, true );
|
438 |
|
439 |
wp_localize_script( 'as3cf-notice', 'as3cf_notice', array(
|
12 |
*/
|
13 |
private $as3cf;
|
14 |
|
|
|
|
|
|
|
|
|
|
|
15 |
/**
|
16 |
* Make this class a singleton
|
17 |
*
|
18 |
* Use this instead of __construct()
|
19 |
*
|
20 |
* @param Amazon_S3_And_CloudFront $as3cf
|
|
|
21 |
*
|
22 |
* @return AS3CF_Notices
|
23 |
*/
|
24 |
+
public static function get_instance( $as3cf ) {
|
25 |
if ( ! isset( static::$instance ) ) {
|
26 |
+
static::$instance = new static( $as3cf );
|
27 |
}
|
28 |
|
29 |
return static::$instance;
|
33 |
* Constructor
|
34 |
*
|
35 |
* @param Amazon_S3_And_CloudFront $as3cf
|
|
|
36 |
*/
|
37 |
+
protected function __construct( $as3cf ) {
|
38 |
+
$this->as3cf = $as3cf;
|
|
|
39 |
|
40 |
add_action( 'admin_notices', array( $this, 'admin_notices' ) );
|
41 |
add_action( 'network_admin_notices', array( $this, 'admin_notices' ) );
|
75 |
'show_callback' => false, // Callback to display extra info on notices. Passing a callback automatically handles show/hide toggle.
|
76 |
'callback_args' => array(), // Arguments to pass to the callback.
|
77 |
'lock_key' => '', // If lock key set, do not show message until lock released.
|
78 |
+
'pre_render_callback' => false, // Callback to call before notice render.
|
79 |
);
|
80 |
|
81 |
$notice = array_intersect_key( array_merge( $defaults, $args ), $defaults );
|
379 |
$notice['type'] = 'notice-info';
|
380 |
}
|
381 |
|
382 |
+
if ( ! empty( $notice['pre_render_callback'] ) && is_callable( $notice['pre_render_callback'] ) ) {
|
383 |
+
call_user_func( $notice['pre_render_callback'] );
|
384 |
+
}
|
385 |
+
|
386 |
$this->as3cf->render_view( 'notice', $notice );
|
387 |
|
388 |
if ( $notice['flash'] ) {
|
427 |
$suffix = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '' : '.min';
|
428 |
|
429 |
// Enqueue notice.css & notice.js globally as some notices can be shown & dismissed on any admin page.
|
430 |
+
$src = plugins_url( 'assets/css/notice.css', $this->as3cf->get_plugin_file_path() );
|
431 |
wp_enqueue_style( 'as3cf-notice', $src, array(), $version );
|
432 |
+
|
433 |
+
$src = plugins_url( 'assets/js/notice' . $suffix . '.js', $this->as3cf->get_plugin_file_path() );
|
434 |
wp_enqueue_script( 'as3cf-notice', $src, array( 'jquery' ), $version, true );
|
435 |
|
436 |
wp_localize_script( 'as3cf-notice', 'as3cf_notice', array(
|
classes/as3cf-plugin-compatibility.php
CHANGED
@@ -61,16 +61,6 @@ class AS3CF_Plugin_Compatibility {
|
|
61 |
* Responsive Images WP 4.4
|
62 |
*/
|
63 |
add_filter( 'wp_calculate_image_srcset', array( $this, 'wp_calculate_image_srcset' ), 10, 5 );
|
64 |
-
|
65 |
-
global $wp_version;
|
66 |
-
if ( 0 === version_compare( $wp_version, '4.4' ) ) {
|
67 |
-
// Hot fix for 4.4
|
68 |
-
add_filter( 'the_content', array( $this, 'wp_make_content_images_responsive' ), 11 );
|
69 |
-
}
|
70 |
-
|
71 |
-
/*
|
72 |
-
* Responsive Images WP 4.4.1+
|
73 |
-
*/
|
74 |
add_filter( 'wp_calculate_image_srcset_meta', array( $this, 'wp_calculate_image_srcset_meta' ), 10, 4 );
|
75 |
|
76 |
if ( $this->as3cf->is_plugin_setup() ) {
|
@@ -92,7 +82,7 @@ class AS3CF_Plugin_Compatibility {
|
|
92 |
* Legacy filter
|
93 |
* 'as3cf_get_attached_file_copy_back_to_local'
|
94 |
*/
|
95 |
-
add_filter( 'as3cf_get_attached_file', array( $this, 'legacy_copy_back_to_local'), 10, 4 );
|
96 |
|
97 |
/*
|
98 |
* WP_Image_Editor
|
@@ -146,7 +136,7 @@ class AS3CF_Plugin_Compatibility {
|
|
146 |
return $addons_to_install;
|
147 |
}
|
148 |
|
149 |
-
foreach( $addons as $addon_slug => $addon ) {
|
150 |
if ( file_exists( WP_PLUGIN_DIR . '/' . $addon_slug . '/' . $addon_slug . '.php' ) ) {
|
151 |
// Addon already installed, ignore.
|
152 |
continue;
|
@@ -183,7 +173,7 @@ class AS3CF_Plugin_Compatibility {
|
|
183 |
}
|
184 |
|
185 |
global $as3cf_compat_check;
|
186 |
-
if ( ! $as3cf_compat_check->check_capabilities() ){
|
187 |
// User can't install plugins anyway, bail.
|
188 |
return;
|
189 |
}
|
@@ -208,7 +198,7 @@ class AS3CF_Plugin_Compatibility {
|
|
208 |
$support_email = 'nom@deliciousbrains.com';
|
209 |
$support_link = sprintf( '<a href="mailto:%1$s">%1$s</a>', $support_email );
|
210 |
|
211 |
-
$notice_addons_text .= '<p>' . sprintf( __( "You will need to purchase a license to get access to these addons. If you're having trouble determining whether or not you need the addons, send an email to %s.", 'amazon-s3-and-cloudfront' ), $support_link ). '</p>';
|
212 |
$notice_addons_text .= sprintf( '<p><a href="%s" class="button button-large">%s</a></p>', 'https://deliciousbrains.com/wp-offload-s3/pricing/', __( 'View Licenses', 'amazon-s3-and-cloudfront' ) );
|
213 |
|
214 |
$notice_addons_text = apply_filters( 'wpos3_compat_addons_notice', $notice_addons_text, $addons_to_install );
|
@@ -351,9 +341,9 @@ class AS3CF_Plugin_Compatibility {
|
|
351 |
* Check the current request is a specific one based on action and
|
352 |
* optional context
|
353 |
*
|
354 |
-
* @param string
|
355 |
-
* @param bool
|
356 |
-
* @param null|string $context_key
|
357 |
*
|
358 |
* @return bool
|
359 |
*/
|
@@ -375,9 +365,14 @@ class AS3CF_Plugin_Compatibility {
|
|
375 |
|
376 |
$context_check = true;
|
377 |
if ( ! is_null( $context_key ) ) {
|
378 |
-
$global
|
379 |
-
$context
|
380 |
-
|
|
|
|
|
|
|
|
|
|
|
381 |
}
|
382 |
|
383 |
return ( $action_key === sanitize_key( $action ) && $context_check );
|
@@ -533,10 +528,12 @@ class AS3CF_Plugin_Compatibility {
|
|
533 |
* @return bool
|
534 |
*/
|
535 |
protected function is_customizer_crop_action() {
|
536 |
-
$header_crop
|
537 |
-
$identity_crop = $this->maybe_process_on_action( 'crop-image', true, 'site-icon' );
|
538 |
|
539 |
-
|
|
|
|
|
|
|
540 |
// Not doing a Customizer action
|
541 |
return false;
|
542 |
}
|
@@ -671,13 +668,11 @@ class AS3CF_Plugin_Compatibility {
|
|
671 |
}
|
672 |
|
673 |
try {
|
674 |
-
$this->as3cf->get_s3client( $s3_object['region'], true )->getObject(
|
675 |
-
|
676 |
-
|
677 |
-
|
678 |
-
|
679 |
-
)
|
680 |
-
);
|
681 |
} catch ( Exception $e ) {
|
682 |
AS3CF_Error::log( sprintf( __( 'There was an error attempting to download the file %s from S3: %s', 'amazon-s3-and-cloudfront' ), $s3_object['key'], $e->getMessage() ) );
|
683 |
|
@@ -762,47 +757,6 @@ class AS3CF_Plugin_Compatibility {
|
|
762 |
return $this->prepare_stream_wrapper_file( $s3_object['bucket'], $s3_object['region'], $s3_object['key'] );
|
763 |
}
|
764 |
|
765 |
-
/**
|
766 |
-
* Filters 'img' elements in post content to add 'srcset' and 'sizes' attributes for S3 URLs.
|
767 |
-
*
|
768 |
-
* @param string $content The raw post content to be filtered.
|
769 |
-
*
|
770 |
-
* @return string Converted content with 'srcset' and 'sizes' attributes added to images.
|
771 |
-
*/
|
772 |
-
public function wp_make_content_images_responsive( $content ) {
|
773 |
-
if ( ! preg_match_all( '/<img [^>]+>/', $content, $matches ) ) {
|
774 |
-
return $content;
|
775 |
-
}
|
776 |
-
|
777 |
-
$selected_images = $attachment_ids = array();
|
778 |
-
|
779 |
-
foreach( $matches[0] as $image ) {
|
780 |
-
if ( false === strpos( $image, ' srcset=' ) && preg_match( '/wp-image-([0-9]+)/i', $image, $class_id ) &&
|
781 |
-
( $attachment_id = absint( $class_id[1] ) ) ) {
|
782 |
-
|
783 |
-
/*
|
784 |
-
* If exactly the same image tag is used more than once, overwrite it.
|
785 |
-
* All identical tags will be replaced later with 'str_replace()'.
|
786 |
-
*/
|
787 |
-
$selected_images[ $image ] = $attachment_id;
|
788 |
-
// Overwrite the ID when the same image is included more than once.
|
789 |
-
$attachment_ids[ $attachment_id ] = true;
|
790 |
-
}
|
791 |
-
}
|
792 |
-
|
793 |
-
foreach ( $selected_images as $image => $attachment_id ) {
|
794 |
-
if ( ! ( $s3object = $this->as3cf->is_attachment_served_by_s3( $attachment_id ) ) ) {
|
795 |
-
// Attachment not uploaded to S3, abort
|
796 |
-
continue;
|
797 |
-
}
|
798 |
-
|
799 |
-
$image_meta = get_post_meta( $attachment_id, '_wp_attachment_metadata', true );
|
800 |
-
$content = str_replace( $image, $this->wp_image_add_srcset_and_sizes( $image, $image_meta, $attachment_id ), $content );
|
801 |
-
}
|
802 |
-
|
803 |
-
return $content;
|
804 |
-
}
|
805 |
-
|
806 |
/**
|
807 |
* Adds 'srcset' and 'sizes' attributes to an existing S3 'img' element.
|
808 |
*
|
@@ -818,7 +772,7 @@ class AS3CF_Plugin_Compatibility {
|
|
818 |
return $image;
|
819 |
}
|
820 |
|
821 |
-
$image_src
|
822 |
list( $image_src ) = explode( '?', $image_src );
|
823 |
|
824 |
// Return early if we couldn't get the image source.
|
@@ -827,13 +781,12 @@ class AS3CF_Plugin_Compatibility {
|
|
827 |
}
|
828 |
|
829 |
// Bail early if an image has been inserted and later edited.
|
830 |
-
if ( preg_match( '/-e[0-9]{13}/', $image_meta['file'], $img_edit_hash ) &&
|
831 |
-
strpos( wp_basename( $image_src ), $img_edit_hash[0] ) === false ) {
|
832 |
|
833 |
return $image;
|
834 |
}
|
835 |
|
836 |
-
$width = preg_match( '/ width="([0-9]+)"/',
|
837 |
$height = preg_match( '/ height="([0-9]+)"/', $image, $match_height ) ? (int) $match_height[1] : 0;
|
838 |
|
839 |
if ( ! $width || ! $height ) {
|
@@ -847,7 +800,7 @@ class AS3CF_Plugin_Compatibility {
|
|
847 |
$width = (int) $image_meta['width'];
|
848 |
$height = (int) $image_meta['height'];
|
849 |
} else {
|
850 |
-
foreach( $image_meta['sizes'] as $image_size_data ) {
|
851 |
if ( $image_filename === $image_size_data['file'] ) {
|
852 |
$width = (int) $image_size_data['width'];
|
853 |
$height = (int) $image_size_data['height'];
|
@@ -905,7 +858,7 @@ class AS3CF_Plugin_Compatibility {
|
|
905 |
return $image_meta;
|
906 |
}
|
907 |
|
908 |
-
if ( false !== strpos( $image_src, $image_meta['file']
|
909 |
// Path matches URL, no need to change
|
910 |
return $image_meta;
|
911 |
}
|
@@ -923,8 +876,18 @@ class AS3CF_Plugin_Compatibility {
|
|
923 |
}
|
924 |
|
925 |
// Strip the meta file prefix so the just the filename will always match
|
926 |
-
// the S3 URL regardless of different prefixes for the offloaded file
|
927 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
928 |
|
929 |
return $image_meta;
|
930 |
}
|
@@ -957,6 +920,7 @@ class AS3CF_Plugin_Compatibility {
|
|
957 |
$s3_url = $this->as3cf->get_attachment_s3_url( $attachment_id, $s3object, null, $size, $image_meta );
|
958 |
|
959 |
if ( false === $s3_url || is_wp_error( $s3_url ) ) {
|
|
|
960 |
continue;
|
961 |
}
|
962 |
|
@@ -984,4 +948,4 @@ class AS3CF_Plugin_Compatibility {
|
|
984 |
|
985 |
return null;
|
986 |
}
|
987 |
-
}
|
61 |
* Responsive Images WP 4.4
|
62 |
*/
|
63 |
add_filter( 'wp_calculate_image_srcset', array( $this, 'wp_calculate_image_srcset' ), 10, 5 );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
64 |
add_filter( 'wp_calculate_image_srcset_meta', array( $this, 'wp_calculate_image_srcset_meta' ), 10, 4 );
|
65 |
|
66 |
if ( $this->as3cf->is_plugin_setup() ) {
|
82 |
* Legacy filter
|
83 |
* 'as3cf_get_attached_file_copy_back_to_local'
|
84 |
*/
|
85 |
+
add_filter( 'as3cf_get_attached_file', array( $this, 'legacy_copy_back_to_local' ), 10, 4 );
|
86 |
|
87 |
/*
|
88 |
* WP_Image_Editor
|
136 |
return $addons_to_install;
|
137 |
}
|
138 |
|
139 |
+
foreach ( $addons as $addon_slug => $addon ) {
|
140 |
if ( file_exists( WP_PLUGIN_DIR . '/' . $addon_slug . '/' . $addon_slug . '.php' ) ) {
|
141 |
// Addon already installed, ignore.
|
142 |
continue;
|
173 |
}
|
174 |
|
175 |
global $as3cf_compat_check;
|
176 |
+
if ( ! $as3cf_compat_check->check_capabilities() ) {
|
177 |
// User can't install plugins anyway, bail.
|
178 |
return;
|
179 |
}
|
198 |
$support_email = 'nom@deliciousbrains.com';
|
199 |
$support_link = sprintf( '<a href="mailto:%1$s">%1$s</a>', $support_email );
|
200 |
|
201 |
+
$notice_addons_text .= '<p>' . sprintf( __( "You will need to purchase a license to get access to these addons. If you're having trouble determining whether or not you need the addons, send an email to %s.", 'amazon-s3-and-cloudfront' ), $support_link ) . '</p>';
|
202 |
$notice_addons_text .= sprintf( '<p><a href="%s" class="button button-large">%s</a></p>', 'https://deliciousbrains.com/wp-offload-s3/pricing/', __( 'View Licenses', 'amazon-s3-and-cloudfront' ) );
|
203 |
|
204 |
$notice_addons_text = apply_filters( 'wpos3_compat_addons_notice', $notice_addons_text, $addons_to_install );
|
341 |
* Check the current request is a specific one based on action and
|
342 |
* optional context
|
343 |
*
|
344 |
+
* @param string $action_key
|
345 |
+
* @param bool $ajax
|
346 |
+
* @param null|string|array $context_key
|
347 |
*
|
348 |
* @return bool
|
349 |
*/
|
365 |
|
366 |
$context_check = true;
|
367 |
if ( ! is_null( $context_key ) ) {
|
368 |
+
$global = constant( 'INPUT_' . $var_type );
|
369 |
+
$context = $this->as3cf->filter_input( 'context', $global );
|
370 |
+
|
371 |
+
if ( is_array( $context_key ) ) {
|
372 |
+
$context_check = in_array( $context, $context_key );
|
373 |
+
} else {
|
374 |
+
$context_check = ( $context_key === $context );
|
375 |
+
}
|
376 |
}
|
377 |
|
378 |
return ( $action_key === sanitize_key( $action ) && $context_check );
|
528 |
* @return bool
|
529 |
*/
|
530 |
protected function is_customizer_crop_action() {
|
531 |
+
$header_crop = $this->maybe_process_on_action( 'custom-header-crop', true );
|
|
|
532 |
|
533 |
+
$context = array( 'site-icon', 'custom_logo' );
|
534 |
+
$image_crop = $this->maybe_process_on_action( 'crop-image', true, $context );
|
535 |
+
|
536 |
+
if ( ! $header_crop && ! $image_crop ) {
|
537 |
// Not doing a Customizer action
|
538 |
return false;
|
539 |
}
|
668 |
}
|
669 |
|
670 |
try {
|
671 |
+
$this->as3cf->get_s3client( $s3_object['region'], true )->getObject( array(
|
672 |
+
'Bucket' => $s3_object['bucket'],
|
673 |
+
'Key' => $s3_object['key'],
|
674 |
+
'SaveAs' => $file,
|
675 |
+
) );
|
|
|
|
|
676 |
} catch ( Exception $e ) {
|
677 |
AS3CF_Error::log( sprintf( __( 'There was an error attempting to download the file %s from S3: %s', 'amazon-s3-and-cloudfront' ), $s3_object['key'], $e->getMessage() ) );
|
678 |
|
757 |
return $this->prepare_stream_wrapper_file( $s3_object['bucket'], $s3_object['region'], $s3_object['key'] );
|
758 |
}
|
759 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
760 |
/**
|
761 |
* Adds 'srcset' and 'sizes' attributes to an existing S3 'img' element.
|
762 |
*
|
772 |
return $image;
|
773 |
}
|
774 |
|
775 |
+
$image_src = preg_match( '/src="([^"]+)"/', $image, $match_src ) ? $match_src[1] : '';
|
776 |
list( $image_src ) = explode( '?', $image_src );
|
777 |
|
778 |
// Return early if we couldn't get the image source.
|
781 |
}
|
782 |
|
783 |
// Bail early if an image has been inserted and later edited.
|
784 |
+
if ( preg_match( '/-e[0-9]{13}/', $image_meta['file'], $img_edit_hash ) && strpos( wp_basename( $image_src ), $img_edit_hash[0] ) === false ) {
|
|
|
785 |
|
786 |
return $image;
|
787 |
}
|
788 |
|
789 |
+
$width = preg_match( '/ width="([0-9]+)"/', $image, $match_width ) ? (int) $match_width[1] : 0;
|
790 |
$height = preg_match( '/ height="([0-9]+)"/', $image, $match_height ) ? (int) $match_height[1] : 0;
|
791 |
|
792 |
if ( ! $width || ! $height ) {
|
800 |
$width = (int) $image_meta['width'];
|
801 |
$height = (int) $image_meta['height'];
|
802 |
} else {
|
803 |
+
foreach ( $image_meta['sizes'] as $image_size_data ) {
|
804 |
if ( $image_filename === $image_size_data['file'] ) {
|
805 |
$width = (int) $image_size_data['width'];
|
806 |
$height = (int) $image_size_data['height'];
|
858 |
return $image_meta;
|
859 |
}
|
860 |
|
861 |
+
if ( false !== strpos( $image_src, $image_meta['file'] ) ) {
|
862 |
// Path matches URL, no need to change
|
863 |
return $image_meta;
|
864 |
}
|
876 |
}
|
877 |
|
878 |
// Strip the meta file prefix so the just the filename will always match
|
879 |
+
// the S3 URL regardless of different prefixes for the offloaded file.
|
880 |
+
// Also ensure filename is encoded the same way as URL.
|
881 |
+
$image_meta['file'] = rawurlencode( $image_basename );
|
882 |
+
|
883 |
+
// Ensure each size filename is encoded the same way as URL.
|
884 |
+
if ( ! empty( $image_meta['sizes'] ) ) {
|
885 |
+
$image_meta['sizes'] = array_map( function ( $size ) {
|
886 |
+
$size['file'] = rawurlencode( $size['file'] );
|
887 |
+
|
888 |
+
return $size;
|
889 |
+
}, $image_meta['sizes'] );
|
890 |
+
}
|
891 |
|
892 |
return $image_meta;
|
893 |
}
|
920 |
$s3_url = $this->as3cf->get_attachment_s3_url( $attachment_id, $s3object, null, $size, $image_meta );
|
921 |
|
922 |
if ( false === $s3_url || is_wp_error( $s3_url ) ) {
|
923 |
+
// Skip URLs not offloaded to S3
|
924 |
continue;
|
925 |
}
|
926 |
|
948 |
|
949 |
return null;
|
950 |
}
|
951 |
+
}
|
classes/as3cf-upgrade.php
CHANGED
@@ -31,17 +31,17 @@ abstract class AS3CF_Upgrade {
|
|
31 |
/**
|
32 |
* @var int
|
33 |
*/
|
34 |
-
protected $upgrade_id;
|
35 |
|
36 |
/**
|
37 |
* @var string
|
38 |
*/
|
39 |
-
protected $upgrade_name;
|
40 |
|
41 |
/**
|
42 |
* @var string 'metadata', 'attachment'
|
43 |
*/
|
44 |
-
protected $upgrade_type;
|
45 |
|
46 |
/**
|
47 |
* @var string
|
@@ -87,13 +87,13 @@ abstract class AS3CF_Upgrade {
|
|
87 |
*
|
88 |
* @param Amazon_S3_And_CloudFront $as3cf - the instance of the as3cf class
|
89 |
*/
|
90 |
-
function __construct( $as3cf ) {
|
91 |
$this->as3cf = $as3cf;
|
92 |
|
93 |
$this->cron_hook = 'as3cf_cron_update_' . $this->upgrade_name;
|
94 |
$this->cron_schedule_key = 'as3cf_update_' . $this->upgrade_name . '_interval';
|
95 |
|
96 |
-
$this->cron_interval_in_minutes = apply_filters( 'as3cf_update_' . $this->upgrade_name . '_interval',
|
97 |
$this->error_threshold = apply_filters( 'as3cf_update_' . $this->upgrade_name . '_error_threshold', 20 );
|
98 |
|
99 |
add_filter( 'cron_schedules', array( $this, 'cron_schedules' ) );
|
@@ -123,12 +123,18 @@ abstract class AS3CF_Upgrade {
|
|
123 |
return false;
|
124 |
}
|
125 |
|
|
|
|
|
|
|
|
|
|
|
126 |
// If the upgrade status is already set, then we've already initialized the upgrade
|
127 |
if ( $upgrade_status = $this->get_upgrade_status() ) {
|
128 |
if ( self::STATUS_RUNNING === $upgrade_status ) {
|
129 |
// Make sure cron job is persisted in case it has dropped
|
130 |
$this->schedule();
|
131 |
}
|
|
|
132 |
return false;
|
133 |
}
|
134 |
|
@@ -142,8 +148,8 @@ abstract class AS3CF_Upgrade {
|
|
142 |
return false;
|
143 |
}
|
144 |
|
145 |
-
// Do we actually attachments to process?
|
146 |
-
if ( 0 === $this->
|
147 |
$this->upgrade_finished();
|
148 |
|
149 |
return false;
|
@@ -153,24 +159,31 @@ abstract class AS3CF_Upgrade {
|
|
153 |
}
|
154 |
|
155 |
/**
|
|
|
|
|
156 |
* @return int
|
157 |
*/
|
158 |
-
abstract protected function
|
159 |
|
160 |
/**
|
161 |
-
*
|
162 |
-
*
|
|
|
|
|
|
|
163 |
*
|
164 |
* @return array
|
165 |
*/
|
166 |
-
abstract protected function
|
167 |
|
168 |
/**
|
169 |
-
*
|
|
|
|
|
170 |
*
|
171 |
* @return bool
|
172 |
*/
|
173 |
-
abstract protected function
|
174 |
|
175 |
/**
|
176 |
* Fire up the upgrade
|
@@ -183,9 +196,9 @@ abstract class AS3CF_Upgrade {
|
|
183 |
}
|
184 |
|
185 |
/**
|
186 |
-
* Cron
|
187 |
*/
|
188 |
-
function do_upgrade() {
|
189 |
// Check if the cron should even be running
|
190 |
if ( $this->get_saved_upgrade_id() >= $this->upgrade_id || $this->get_upgrade_status() !== self::STATUS_RUNNING ) {
|
191 |
$this->unschedule();
|
@@ -196,35 +209,32 @@ abstract class AS3CF_Upgrade {
|
|
196 |
// set the batch size limit for the query
|
197 |
$limit = apply_filters( 'as3cf_update_' . $this->upgrade_name . '_batch_size', 500 );
|
198 |
$all_limit = $limit;
|
199 |
-
|
200 |
-
// only process the loop for a certain amount of time
|
201 |
-
$minutes = $this->cron_interval_in_minutes * 60;
|
202 |
-
// smaller time limit so won't run into another instance of cron
|
203 |
-
$minutes = $minutes * 0.8;
|
204 |
-
$finish = time() + $minutes;
|
205 |
|
206 |
$session = $this->get_session();
|
207 |
|
208 |
// find the blog IDs that have been processed so we can skip them
|
209 |
$processed_blog_ids = isset( $session['processed_blog_ids'] ) ? $session['processed_blog_ids'] : array();
|
210 |
$this->error_count = isset( $session['error_count'] ) ? $session['error_count'] : 0;
|
|
|
211 |
|
212 |
// get the table prefixes for all the blogs
|
213 |
$table_prefixes = $this->as3cf->get_all_blog_table_prefixes( $processed_blog_ids );
|
214 |
|
215 |
-
$
|
216 |
-
$all_count
|
217 |
|
218 |
foreach ( $table_prefixes as $blog_id => $table_prefix ) {
|
219 |
-
$
|
220 |
-
$count
|
221 |
|
222 |
if ( 0 === $count ) {
|
223 |
-
//
|
|
|
224 |
$processed_blog_ids[] = $blog_id;
|
225 |
} else {
|
226 |
$all_count += $count;
|
227 |
-
$
|
228 |
}
|
229 |
|
230 |
if ( $all_count >= $all_limit ) {
|
@@ -241,18 +251,18 @@ abstract class AS3CF_Upgrade {
|
|
241 |
}
|
242 |
|
243 |
// loop through and update s3 meta with region
|
244 |
-
foreach ( $
|
245 |
$this->as3cf->switch_to_blog( $blog_id );
|
246 |
|
247 |
-
foreach ( $
|
248 |
if ( $this->error_count >= $this->error_threshold ) {
|
249 |
$this->upgrade_error( $session );
|
250 |
|
251 |
return;
|
252 |
}
|
253 |
|
254 |
-
// Do the actual upgrade to the
|
255 |
-
$this->
|
256 |
|
257 |
if ( time() >= $finish || $this->as3cf->memory_exceeded( 'as3cf_update_' . $this->upgrade_name . '_memory_exceeded' ) ) {
|
258 |
// Batch limits reached
|
@@ -265,6 +275,7 @@ abstract class AS3CF_Upgrade {
|
|
265 |
$this->as3cf->restore_current_blog();
|
266 |
}
|
267 |
|
|
|
268 |
$session['processed_blog_ids'] = $processed_blog_ids;
|
269 |
$session['error_count'] = $this->error_count;
|
270 |
|
@@ -274,22 +285,28 @@ abstract class AS3CF_Upgrade {
|
|
274 |
/**
|
275 |
* Adds notices about issues with upgrades allowing user to restart them
|
276 |
*/
|
277 |
-
function maybe_display_notices() {
|
278 |
-
$action_url = $this->as3cf->get_plugin_page_url( array(
|
|
|
|
|
|
|
279 |
$msg_type = 'notice-info';
|
280 |
|
281 |
switch ( $this->get_upgrade_status() ) {
|
282 |
case self::STATUS_RUNNING:
|
283 |
-
$msg =
|
284 |
$action_text = __( 'Pause Update', 'amazon-s3-and-cloudfront' );
|
285 |
-
$action_url = $this->as3cf->get_plugin_page_url( array(
|
|
|
|
|
|
|
286 |
break;
|
287 |
case self::STATUS_PAUSED:
|
288 |
-
$msg =
|
289 |
$action_text = __( 'Restart Update', 'amazon-s3-and-cloudfront' );
|
290 |
break;
|
291 |
case self::STATUS_ERROR:
|
292 |
-
$msg =
|
293 |
$action_text = __( 'Try Run It Again', 'amazon-s3-and-cloudfront' );
|
294 |
$msg_type = 'error';
|
295 |
break;
|
@@ -307,10 +324,79 @@ abstract class AS3CF_Upgrade {
|
|
307 |
$this->as3cf->render_view( 'notice', $args );
|
308 |
}
|
309 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
310 |
/**
|
311 |
* Handler for the running upgrade actions
|
312 |
*/
|
313 |
-
function maybe_handle_action() {
|
314 |
if ( ! isset( $_GET['page'] ) || sanitize_key( $_GET['page'] ) !== $this->as3cf->get_plugin_slug() ) { // input var okay
|
315 |
return;
|
316 |
}
|
@@ -324,6 +410,7 @@ abstract class AS3CF_Upgrade {
|
|
324 |
}
|
325 |
|
326 |
$method_name = 'action_' . sanitize_key( $_GET['action'] ); // input var okay
|
|
|
327 |
if ( method_exists( $this, $method_name ) ) {
|
328 |
call_user_func( array( $this, $method_name ) );
|
329 |
}
|
@@ -334,7 +421,7 @@ abstract class AS3CF_Upgrade {
|
|
334 |
*
|
335 |
* @param array $session
|
336 |
*/
|
337 |
-
function upgrade_error( $session ) {
|
338 |
$session['status'] = self::STATUS_ERROR;
|
339 |
$this->save_session( $session );
|
340 |
$this->unschedule();
|
@@ -343,7 +430,7 @@ abstract class AS3CF_Upgrade {
|
|
343 |
/**
|
344 |
* Complete the upgrade
|
345 |
*/
|
346 |
-
function upgrade_finished() {
|
347 |
$this->clear_session();
|
348 |
$this->update_saved_upgrade_id();
|
349 |
$this->unschedule();
|
@@ -352,7 +439,7 @@ abstract class AS3CF_Upgrade {
|
|
352 |
/**
|
353 |
* Restart upgrade
|
354 |
*/
|
355 |
-
function action_restart_update() {
|
356 |
$this->schedule();
|
357 |
$this->change_status_request( self::STATUS_RUNNING );
|
358 |
}
|
@@ -360,7 +447,7 @@ abstract class AS3CF_Upgrade {
|
|
360 |
/**
|
361 |
* Pause upgrade
|
362 |
*/
|
363 |
-
function action_pause_update() {
|
364 |
$this->unschedule();
|
365 |
$this->change_status_request( self::STATUS_PAUSED );
|
366 |
}
|
@@ -370,7 +457,7 @@ abstract class AS3CF_Upgrade {
|
|
370 |
*
|
371 |
* @param int $status
|
372 |
*/
|
373 |
-
function change_status_request( $status ) {
|
374 |
$session = $this->get_session();
|
375 |
$session['status'] = $status;
|
376 |
$this->save_session( $session );
|
@@ -383,14 +470,14 @@ abstract class AS3CF_Upgrade {
|
|
383 |
/**
|
384 |
* Schedule the cron
|
385 |
*/
|
386 |
-
function schedule() {
|
387 |
$this->as3cf->schedule_event( $this->cron_hook, $this->cron_schedule_key );
|
388 |
}
|
389 |
|
390 |
/**
|
391 |
* Remove the cron schedule
|
392 |
*/
|
393 |
-
function unschedule() {
|
394 |
$this->as3cf->clear_scheduled_event( $this->cron_hook );
|
395 |
}
|
396 |
|
@@ -401,7 +488,7 @@ abstract class AS3CF_Upgrade {
|
|
401 |
*
|
402 |
* @return array
|
403 |
*/
|
404 |
-
function cron_schedules( $schedules ) {
|
405 |
// Add the upgrade interval to the existing schedules.
|
406 |
$schedules[ $this->cron_schedule_key ] = array(
|
407 |
'interval' => $this->cron_interval_in_minutes * 60,
|
@@ -415,7 +502,7 @@ abstract class AS3CF_Upgrade {
|
|
415 |
* Get the current status of the upgrade
|
416 |
* See STATUS_* constants in the class declaration above.
|
417 |
*/
|
418 |
-
function get_upgrade_status() {
|
419 |
$session = $this->get_session();
|
420 |
|
421 |
if ( ! isset( $session['status'] ) ) {
|
@@ -430,7 +517,7 @@ abstract class AS3CF_Upgrade {
|
|
430 |
*
|
431 |
* @return array
|
432 |
*/
|
433 |
-
function get_session() {
|
434 |
return get_site_option( 'update_' . $this->upgrade_name . '_session', array() );
|
435 |
}
|
436 |
|
@@ -439,7 +526,7 @@ abstract class AS3CF_Upgrade {
|
|
439 |
*
|
440 |
* @param array $session session data to store
|
441 |
*/
|
442 |
-
function save_session( $session ) {
|
443 |
update_site_option( 'update_' . $this->upgrade_name . '_session', $session );
|
444 |
}
|
445 |
|
@@ -447,7 +534,7 @@ abstract class AS3CF_Upgrade {
|
|
447 |
* Remove the session data to be used between requests
|
448 |
*
|
449 |
*/
|
450 |
-
function clear_session() {
|
451 |
delete_site_option( 'update_' . $this->upgrade_name . '_session' );
|
452 |
}
|
453 |
|
@@ -456,14 +543,14 @@ abstract class AS3CF_Upgrade {
|
|
456 |
*
|
457 |
* @return int|mixed|string|WP_Error
|
458 |
*/
|
459 |
-
function get_saved_upgrade_id() {
|
460 |
return $this->as3cf->get_setting( $this->settings_key, 0 );
|
461 |
}
|
462 |
|
463 |
/**
|
464 |
* Update the saved upgrade ID
|
465 |
*/
|
466 |
-
function update_saved_upgrade_id() {
|
467 |
$this->as3cf->set_setting( $this->settings_key, $this->upgrade_id );
|
468 |
$this->as3cf->save_settings();
|
469 |
}
|
@@ -473,7 +560,7 @@ abstract class AS3CF_Upgrade {
|
|
473 |
*
|
474 |
* @return bool
|
475 |
*/
|
476 |
-
function has_previous_upgrade_completed() {
|
477 |
// Has the previous upgrade completed yet?
|
478 |
$previous_id = $this->upgrade_id - 1;
|
479 |
if ( 0 !== $previous_id && (int) $this->get_saved_upgrade_id() < $previous_id ) {
|
31 |
/**
|
32 |
* @var int
|
33 |
*/
|
34 |
+
protected $upgrade_id = 0;
|
35 |
|
36 |
/**
|
37 |
* @var string
|
38 |
*/
|
39 |
+
protected $upgrade_name = 'base';
|
40 |
|
41 |
/**
|
42 |
* @var string 'metadata', 'attachment'
|
43 |
*/
|
44 |
+
protected $upgrade_type = 'attachment';
|
45 |
|
46 |
/**
|
47 |
* @var string
|
87 |
*
|
88 |
* @param Amazon_S3_And_CloudFront $as3cf - the instance of the as3cf class
|
89 |
*/
|
90 |
+
public function __construct( $as3cf ) {
|
91 |
$this->as3cf = $as3cf;
|
92 |
|
93 |
$this->cron_hook = 'as3cf_cron_update_' . $this->upgrade_name;
|
94 |
$this->cron_schedule_key = 'as3cf_update_' . $this->upgrade_name . '_interval';
|
95 |
|
96 |
+
$this->cron_interval_in_minutes = apply_filters( 'as3cf_update_' . $this->upgrade_name . '_interval', 2 );
|
97 |
$this->error_threshold = apply_filters( 'as3cf_update_' . $this->upgrade_name . '_error_threshold', 20 );
|
98 |
|
99 |
add_filter( 'cron_schedules', array( $this, 'cron_schedules' ) );
|
123 |
return false;
|
124 |
}
|
125 |
|
126 |
+
// Is plugin setup?
|
127 |
+
if ( ! $this->as3cf->is_plugin_setup() ) {
|
128 |
+
return false;
|
129 |
+
}
|
130 |
+
|
131 |
// If the upgrade status is already set, then we've already initialized the upgrade
|
132 |
if ( $upgrade_status = $this->get_upgrade_status() ) {
|
133 |
if ( self::STATUS_RUNNING === $upgrade_status ) {
|
134 |
// Make sure cron job is persisted in case it has dropped
|
135 |
$this->schedule();
|
136 |
}
|
137 |
+
|
138 |
return false;
|
139 |
}
|
140 |
|
148 |
return false;
|
149 |
}
|
150 |
|
151 |
+
// Do we actually have attachments to process?
|
152 |
+
if ( 0 === $this->count_items_to_process() ) {
|
153 |
$this->upgrade_finished();
|
154 |
|
155 |
return false;
|
159 |
}
|
160 |
|
161 |
/**
|
162 |
+
* Count items to process.
|
163 |
+
*
|
164 |
* @return int
|
165 |
*/
|
166 |
+
abstract protected function count_items_to_process();
|
167 |
|
168 |
/**
|
169 |
+
* Get items to process.
|
170 |
+
*
|
171 |
+
* @param string $prefix
|
172 |
+
* @param int $limit
|
173 |
+
* @param bool|mixed $offset
|
174 |
*
|
175 |
* @return array
|
176 |
*/
|
177 |
+
abstract protected function get_items_to_process( $prefix, $limit, $offset = false );
|
178 |
|
179 |
/**
|
180 |
+
* Upgrade attachment.
|
181 |
+
*
|
182 |
+
* @param mixed $attachment
|
183 |
*
|
184 |
* @return bool
|
185 |
*/
|
186 |
+
abstract protected function upgrade_item( $attachment );
|
187 |
|
188 |
/**
|
189 |
* Fire up the upgrade
|
196 |
}
|
197 |
|
198 |
/**
|
199 |
+
* Cron job to update the region of the bucket in s3 metadata
|
200 |
*/
|
201 |
+
public function do_upgrade() {
|
202 |
// Check if the cron should even be running
|
203 |
if ( $this->get_saved_upgrade_id() >= $this->upgrade_id || $this->get_upgrade_status() !== self::STATUS_RUNNING ) {
|
204 |
$this->unschedule();
|
209 |
// set the batch size limit for the query
|
210 |
$limit = apply_filters( 'as3cf_update_' . $this->upgrade_name . '_batch_size', 500 );
|
211 |
$all_limit = $limit;
|
212 |
+
$finish = time() + apply_filters( 'as3cf_update_' . $this->upgrade_name . '_time_limit', 20 );
|
|
|
|
|
|
|
|
|
|
|
213 |
|
214 |
$session = $this->get_session();
|
215 |
|
216 |
// find the blog IDs that have been processed so we can skip them
|
217 |
$processed_blog_ids = isset( $session['processed_blog_ids'] ) ? $session['processed_blog_ids'] : array();
|
218 |
$this->error_count = isset( $session['error_count'] ) ? $session['error_count'] : 0;
|
219 |
+
$offset = isset( $session['offset'] ) ? $session['offset'] : false;
|
220 |
|
221 |
// get the table prefixes for all the blogs
|
222 |
$table_prefixes = $this->as3cf->get_all_blog_table_prefixes( $processed_blog_ids );
|
223 |
|
224 |
+
$all_items = array();
|
225 |
+
$all_count = 0;
|
226 |
|
227 |
foreach ( $table_prefixes as $blog_id => $table_prefix ) {
|
228 |
+
$items = $this->get_items_to_process( $table_prefix, $limit, $offset );
|
229 |
+
$count = count( $items );
|
230 |
|
231 |
if ( 0 === $count ) {
|
232 |
+
// No more items, record the blog ID to skip next time
|
233 |
+
$session['offset'] = false;
|
234 |
$processed_blog_ids[] = $blog_id;
|
235 |
} else {
|
236 |
$all_count += $count;
|
237 |
+
$all_items[ $blog_id ] = $items;
|
238 |
}
|
239 |
|
240 |
if ( $all_count >= $all_limit ) {
|
251 |
}
|
252 |
|
253 |
// loop through and update s3 meta with region
|
254 |
+
foreach ( $all_items as $blog_id => $items ) {
|
255 |
$this->as3cf->switch_to_blog( $blog_id );
|
256 |
|
257 |
+
foreach ( $items as $item ) {
|
258 |
if ( $this->error_count >= $this->error_threshold ) {
|
259 |
$this->upgrade_error( $session );
|
260 |
|
261 |
return;
|
262 |
}
|
263 |
|
264 |
+
// Do the actual upgrade to the item
|
265 |
+
$this->upgrade_item( $item );
|
266 |
|
267 |
if ( time() >= $finish || $this->as3cf->memory_exceeded( 'as3cf_update_' . $this->upgrade_name . '_memory_exceeded' ) ) {
|
268 |
// Batch limits reached
|
275 |
$this->as3cf->restore_current_blog();
|
276 |
}
|
277 |
|
278 |
+
$session['offset'] = isset( $item ) ? $item : false;
|
279 |
$session['processed_blog_ids'] = $processed_blog_ids;
|
280 |
$session['error_count'] = $this->error_count;
|
281 |
|
285 |
/**
|
286 |
* Adds notices about issues with upgrades allowing user to restart them
|
287 |
*/
|
288 |
+
public function maybe_display_notices() {
|
289 |
+
$action_url = $this->as3cf->get_plugin_page_url( array(
|
290 |
+
'action' => 'restart_update',
|
291 |
+
'update' => $this->upgrade_name,
|
292 |
+
), 'self' );
|
293 |
$msg_type = 'notice-info';
|
294 |
|
295 |
switch ( $this->get_upgrade_status() ) {
|
296 |
case self::STATUS_RUNNING:
|
297 |
+
$msg = $this->get_running_message();
|
298 |
$action_text = __( 'Pause Update', 'amazon-s3-and-cloudfront' );
|
299 |
+
$action_url = $this->as3cf->get_plugin_page_url( array(
|
300 |
+
'action' => 'pause_update',
|
301 |
+
'update' => $this->upgrade_name,
|
302 |
+
), 'self' );
|
303 |
break;
|
304 |
case self::STATUS_PAUSED:
|
305 |
+
$msg = $this->get_paused_message();
|
306 |
$action_text = __( 'Restart Update', 'amazon-s3-and-cloudfront' );
|
307 |
break;
|
308 |
case self::STATUS_ERROR:
|
309 |
+
$msg = $this->get_error_message();
|
310 |
$action_text = __( 'Try Run It Again', 'amazon-s3-and-cloudfront' );
|
311 |
$msg_type = 'error';
|
312 |
break;
|
324 |
$this->as3cf->render_view( 'notice', $args );
|
325 |
}
|
326 |
|
327 |
+
/**
|
328 |
+
* Get running message.
|
329 |
+
*
|
330 |
+
* @return string
|
331 |
+
*/
|
332 |
+
protected function get_running_message() {
|
333 |
+
return sprintf( __( '<strong>Running %1$s Update%2$s</strong> — We’re going through all the Media Library items uploaded to S3 %3$s This will be done quietly in the background, processing a small batch of Media Library items every %4$d minutes. There should be no noticeable impact on your server’s performance.', 'amazon-s3-and-cloudfront' ),
|
334 |
+
ucwords( $this->upgrade_type ),
|
335 |
+
$this->get_progress_text(),
|
336 |
+
$this->running_update_text,
|
337 |
+
$this->cron_interval_in_minutes
|
338 |
+
);
|
339 |
+
}
|
340 |
+
|
341 |
+
/**
|
342 |
+
* Get paused message.
|
343 |
+
*
|
344 |
+
* @return string
|
345 |
+
*/
|
346 |
+
protected function get_paused_message() {
|
347 |
+
return sprintf( __( '<strong>%1$s Update Paused%2$s</strong> — Updating Media Library %3$s has been paused.', 'amazon-s3-and-cloudfront' ),
|
348 |
+
ucwords( $this->upgrade_type ),
|
349 |
+
$this->get_progress_text(),
|
350 |
+
$this->upgrade_type
|
351 |
+
);
|
352 |
+
}
|
353 |
+
|
354 |
+
/**
|
355 |
+
* Get error message.
|
356 |
+
*
|
357 |
+
* @return string
|
358 |
+
*/
|
359 |
+
protected function get_error_message() {
|
360 |
+
return sprintf( __( '<strong>Error Updating %1$s</strong> — We ran into some errors attempting to update the %2$s for all your Media Library items that have been uploaded to S3. Please check your error log for details. (#%3$d)', 'amazon-s3-and-cloudfront' ),
|
361 |
+
ucwords( $this->upgrade_type ),
|
362 |
+
$this->upgrade_type,
|
363 |
+
$this->upgrade_id
|
364 |
+
);
|
365 |
+
}
|
366 |
+
|
367 |
+
/**
|
368 |
+
* Get progress text.
|
369 |
+
*
|
370 |
+
* @return string
|
371 |
+
*/
|
372 |
+
protected function get_progress_text() {
|
373 |
+
$progress = $this->calculate_progress();
|
374 |
+
|
375 |
+
if ( false === $progress ) {
|
376 |
+
// Progress can not be calculated, return
|
377 |
+
return '';
|
378 |
+
}
|
379 |
+
|
380 |
+
if ( $progress > 100 ) {
|
381 |
+
$progress = 100;
|
382 |
+
}
|
383 |
+
|
384 |
+
return sprintf( __( ' (%s%% Complete)', 'amazon-s3-and-cloudfront' ), $progress );
|
385 |
+
}
|
386 |
+
|
387 |
+
/**
|
388 |
+
* Calculate progress.
|
389 |
+
*
|
390 |
+
* @return bool|int|float
|
391 |
+
*/
|
392 |
+
protected function calculate_progress() {
|
393 |
+
return false;
|
394 |
+
}
|
395 |
+
|
396 |
/**
|
397 |
* Handler for the running upgrade actions
|
398 |
*/
|
399 |
+
public function maybe_handle_action() {
|
400 |
if ( ! isset( $_GET['page'] ) || sanitize_key( $_GET['page'] ) !== $this->as3cf->get_plugin_slug() ) { // input var okay
|
401 |
return;
|
402 |
}
|
410 |
}
|
411 |
|
412 |
$method_name = 'action_' . sanitize_key( $_GET['action'] ); // input var okay
|
413 |
+
|
414 |
if ( method_exists( $this, $method_name ) ) {
|
415 |
call_user_func( array( $this, $method_name ) );
|
416 |
}
|
421 |
*
|
422 |
* @param array $session
|
423 |
*/
|
424 |
+
protected function upgrade_error( $session ) {
|
425 |
$session['status'] = self::STATUS_ERROR;
|
426 |
$this->save_session( $session );
|
427 |
$this->unschedule();
|
430 |
/**
|
431 |
* Complete the upgrade
|
432 |
*/
|
433 |
+
protected function upgrade_finished() {
|
434 |
$this->clear_session();
|
435 |
$this->update_saved_upgrade_id();
|
436 |
$this->unschedule();
|
439 |
/**
|
440 |
* Restart upgrade
|
441 |
*/
|
442 |
+
protected function action_restart_update() {
|
443 |
$this->schedule();
|
444 |
$this->change_status_request( self::STATUS_RUNNING );
|
445 |
}
|
447 |
/**
|
448 |
* Pause upgrade
|
449 |
*/
|
450 |
+
protected function action_pause_update() {
|
451 |
$this->unschedule();
|
452 |
$this->change_status_request( self::STATUS_PAUSED );
|
453 |
}
|
457 |
*
|
458 |
* @param int $status
|
459 |
*/
|
460 |
+
protected function change_status_request( $status ) {
|
461 |
$session = $this->get_session();
|
462 |
$session['status'] = $status;
|
463 |
$this->save_session( $session );
|
470 |
/**
|
471 |
* Schedule the cron
|
472 |
*/
|
473 |
+
protected function schedule() {
|
474 |
$this->as3cf->schedule_event( $this->cron_hook, $this->cron_schedule_key );
|
475 |
}
|
476 |
|
477 |
/**
|
478 |
* Remove the cron schedule
|
479 |
*/
|
480 |
+
protected function unschedule() {
|
481 |
$this->as3cf->clear_scheduled_event( $this->cron_hook );
|
482 |
}
|
483 |
|
488 |
*
|
489 |
* @return array
|
490 |
*/
|
491 |
+
public function cron_schedules( $schedules ) {
|
492 |
// Add the upgrade interval to the existing schedules.
|
493 |
$schedules[ $this->cron_schedule_key ] = array(
|
494 |
'interval' => $this->cron_interval_in_minutes * 60,
|
502 |
* Get the current status of the upgrade
|
503 |
* See STATUS_* constants in the class declaration above.
|
504 |
*/
|
505 |
+
protected function get_upgrade_status() {
|
506 |
$session = $this->get_session();
|
507 |
|
508 |
if ( ! isset( $session['status'] ) ) {
|
517 |
*
|
518 |
* @return array
|
519 |
*/
|
520 |
+
protected function get_session() {
|
521 |
return get_site_option( 'update_' . $this->upgrade_name . '_session', array() );
|
522 |
}
|
523 |
|
526 |
*
|
527 |
* @param array $session session data to store
|
528 |
*/
|
529 |
+
protected function save_session( $session ) {
|
530 |
update_site_option( 'update_' . $this->upgrade_name . '_session', $session );
|
531 |
}
|
532 |
|
534 |
* Remove the session data to be used between requests
|
535 |
*
|
536 |
*/
|
537 |
+
protected function clear_session() {
|
538 |
delete_site_option( 'update_' . $this->upgrade_name . '_session' );
|
539 |
}
|
540 |
|
543 |
*
|
544 |
* @return int|mixed|string|WP_Error
|
545 |
*/
|
546 |
+
protected function get_saved_upgrade_id() {
|
547 |
return $this->as3cf->get_setting( $this->settings_key, 0 );
|
548 |
}
|
549 |
|
550 |
/**
|
551 |
* Update the saved upgrade ID
|
552 |
*/
|
553 |
+
protected function update_saved_upgrade_id() {
|
554 |
$this->as3cf->set_setting( $this->settings_key, $this->upgrade_id );
|
555 |
$this->as3cf->save_settings();
|
556 |
}
|
560 |
*
|
561 |
* @return bool
|
562 |
*/
|
563 |
+
protected function has_previous_upgrade_completed() {
|
564 |
// Has the previous upgrade completed yet?
|
565 |
$previous_id = $this->upgrade_id - 1;
|
566 |
if ( 0 !== $previous_id && (int) $this->get_saved_upgrade_id() < $previous_id ) {
|
classes/filters/as3cf-local-to-s3.php
ADDED
@@ -0,0 +1,197 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class AS3CF_Local_To_S3 extends AS3CF_Filter {
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Init.
|
7 |
+
*/
|
8 |
+
protected function init() {
|
9 |
+
// Hot fix for 4.4 responsive images
|
10 |
+
$priority = 1;
|
11 |
+
|
12 |
+
global $wp_version;
|
13 |
+
if ( 0 === version_compare( $wp_version, '4.4' ) ) {
|
14 |
+
$priority = 10;
|
15 |
+
}
|
16 |
+
|
17 |
+
// EDD
|
18 |
+
add_filter( 'edd_download_files', array( $this, 'filter_edd_download_files' ) );
|
19 |
+
// Customizer
|
20 |
+
add_filter( 'theme_mod_background_image', array( $this, 'filter_customizer_image' ) );
|
21 |
+
add_filter( 'theme_mod_header_image', array( $this, 'filter_customizer_image' ) );
|
22 |
+
// Posts
|
23 |
+
add_filter( 'the_content', array( $this, 'filter_post' ), $priority, 1 );
|
24 |
+
add_filter( 'content_edit_pre', array( $this, 'filter_post' ) );
|
25 |
+
add_filter( 'the_excerpt', array( $this, 'filter_post' ) );
|
26 |
+
add_filter( 'excerpt_edit_pre', array( $this, 'filter_post' ) );
|
27 |
+
// Widgets
|
28 |
+
add_filter( 'widget_text', array( $this, 'filter_widget' ) );
|
29 |
+
add_filter( 'widget_form_callback', array( $this, 'filter_widget_form' ), 10, 2 );
|
30 |
+
}
|
31 |
+
|
32 |
+
/**
|
33 |
+
* Filter widget.
|
34 |
+
*
|
35 |
+
* @param string $content
|
36 |
+
*
|
37 |
+
* @return string
|
38 |
+
*/
|
39 |
+
public function filter_widget( $content ) {
|
40 |
+
$cache = $this->get_option_cache();
|
41 |
+
$to_cache = array();
|
42 |
+
$content = $this->process_content( $content, $cache, $to_cache );
|
43 |
+
|
44 |
+
$this->maybe_update_option_cache( $to_cache );
|
45 |
+
|
46 |
+
return $content;
|
47 |
+
}
|
48 |
+
|
49 |
+
/**
|
50 |
+
* Filter widget form.
|
51 |
+
*
|
52 |
+
* @param array $instance
|
53 |
+
* @param WP_Widget $class
|
54 |
+
*
|
55 |
+
* @return string
|
56 |
+
*/
|
57 |
+
public function filter_widget_form( $instance, $class ) {
|
58 |
+
if ( ! is_a( $class, 'WP_Widget_Text' ) || empty( $instance ) ) {
|
59 |
+
return $instance;
|
60 |
+
}
|
61 |
+
|
62 |
+
$cache = $this->get_option_cache();
|
63 |
+
$to_cache = array();
|
64 |
+
$instance['text'] = $this->process_content( $instance['text'], $cache, $to_cache );
|
65 |
+
|
66 |
+
$this->maybe_update_option_cache( $to_cache );
|
67 |
+
|
68 |
+
return $instance;
|
69 |
+
}
|
70 |
+
|
71 |
+
/**
|
72 |
+
* Does URL need replacing?
|
73 |
+
*
|
74 |
+
* @param string $url
|
75 |
+
*
|
76 |
+
* @return bool
|
77 |
+
*/
|
78 |
+
protected function url_needs_replacing( $url ) {
|
79 |
+
$uploads = wp_upload_dir();
|
80 |
+
$base_url = $this->as3cf->remove_scheme( $uploads['baseurl'] );
|
81 |
+
|
82 |
+
if ( false !== strpos( $url, $base_url ) ) {
|
83 |
+
// Local URL, perform replacement
|
84 |
+
return true;
|
85 |
+
}
|
86 |
+
|
87 |
+
// Remote URL, no replacement needed
|
88 |
+
return false;
|
89 |
+
}
|
90 |
+
|
91 |
+
/**
|
92 |
+
* Get URL
|
93 |
+
*
|
94 |
+
* @param int $attachment_id
|
95 |
+
* @param null|string $size
|
96 |
+
*
|
97 |
+
* @return bool|string
|
98 |
+
*/
|
99 |
+
protected function get_url( $attachment_id, $size = null ) {
|
100 |
+
return $this->as3cf->get_attachment_url( $attachment_id, null, $size );
|
101 |
+
}
|
102 |
+
|
103 |
+
/**
|
104 |
+
* Get base URL.
|
105 |
+
*
|
106 |
+
* @param int $attachment_id
|
107 |
+
*
|
108 |
+
* @return string|false
|
109 |
+
*/
|
110 |
+
protected function get_base_url( $attachment_id ) {
|
111 |
+
return $this->as3cf->get_attachment_local_url( $attachment_id );
|
112 |
+
}
|
113 |
+
|
114 |
+
/**
|
115 |
+
* Get attachment ID from URL.
|
116 |
+
*
|
117 |
+
* @param string $url
|
118 |
+
*
|
119 |
+
* @return bool|int
|
120 |
+
*/
|
121 |
+
protected function get_attachment_id_from_url( $url ) {
|
122 |
+
global $wpdb;
|
123 |
+
|
124 |
+
$upload_dir = wp_upload_dir();
|
125 |
+
$base_url = $this->as3cf->remove_scheme( $upload_dir['baseurl'] );
|
126 |
+
$full_url = $this->as3cf->remove_scheme( $this->as3cf->remove_size_from_filename( $url ) );
|
127 |
+
$path = $this->as3cf->decode_filename_in_path( ltrim( str_replace( $base_url, '', $full_url ), '/' ) );
|
128 |
+
|
129 |
+
if ( isset( $this->query_cache[ $full_url ] ) ) {
|
130 |
+
// ID already cached, return
|
131 |
+
return $this->query_cache[ $full_url ];
|
132 |
+
}
|
133 |
+
|
134 |
+
$sql = $wpdb->prepare( "
|
135 |
+
SELECT post_id FROM {$wpdb->postmeta}
|
136 |
+
WHERE meta_key = %s
|
137 |
+
AND meta_value = %s
|
138 |
+
", '_wp_attached_file', $path );
|
139 |
+
|
140 |
+
$result = $wpdb->get_var( $sql );
|
141 |
+
|
142 |
+
if ( is_null( $result ) ) {
|
143 |
+
// Attachment ID not found, return false
|
144 |
+
$this->query_cache[ $full_url ] = false;
|
145 |
+
|
146 |
+
return false;
|
147 |
+
}
|
148 |
+
|
149 |
+
$this->query_cache[ $full_url ] = (int) $result;
|
150 |
+
|
151 |
+
return (int) $result;
|
152 |
+
}
|
153 |
+
|
154 |
+
/**
|
155 |
+
* Normalize find value.
|
156 |
+
*
|
157 |
+
* @param string $url
|
158 |
+
*
|
159 |
+
* @return string
|
160 |
+
*/
|
161 |
+
protected function normalize_find_value( $url ) {
|
162 |
+
return $this->as3cf->decode_filename_in_path( $url );
|
163 |
+
}
|
164 |
+
|
165 |
+
/**
|
166 |
+
* Normalize replace value.
|
167 |
+
*
|
168 |
+
* @param string $url
|
169 |
+
*
|
170 |
+
* @return string
|
171 |
+
*/
|
172 |
+
protected function normalize_replace_value( $url ) {
|
173 |
+
return $this->as3cf->encode_filename_in_path( $url );
|
174 |
+
}
|
175 |
+
|
176 |
+
/**
|
177 |
+
* Post process content.
|
178 |
+
*
|
179 |
+
* @param string $content
|
180 |
+
*
|
181 |
+
* @return string
|
182 |
+
*/
|
183 |
+
protected function post_process_content( $content ) {
|
184 |
+
return $content;
|
185 |
+
}
|
186 |
+
|
187 |
+
/**
|
188 |
+
* Pre replace content.
|
189 |
+
*
|
190 |
+
* @param string $content
|
191 |
+
*
|
192 |
+
* @return string
|
193 |
+
*/
|
194 |
+
protected function pre_replace_content( $content ) {
|
195 |
+
return $this->remove_aws_query_strings( $content );
|
196 |
+
}
|
197 |
+
}
|
classes/filters/as3cf-s3-to-local.php
ADDED
@@ -0,0 +1,208 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class AS3CF_S3_To_Local extends AS3CF_Filter {
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Init.
|
7 |
+
*/
|
8 |
+
protected function init() {
|
9 |
+
// EDD
|
10 |
+
add_filter( 'edd_metabox_save_edd_download_files', array( $this, 'filter_edd_download_files' ) );
|
11 |
+
// Customizer
|
12 |
+
add_filter( 'pre_set_theme_mod_background_image', array( $this, 'filter_customizer_image' ), 10, 2 );
|
13 |
+
add_filter( 'pre_set_theme_mod_header_image', array( $this, 'filter_customizer_image' ), 10, 2 );
|
14 |
+
add_filter( 'pre_set_theme_mod_header_image_data', array( $this, 'filter_header_image_data' ), 10, 2 );
|
15 |
+
// Posts
|
16 |
+
add_filter( 'content_save_pre', array( $this, 'filter_post' ) );
|
17 |
+
add_filter( 'excerpt_save_pre', array( $this, 'filter_post' ) );
|
18 |
+
// Widgets
|
19 |
+
add_filter( 'widget_update_callback', array( $this, 'filter_widget_update' ), 10, 4 );
|
20 |
+
}
|
21 |
+
|
22 |
+
/**
|
23 |
+
* Filter widget update.
|
24 |
+
*
|
25 |
+
* @param array $instance
|
26 |
+
* @param array $new_instance
|
27 |
+
* @param array $old_instance
|
28 |
+
* @param WP_Widget $class
|
29 |
+
*
|
30 |
+
* @return array
|
31 |
+
*
|
32 |
+
*/
|
33 |
+
public function filter_widget_update( $instance, $new_instance, $old_instance, $class ) {
|
34 |
+
if ( ! is_a( $class, 'WP_Widget_Text' ) || empty( $instance ) ) {
|
35 |
+
return $instance;
|
36 |
+
}
|
37 |
+
|
38 |
+
$cache = $this->get_option_cache();
|
39 |
+
$to_cache = array();
|
40 |
+
$instance['text'] = $this->process_content( $instance['text'], $cache, $to_cache );
|
41 |
+
|
42 |
+
$this->maybe_update_option_cache( $to_cache );
|
43 |
+
|
44 |
+
return $instance;
|
45 |
+
}
|
46 |
+
|
47 |
+
/**
|
48 |
+
* Does URL need replacing?
|
49 |
+
*
|
50 |
+
* @param string $url
|
51 |
+
*
|
52 |
+
* @return bool
|
53 |
+
*/
|
54 |
+
protected function url_needs_replacing( $url ) {
|
55 |
+
$uploads = wp_upload_dir();
|
56 |
+
$base_url = $this->as3cf->remove_scheme( $uploads['baseurl'] );
|
57 |
+
|
58 |
+
if ( false !== strpos( $url, $base_url ) ) {
|
59 |
+
// Local URL, no replacement needed
|
60 |
+
return false;
|
61 |
+
}
|
62 |
+
|
63 |
+
// Remote URL, perform replacement
|
64 |
+
return true;
|
65 |
+
}
|
66 |
+
|
67 |
+
/**
|
68 |
+
* Get URL
|
69 |
+
*
|
70 |
+
* @param int $attachment_id
|
71 |
+
* @param null|string $size
|
72 |
+
*
|
73 |
+
* @return bool|string
|
74 |
+
*/
|
75 |
+
protected function get_url( $attachment_id, $size = null ) {
|
76 |
+
return $this->as3cf->get_attachment_local_url_size( $attachment_id, $size );
|
77 |
+
}
|
78 |
+
|
79 |
+
/**
|
80 |
+
* Get base URL.
|
81 |
+
*
|
82 |
+
* @param int $attachment_id
|
83 |
+
*
|
84 |
+
* @return string|false
|
85 |
+
*/
|
86 |
+
protected function get_base_url( $attachment_id ) {
|
87 |
+
return $this->as3cf->get_attachment_url( $attachment_id );
|
88 |
+
}
|
89 |
+
|
90 |
+
/**
|
91 |
+
* Get attachment ID from URL.
|
92 |
+
*
|
93 |
+
* @param string $url
|
94 |
+
*
|
95 |
+
* @return bool|int
|
96 |
+
*/
|
97 |
+
protected function get_attachment_id_from_url( $url ) {
|
98 |
+
global $wpdb;
|
99 |
+
|
100 |
+
$full_url = $this->as3cf->remove_size_from_filename( $url );
|
101 |
+
$parts = parse_url( $full_url );
|
102 |
+
$path = $this->as3cf->decode_filename_in_path( ltrim( $parts['path'], '/' ) );
|
103 |
+
|
104 |
+
if ( isset( $this->query_cache[ $full_url ] ) ) {
|
105 |
+
// ID already cached, return
|
106 |
+
return $this->query_cache[ $full_url ];
|
107 |
+
}
|
108 |
+
|
109 |
+
if ( false !== strpos( $path, '/' ) ) {
|
110 |
+
// Remove the first directory to cater for bucket in path domain settings
|
111 |
+
$path = explode( '/', $path );
|
112 |
+
array_shift( $path );
|
113 |
+
$path = implode( '/', $path );
|
114 |
+
}
|
115 |
+
|
116 |
+
$sql = $wpdb->prepare( "
|
117 |
+
SELECT * FROM {$wpdb->postmeta}
|
118 |
+
WHERE meta_key = %s
|
119 |
+
AND meta_value LIKE %s;
|
120 |
+
", 'amazonS3_info', '%' . $path . '%' );
|
121 |
+
|
122 |
+
$results = $wpdb->get_results( $sql );
|
123 |
+
|
124 |
+
if ( empty( $results ) ) {
|
125 |
+
// No attachment found, return false
|
126 |
+
return false;
|
127 |
+
}
|
128 |
+
|
129 |
+
if ( 1 === count( $results ) ) {
|
130 |
+
// Attachment matched, return ID
|
131 |
+
$this->query_cache[ $full_url ] = $results[0]->post_id;
|
132 |
+
|
133 |
+
return $results[0]->post_id;
|
134 |
+
}
|
135 |
+
|
136 |
+
$path = ltrim( $parts['path'], '/' );
|
137 |
+
|
138 |
+
foreach ( $results as $result ) {
|
139 |
+
$meta = maybe_unserialize( $result->meta_value );
|
140 |
+
|
141 |
+
if ( ! isset( $meta['bucket'] ) || ! isset( $meta['key'] ) ) {
|
142 |
+
// Can't determine S3 bucket or key, continue
|
143 |
+
continue;
|
144 |
+
}
|
145 |
+
|
146 |
+
if ( false !== strpos( $path, $meta['bucket'] ) ) {
|
147 |
+
// Bucket in path, remove
|
148 |
+
$path = ltrim( str_replace( $meta['bucket'], '', $path ), '/' );
|
149 |
+
}
|
150 |
+
|
151 |
+
if ( $path === $meta['key'] ) {
|
152 |
+
// Exact match, return ID
|
153 |
+
$this->query_cache[ $full_url ] = $results[0]->post_id;
|
154 |
+
|
155 |
+
return $result->post_id;
|
156 |
+
}
|
157 |
+
}
|
158 |
+
|
159 |
+
// Can't determine ID, return false
|
160 |
+
$this->query_cache[ $full_url ] = false;
|
161 |
+
|
162 |
+
return false;
|
163 |
+
}
|
164 |
+
|
165 |
+
/**
|
166 |
+
* Normalize find value.
|
167 |
+
*
|
168 |
+
* @param string $url
|
169 |
+
*
|
170 |
+
* @return string
|
171 |
+
*/
|
172 |
+
protected function normalize_find_value( $url ) {
|
173 |
+
return $this->as3cf->encode_filename_in_path( $url );
|
174 |
+
}
|
175 |
+
|
176 |
+
/**
|
177 |
+
* Normalize replace value.
|
178 |
+
*
|
179 |
+
* @param string $url
|
180 |
+
*
|
181 |
+
* @return string
|
182 |
+
*/
|
183 |
+
protected function normalize_replace_value( $url ) {
|
184 |
+
return $this->as3cf->decode_filename_in_path( $url );
|
185 |
+
}
|
186 |
+
|
187 |
+
/**
|
188 |
+
* Post process content.
|
189 |
+
*
|
190 |
+
* @param string $content
|
191 |
+
*
|
192 |
+
* @return string
|
193 |
+
*/
|
194 |
+
protected function post_process_content( $content ) {
|
195 |
+
return $this->remove_aws_query_strings( $content );
|
196 |
+
}
|
197 |
+
|
198 |
+
/**
|
199 |
+
* Pre replace content.
|
200 |
+
*
|
201 |
+
* @param string $content
|
202 |
+
*
|
203 |
+
* @return string
|
204 |
+
*/
|
205 |
+
protected function pre_replace_content( $content ) {
|
206 |
+
return $content;
|
207 |
+
}
|
208 |
+
}
|
classes/upgrades/as3cf-content-replace-urls.php
ADDED
@@ -0,0 +1,623 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// Exit if accessed directly
|
4 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
5 |
+
exit;
|
6 |
+
}
|
7 |
+
|
8 |
+
/**
|
9 |
+
* AS3CF_Upgrade_Content_Replace_URLs Class
|
10 |
+
*
|
11 |
+
* This class handles replacing all S3 URLs in post
|
12 |
+
* content with the local URL.
|
13 |
+
*
|
14 |
+
* @since 1.2
|
15 |
+
*/
|
16 |
+
class AS3CF_Upgrade_Content_Replace_URLs extends AS3CF_Upgrade {
|
17 |
+
|
18 |
+
/**
|
19 |
+
* @var int Current blog ID
|
20 |
+
*/
|
21 |
+
protected $blog_id;
|
22 |
+
|
23 |
+
/**
|
24 |
+
* @var int Finish time
|
25 |
+
*/
|
26 |
+
protected $finish;
|
27 |
+
|
28 |
+
/**
|
29 |
+
* @var array Session data
|
30 |
+
*/
|
31 |
+
protected $session;
|
32 |
+
|
33 |
+
/**
|
34 |
+
* Initiate the upgrade
|
35 |
+
*
|
36 |
+
* @param object $as3cf Instance of calling class
|
37 |
+
*/
|
38 |
+
public function __construct( $as3cf ) {
|
39 |
+
$this->upgrade_id = 4;
|
40 |
+
$this->upgrade_name = 'replace_s3_urls';
|
41 |
+
$this->upgrade_type = 'posts';
|
42 |
+
|
43 |
+
$this->running_update_text = __( 'and ensuring that only the local URL exists in post content.', 'amazon-s3-and-cloudfront' );
|
44 |
+
|
45 |
+
parent::__construct( $as3cf );
|
46 |
+
}
|
47 |
+
|
48 |
+
/**
|
49 |
+
* Fire up the upgrade
|
50 |
+
*/
|
51 |
+
protected function init() {
|
52 |
+
$session = array(
|
53 |
+
'status' => self::STATUS_RUNNING,
|
54 |
+
'total_attachments' => 0,
|
55 |
+
'processed_attachments' => 0,
|
56 |
+
'blogs_processed' => false,
|
57 |
+
'blogs' => array(),
|
58 |
+
);
|
59 |
+
|
60 |
+
foreach ( $this->as3cf->get_all_blog_table_prefixes() as $blog_id => $prefix ) {
|
61 |
+
$session['blogs'][ $blog_id ] = array(
|
62 |
+
'prefix' => $prefix,
|
63 |
+
'processed' => false,
|
64 |
+
'total_attachments' => null,
|
65 |
+
'last_attachment_id' => null,
|
66 |
+
'highest_post_id' => null,
|
67 |
+
'last_post_id' => null,
|
68 |
+
);
|
69 |
+
}
|
70 |
+
|
71 |
+
$this->save_session( $session );
|
72 |
+
$this->schedule();
|
73 |
+
}
|
74 |
+
|
75 |
+
/**
|
76 |
+
* Count attachments to process. We don't care about the total at this stage
|
77 |
+
* so just loop over blogs until attachments exist on S3.
|
78 |
+
*
|
79 |
+
* @return int
|
80 |
+
*/
|
81 |
+
protected function count_items_to_process() {
|
82 |
+
$table_prefixes = $this->as3cf->get_all_blog_table_prefixes();
|
83 |
+
|
84 |
+
foreach ( $table_prefixes as $blog_id => $table_prefix ) {
|
85 |
+
if ( $this->as3cf->count_attachments( $table_prefix, true ) ) {
|
86 |
+
return 1;
|
87 |
+
}
|
88 |
+
}
|
89 |
+
|
90 |
+
return 0;
|
91 |
+
}
|
92 |
+
|
93 |
+
/**
|
94 |
+
* Cron job to update post content, ensuring no S3 URLs exist.
|
95 |
+
*/
|
96 |
+
public function do_upgrade() {
|
97 |
+
// Check if the cron should even be running
|
98 |
+
if ( $this->get_saved_upgrade_id() >= $this->upgrade_id || $this->get_upgrade_status() !== self::STATUS_RUNNING ) {
|
99 |
+
$this->unschedule();
|
100 |
+
|
101 |
+
return;
|
102 |
+
}
|
103 |
+
|
104 |
+
$limit = apply_filters( 'as3cf_update_' . $this->upgrade_name . '_batch_size', 50 );
|
105 |
+
$this->finish = time() + apply_filters( 'as3cf_update_' . $this->upgrade_name . '_time_limit', 10 );
|
106 |
+
$this->session = $this->get_session();
|
107 |
+
|
108 |
+
if ( ! $this->maybe_process_blogs() ) {
|
109 |
+
// Blogs still to process but limits reached, return
|
110 |
+
$this->save_session( $this->session );
|
111 |
+
|
112 |
+
return;
|
113 |
+
}
|
114 |
+
|
115 |
+
foreach ( $this->session['blogs'] as $blog_id => $blog ) {
|
116 |
+
$this->blog_id = $blog_id;
|
117 |
+
$this->as3cf->switch_to_blog( $blog_id );
|
118 |
+
|
119 |
+
if ( $this->batch_limit_reached() ) {
|
120 |
+
// Limits reached, end batch
|
121 |
+
break;
|
122 |
+
}
|
123 |
+
|
124 |
+
if ( $blog['processed'] ) {
|
125 |
+
// Blog processed, move onto the next
|
126 |
+
continue;
|
127 |
+
}
|
128 |
+
|
129 |
+
$offset = $this->session['blogs'][ $blog_id ]['last_attachment_id'];
|
130 |
+
$attachments = $this->get_items_to_process( $blog['prefix'], $limit, $offset );
|
131 |
+
|
132 |
+
if ( empty( $attachments ) ) {
|
133 |
+
// All attachments processed, maybe move onto next blog
|
134 |
+
$this->session['blogs'][ $blog_id ]['processed'] = true;
|
135 |
+
|
136 |
+
if ( $this->all_blogs_processed() ) {
|
137 |
+
// All blogs processed, complete upgrade
|
138 |
+
$this->upgrade_finished();
|
139 |
+
|
140 |
+
return;
|
141 |
+
}
|
142 |
+
|
143 |
+
continue;
|
144 |
+
}
|
145 |
+
|
146 |
+
foreach ( $attachments as $attachment ) {
|
147 |
+
if ( $this->batch_limit_reached() ) {
|
148 |
+
// Limits reached, end batch
|
149 |
+
break 2;
|
150 |
+
}
|
151 |
+
|
152 |
+
if ( $this->upgrade_item( $attachment ) ) {
|
153 |
+
$this->session['processed_attachments'] += 1;
|
154 |
+
$this->session['blogs'][ $blog_id ]['last_attachment_id'] = $attachment->ID;
|
155 |
+
$this->session['blogs'][ $blog_id ]['last_post_id'] = null;
|
156 |
+
} else {
|
157 |
+
// Limits reached while processing posts, end batch
|
158 |
+
break 2;
|
159 |
+
}
|
160 |
+
}
|
161 |
+
|
162 |
+
$this->as3cf->restore_current_blog();
|
163 |
+
}
|
164 |
+
|
165 |
+
$this->save_session( $this->session );
|
166 |
+
}
|
167 |
+
|
168 |
+
/**
|
169 |
+
* Maybe process blogs.
|
170 |
+
*
|
171 |
+
* @return bool
|
172 |
+
*/
|
173 |
+
protected function maybe_process_blogs() {
|
174 |
+
if ( $this->session['blogs_processed'] ) {
|
175 |
+
// Blogs already processed, return
|
176 |
+
return true;
|
177 |
+
}
|
178 |
+
|
179 |
+
foreach ( $this->session['blogs'] as $blog_id => $blog ) {
|
180 |
+
if ( $this->batch_limit_reached() ) {
|
181 |
+
// Limits reached, return
|
182 |
+
return false;
|
183 |
+
}
|
184 |
+
|
185 |
+
if ( is_null( $blog['total_attachments'] ) ) {
|
186 |
+
// Handle theme mods
|
187 |
+
$this->upgrade_theme_mods( $blog['prefix'] );
|
188 |
+
|
189 |
+
// Count total attachments
|
190 |
+
$count = $this->as3cf->count_attachments( $blog['prefix'], true );
|
191 |
+
|
192 |
+
// Update blog session data
|
193 |
+
$this->session['blogs'][ $blog_id ]['total_attachments'] = $count;
|
194 |
+
$this->session['total_attachments'] += $count;
|
195 |
+
}
|
196 |
+
|
197 |
+
if ( is_null( $blog['highest_post_id'] ) ) {
|
198 |
+
// Retrieve highest post ID
|
199 |
+
$this->session['blogs'][ $blog_id ]['highest_post_id'] = $this->get_highest_post_id( $blog['prefix'] );
|
200 |
+
}
|
201 |
+
}
|
202 |
+
|
203 |
+
$this->session['blogs_processed'] = true;
|
204 |
+
|
205 |
+
return true;
|
206 |
+
}
|
207 |
+
|
208 |
+
/**
|
209 |
+
* Get highest post ID.
|
210 |
+
*
|
211 |
+
* @param string $prefix
|
212 |
+
*
|
213 |
+
* @return int
|
214 |
+
*/
|
215 |
+
protected function get_highest_post_id( $prefix ) {
|
216 |
+
global $wpdb;
|
217 |
+
|
218 |
+
$sql = "SELECT ID FROM `{$prefix}posts` ORDER BY ID DESC LIMIT 1";
|
219 |
+
|
220 |
+
return (int) $wpdb->get_var( $sql );
|
221 |
+
}
|
222 |
+
|
223 |
+
/**
|
224 |
+
* All blogs processed.
|
225 |
+
*
|
226 |
+
* @return bool
|
227 |
+
*/
|
228 |
+
protected function all_blogs_processed() {
|
229 |
+
foreach ( $this->session['blogs'] as $blog ) {
|
230 |
+
if ( ! $blog['processed'] ) {
|
231 |
+
return false;
|
232 |
+
}
|
233 |
+
}
|
234 |
+
|
235 |
+
return true;
|
236 |
+
}
|
237 |
+
|
238 |
+
/**
|
239 |
+
* Upgrade theme mods. Ensures background and header images have local URLs saved to the database.
|
240 |
+
*
|
241 |
+
* @param string $prefix
|
242 |
+
*/
|
243 |
+
protected function upgrade_theme_mods( $prefix ) {
|
244 |
+
global $wpdb;
|
245 |
+
|
246 |
+
$mods = $wpdb->get_results( "SELECT * FROM `{$prefix}options` WHERE option_name LIKE 'theme_mods_%'" );
|
247 |
+
|
248 |
+
foreach ( $mods as $mod ) {
|
249 |
+
$value = maybe_unserialize( $mod->option_value );
|
250 |
+
|
251 |
+
if ( isset( $value['background_image'] ) ) {
|
252 |
+
$value['background_image'] = $this->as3cf->filter_s3->filter_customizer_image( $value['background_image'] );
|
253 |
+
}
|
254 |
+
|
255 |
+
if ( isset( $value['header_image'] ) ) {
|
256 |
+
$value['header_image'] = $this->as3cf->filter_s3->filter_customizer_image( $value['header_image'] );
|
257 |
+
}
|
258 |
+
|
259 |
+
if ( isset( $value['header_image_data'] ) ) {
|
260 |
+
$value['header_image_data'] = $this->as3cf->filter_s3->filter_header_image_data( $value['header_image_data'] );
|
261 |
+
}
|
262 |
+
|
263 |
+
$value = maybe_serialize( $value );
|
264 |
+
|
265 |
+
if ( $value !== $mod->option_value ) {
|
266 |
+
$wpdb->query( "UPDATE `{$prefix}options` SET option_value = '{$value}' WHERE option_id = '{$mod->option_id}'" );
|
267 |
+
}
|
268 |
+
}
|
269 |
+
}
|
270 |
+
|
271 |
+
/**
|
272 |
+
* Get items to process.
|
273 |
+
*
|
274 |
+
* @param string $prefix
|
275 |
+
* @param int $limit
|
276 |
+
* @param bool|mixed $offset
|
277 |
+
*
|
278 |
+
* @return array
|
279 |
+
*/
|
280 |
+
protected function get_items_to_process( $prefix, $limit, $offset = false ) {
|
281 |
+
global $wpdb;
|
282 |
+
|
283 |
+
$sql = "SELECT posts.ID FROM `{$prefix}posts` AS posts
|
284 |
+
INNER JOIN `{$prefix}postmeta` AS postmeta
|
285 |
+
ON posts.ID = postmeta.post_id
|
286 |
+
WHERE posts.post_type = 'attachment'
|
287 |
+
AND postmeta.meta_key = 'amazonS3_info'";
|
288 |
+
|
289 |
+
if ( ! empty( $offset ) ) {
|
290 |
+
$sql .= " AND posts.ID < '{$offset}'";
|
291 |
+
}
|
292 |
+
|
293 |
+
$sql .= " ORDER BY posts.ID DESC LIMIT {$limit}";
|
294 |
+
|
295 |
+
return $wpdb->get_results( $sql );
|
296 |
+
}
|
297 |
+
|
298 |
+
/**
|
299 |
+
* Upgrade attachment.
|
300 |
+
*
|
301 |
+
* @param mixed $attachment
|
302 |
+
*
|
303 |
+
* @return bool
|
304 |
+
*/
|
305 |
+
protected function upgrade_item( $attachment ) {
|
306 |
+
$limit = apply_filters( 'as3cf_update_' . $this->upgrade_name . '_sql_limit', 100000 );
|
307 |
+
$highest_post_id = $this->session['blogs'][ $this->blog_id ]['highest_post_id'];
|
308 |
+
$last_post_id = $this->session['blogs'][ $this->blog_id ]['last_post_id'];
|
309 |
+
$where_highest_id = is_null( $last_post_id ) ? $highest_post_id : $last_post_id;
|
310 |
+
$where_lowest_id = max( $where_highest_id - $limit, 0 );
|
311 |
+
|
312 |
+
while ( true ) {
|
313 |
+
$this->find_and_replace_attachment_urls( $attachment->ID, $where_lowest_id, $where_highest_id );
|
314 |
+
|
315 |
+
if ( $this->batch_limit_reached() ) {
|
316 |
+
// Batch limit reached
|
317 |
+
break;
|
318 |
+
}
|
319 |
+
|
320 |
+
if ( $where_lowest_id <= 0 ) {
|
321 |
+
// Batch completed
|
322 |
+
return true;
|
323 |
+
}
|
324 |
+
|
325 |
+
$where_highest_id = $where_lowest_id;
|
326 |
+
$where_lowest_id = max( $where_lowest_id - $limit, 0 );
|
327 |
+
}
|
328 |
+
|
329 |
+
$this->session['blogs'][ $this->blog_id ]['last_post_id'] = $where_lowest_id;
|
330 |
+
|
331 |
+
return false;
|
332 |
+
}
|
333 |
+
|
334 |
+
/**
|
335 |
+
* Find and replace embedded URLs for an attachment.
|
336 |
+
*
|
337 |
+
* @param int $attachment_id
|
338 |
+
* @param int $where_lowest_id
|
339 |
+
* @param int $where_highest_id
|
340 |
+
*/
|
341 |
+
protected function find_and_replace_attachment_urls( $attachment_id, $where_lowest_id, $where_highest_id ) {
|
342 |
+
$meta = wp_get_attachment_metadata( $attachment_id, true );
|
343 |
+
$backups = get_post_meta( $attachment_id, '_wp_attachment_backup_sizes', true );
|
344 |
+
$file_path = get_attached_file( $attachment_id, true );
|
345 |
+
|
346 |
+
$new_url = $this->as3cf->get_attachment_local_url( $attachment_id );
|
347 |
+
$old_url = $this->as3cf->maybe_remove_query_string( $this->as3cf->get_attachment_url( $attachment_id, null, null, $meta, array(), true ) );
|
348 |
+
|
349 |
+
if ( empty( $old_url ) || empty( $new_url ) ) {
|
350 |
+
return;
|
351 |
+
}
|
352 |
+
|
353 |
+
$urls = $this->get_find_and_replace_urls( $file_path, $old_url, $new_url, $meta, $backups );
|
354 |
+
|
355 |
+
$this->process_pair_replacement( $urls, $where_lowest_id, $where_highest_id );
|
356 |
+
}
|
357 |
+
|
358 |
+
/**
|
359 |
+
* Get find and replace URLs.
|
360 |
+
*
|
361 |
+
* @param string $file_path
|
362 |
+
* @param string $old_url
|
363 |
+
* @param string $new_url
|
364 |
+
* @param array $meta
|
365 |
+
* @param array|string $backups
|
366 |
+
*
|
367 |
+
* @return array
|
368 |
+
*/
|
369 |
+
protected function get_find_and_replace_urls( $file_path, $old_url, $new_url, $meta, $backups = '' ) {
|
370 |
+
$url_pairs = array();
|
371 |
+
$file_name = basename( $file_path );
|
372 |
+
$old_file_name = basename( $old_url );
|
373 |
+
$new_file_name = basename( $new_url );
|
374 |
+
|
375 |
+
// Full size image
|
376 |
+
$url_pairs[] = $this->add_url_pair( $file_path, $file_name, $old_url, $old_file_name, $new_url, $new_file_name );
|
377 |
+
|
378 |
+
if ( isset( $meta['thumb'] ) && $meta['thumb'] ) {
|
379 |
+
// Replace URLs for legacy thumbnail of image
|
380 |
+
$url_pairs[] = $this->add_url_pair( $file_path, $file_name, $old_url, $old_file_name, $new_url, $new_file_name, $meta['thumb'] );
|
381 |
+
}
|
382 |
+
|
383 |
+
if ( ! empty( $meta['sizes'] ) ) {
|
384 |
+
// Replace URLs for intermediate sizes of image
|
385 |
+
foreach ( $meta['sizes'] as $key => $size ) {
|
386 |
+
if ( ! isset( $size['file'] ) ) {
|
387 |
+
continue;
|
388 |
+
}
|
389 |
+
|
390 |
+
$url_pairs[] = $this->add_url_pair( $file_path, $file_name, $old_url, $old_file_name, $new_url, $new_file_name, $size['file'] );
|
391 |
+
}
|
392 |
+
}
|
393 |
+
|
394 |
+
if ( ! empty( $backups ) ) {
|
395 |
+
// Replace URLs for backup images
|
396 |
+
foreach ( $backups as $backup ) {
|
397 |
+
if ( ! isset( $backup['file'] ) ) {
|
398 |
+
continue;
|
399 |
+
}
|
400 |
+
|
401 |
+
$url_pairs[] = $this->add_url_pair( $file_path, $file_name, $old_url, $old_file_name, $new_url, $new_file_name, $backup['file'] );
|
402 |
+
}
|
403 |
+
}
|
404 |
+
|
405 |
+
// Also find encoded file names
|
406 |
+
$url_pairs = $this->maybe_add_encoded_url_pairs( $url_pairs );
|
407 |
+
|
408 |
+
// Remove URL protocols
|
409 |
+
foreach ( $url_pairs as $key => $url_pair ) {
|
410 |
+
$url_pairs[ $key ]['old_url'] = $this->as3cf->remove_scheme( $url_pair['old_url'] );
|
411 |
+
$url_pairs[ $key ]['new_url'] = $this->as3cf->remove_scheme( $url_pair['new_url'] );
|
412 |
+
}
|
413 |
+
|
414 |
+
return apply_filters( 'as3cf_find_replace_url_pairs', $url_pairs, $file_path, $old_url, $new_url, $meta );
|
415 |
+
}
|
416 |
+
|
417 |
+
/**
|
418 |
+
* Add URL pair.
|
419 |
+
*
|
420 |
+
* @param string $file_path
|
421 |
+
* @param string $file_name
|
422 |
+
* @param string $old_url
|
423 |
+
* @param string $old_file_name
|
424 |
+
* @param string $new_url
|
425 |
+
* @param string $new_file_name
|
426 |
+
* @param string|bool $size_file_name
|
427 |
+
*
|
428 |
+
* @return array
|
429 |
+
*/
|
430 |
+
protected function add_url_pair( $file_path, $file_name, $old_url, $old_file_name, $new_url, $new_file_name, $size_file_name = false ) {
|
431 |
+
if ( ! $size_file_name ) {
|
432 |
+
return array(
|
433 |
+
'old_path' => $file_path,
|
434 |
+
'old_url' => str_replace( $old_file_name, $file_name, $old_url ),
|
435 |
+
'new_url' => $new_url,
|
436 |
+
);
|
437 |
+
}
|
438 |
+
|
439 |
+
return array(
|
440 |
+
'old_path' => str_replace( $file_name, $size_file_name, $file_path ),
|
441 |
+
'old_url' => str_replace( $old_file_name, $size_file_name, $old_url ),
|
442 |
+
'new_url' => str_replace( $new_file_name, $size_file_name, $new_url ),
|
443 |
+
);
|
444 |
+
}
|
445 |
+
|
446 |
+
/**
|
447 |
+
* Maybe add encoded URL pairs.
|
448 |
+
*
|
449 |
+
* @param array $url_pairs
|
450 |
+
*
|
451 |
+
* @return array
|
452 |
+
*/
|
453 |
+
protected function maybe_add_encoded_url_pairs( $url_pairs ) {
|
454 |
+
foreach ( $url_pairs as $url_pair ) {
|
455 |
+
$file_name = basename( $url_pair['old_url'] );
|
456 |
+
$encoded_file_name = $this->as3cf->encode_filename_in_path( $file_name );
|
457 |
+
|
458 |
+
if ( $file_name !== $encoded_file_name ) {
|
459 |
+
$url_pair['old_url'] = str_replace( $file_name, $encoded_file_name, $url_pair['old_url'] );
|
460 |
+
$url_pairs[] = $url_pair;
|
461 |
+
}
|
462 |
+
}
|
463 |
+
|
464 |
+
return $url_pairs;
|
465 |
+
}
|
466 |
+
|
467 |
+
/**
|
468 |
+
* Perform the find and replace in the database of old and new URLs.
|
469 |
+
*
|
470 |
+
* @param array $url_pairs
|
471 |
+
* @param int $where_lowest_id
|
472 |
+
* @param int $where_highest_id
|
473 |
+
*/
|
474 |
+
protected function process_pair_replacement( $url_pairs, $where_lowest_id, $where_highest_id ) {
|
475 |
+
global $wpdb;
|
476 |
+
|
477 |
+
$posts = $wpdb->get_results( $this->generate_select_sql( $url_pairs, $where_lowest_id, $where_highest_id ) );
|
478 |
+
|
479 |
+
if ( empty( $posts ) ) {
|
480 |
+
// Nothing to process, move on
|
481 |
+
return;
|
482 |
+
}
|
483 |
+
|
484 |
+
// Limit REPLACE statements to 10 per query and INTO to 100 per query
|
485 |
+
$url_pairs = array_chunk( $url_pairs, 10 );
|
486 |
+
$ids = array_chunk( wp_list_pluck( $posts, 'ID' ), 100 );
|
487 |
+
|
488 |
+
foreach ( $url_pairs as $url_pairs_chunk ) {
|
489 |
+
foreach ( $ids as $ids_chunk ) {
|
490 |
+
$wpdb->query( $this->generate_update_sql( $url_pairs_chunk, $ids_chunk ) );
|
491 |
+
}
|
492 |
+
}
|
493 |
+
}
|
494 |
+
|
495 |
+
/**
|
496 |
+
* Generate select SQL.
|
497 |
+
*
|
498 |
+
* @param array $url_pairs
|
499 |
+
* @param int $where_lowest_id
|
500 |
+
* @param int $where_highest_id
|
501 |
+
*
|
502 |
+
* @return string
|
503 |
+
*/
|
504 |
+
protected function generate_select_sql( $url_pairs, $where_lowest_id, $where_highest_id ) {
|
505 |
+
global $wpdb;
|
506 |
+
|
507 |
+
$paths = array();
|
508 |
+
|
509 |
+
// Get unique URLs without size string and extension
|
510 |
+
foreach ( $url_pairs as $url_pair ) {
|
511 |
+
$paths[] = $this->as3cf->remove_size_from_filename( $url_pair['old_url'], true );
|
512 |
+
}
|
513 |
+
|
514 |
+
$paths = array_unique( $paths );
|
515 |
+
$sql = '';
|
516 |
+
|
517 |
+
foreach ( $paths as $path ) {
|
518 |
+
if ( ! empty( $sql ) ) {
|
519 |
+
$sql .= " OR ";
|
520 |
+
}
|
521 |
+
|
522 |
+
$sql .= "post_content LIKE '%{$path}%'";
|
523 |
+
}
|
524 |
+
|
525 |
+
return "SELECT ID FROM {$wpdb->posts} WHERE ID > {$where_lowest_id} AND ID <= {$where_highest_id} AND ({$sql})";
|
526 |
+
}
|
527 |
+
|
528 |
+
/**
|
529 |
+
* Generate update SQL.
|
530 |
+
*
|
531 |
+
* @param array $url_pairs
|
532 |
+
* @param array $ids
|
533 |
+
*
|
534 |
+
* @return string
|
535 |
+
*/
|
536 |
+
protected function generate_update_sql( $url_pairs, $ids ) {
|
537 |
+
global $wpdb;
|
538 |
+
|
539 |
+
$ids = implode( ',', $ids );
|
540 |
+
$sql = '';
|
541 |
+
|
542 |
+
foreach ( $url_pairs as $pair ) {
|
543 |
+
if ( ! isset( $pair['old_url'] ) || ! isset( $pair['new_url'] ) ) {
|
544 |
+
// We need both URLs for the find and replace
|
545 |
+
continue;
|
546 |
+
}
|
547 |
+
|
548 |
+
if ( empty( $sql ) ) {
|
549 |
+
// First replace statement
|
550 |
+
$sql = "REPLACE(post_content, '{$pair['old_url']}', '{$pair['new_url']}')";
|
551 |
+
} else {
|
552 |
+
// Nested replace statement
|
553 |
+
$sql = "REPLACE({$sql}, '{$pair['old_url']}', '{$pair['new_url']}')";
|
554 |
+
}
|
555 |
+
}
|
556 |
+
|
557 |
+
return "UPDATE {$wpdb->posts} SET `post_content` = {$sql} WHERE `ID` IN({$ids})";
|
558 |
+
}
|
559 |
+
|
560 |
+
/**
|
561 |
+
* Get running message.
|
562 |
+
*
|
563 |
+
* @return string
|
564 |
+
*/
|
565 |
+
protected function get_running_message() {
|
566 |
+
return sprintf( __( '<strong>Running 1.2 Upgrade%1$s</strong><br>A find & replace is running in the background to update URLs in your content. %2$s', 'amazon-s3-and-cloudfront' ), $this->get_progress_text(), $this->get_generic_message() );
|
567 |
+
}
|
568 |
+
|
569 |
+
/**
|
570 |
+
* Get paused message.
|
571 |
+
*
|
572 |
+
* @return string
|
573 |
+
*/
|
574 |
+
protected function get_paused_message() {
|
575 |
+
return sprintf( __( '<strong>Paused 1.2 Upgrade</strong><br>The find & replace to update URLs in your content has been paused. %s', 'amazon-s3-and-cloudfront' ), $this->get_generic_message() );
|
576 |
+
}
|
577 |
+
|
578 |
+
/**
|
579 |
+
* Get notice message.
|
580 |
+
*
|
581 |
+
* @return string
|
582 |
+
*/
|
583 |
+
protected function get_generic_message() {
|
584 |
+
$link_text = __( 'See our documentation', 'amazon-s3-and-cloudfront' );
|
585 |
+
$link = $this->as3cf->dbrains_link( 'https://deliciousbrains.com/wp-offload-s3/doc/version-1-2-upgrade', $link_text );
|
586 |
+
|
587 |
+
return sprintf( __( '%s for details on why we’re doing this, why it runs slowly, and how to make it run faster.', 'amazon-s3-and-cloudfront' ), $link );
|
588 |
+
}
|
589 |
+
|
590 |
+
/**
|
591 |
+
* Calculate progress.
|
592 |
+
*
|
593 |
+
* @return bool|int|float
|
594 |
+
*/
|
595 |
+
protected function calculate_progress() {
|
596 |
+
$session = $this->get_session();
|
597 |
+
|
598 |
+
if ( ! isset( $session['total_attachments'] ) || ! isset( $session['processed_attachments'] ) ) {
|
599 |
+
// Session data not created, return
|
600 |
+
return false;
|
601 |
+
}
|
602 |
+
|
603 |
+
if ( ! $session['blogs_processed'] || is_null( $session['total_attachments'] ) || is_null( $session['processed_attachments'] ) ) {
|
604 |
+
// Still processing blogs, return 0
|
605 |
+
return 0;
|
606 |
+
}
|
607 |
+
|
608 |
+
return round( $session['processed_attachments'] / $session['total_attachments'] * 100, 2 );
|
609 |
+
}
|
610 |
+
|
611 |
+
/**
|
612 |
+
* Batch limit reached.
|
613 |
+
*
|
614 |
+
* @return bool
|
615 |
+
*/
|
616 |
+
protected function batch_limit_reached() {
|
617 |
+
if ( time() >= $this->finish || $this->as3cf->memory_exceeded( 'as3cf_update_' . $this->upgrade_name . '_memory_exceeded' ) ) {
|
618 |
+
return true;
|
619 |
+
}
|
620 |
+
|
621 |
+
return false;
|
622 |
+
}
|
623 |
+
}
|
classes/upgrades/as3cf-edd-replace-urls.php
ADDED
@@ -0,0 +1,105 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// Exit if accessed directly
|
4 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
5 |
+
exit;
|
6 |
+
}
|
7 |
+
|
8 |
+
/**
|
9 |
+
* AS3CF_Upgrade_EDD_Replace_URLs Class
|
10 |
+
*
|
11 |
+
* This class handles replacing all S3 URLs in EDD
|
12 |
+
* downloads with the local URL.
|
13 |
+
*
|
14 |
+
* @since 1.2
|
15 |
+
*/
|
16 |
+
class AS3CF_Upgrade_EDD_Replace_URLs extends AS3CF_Upgrade {
|
17 |
+
|
18 |
+
/**
|
19 |
+
* Initiate the upgrade
|
20 |
+
*
|
21 |
+
* @param object $as3cf Instance of calling class
|
22 |
+
*/
|
23 |
+
public function __construct( $as3cf ) {
|
24 |
+
$this->upgrade_id = 5;
|
25 |
+
$this->upgrade_name = 'replace_edd_urls';
|
26 |
+
$this->upgrade_type = 'post meta';
|
27 |
+
|
28 |
+
$this->running_update_text = __( 'and ensuring that only the local URL exists in EDD post meta.', 'amazon-s3-and-cloudfront' );
|
29 |
+
|
30 |
+
parent::__construct( $as3cf );
|
31 |
+
}
|
32 |
+
|
33 |
+
/**
|
34 |
+
* Count attachments to process.
|
35 |
+
*
|
36 |
+
* @return int
|
37 |
+
*/
|
38 |
+
protected function count_items_to_process() {
|
39 |
+
global $wpdb;
|
40 |
+
|
41 |
+
$table_prefixes = $this->as3cf->get_all_blog_table_prefixes();
|
42 |
+
$count = 0;
|
43 |
+
|
44 |
+
foreach ( $table_prefixes as $blog_id => $table_prefix ) {
|
45 |
+
$count += (int) $wpdb->get_var( "SELECT COUNT(*) FROM `{$table_prefix}postmeta` WHERE meta_key = 'edd_download_files'" );
|
46 |
+
}
|
47 |
+
|
48 |
+
return $count;
|
49 |
+
}
|
50 |
+
|
51 |
+
/**
|
52 |
+
* Get items to process.
|
53 |
+
*
|
54 |
+
* @param string $prefix
|
55 |
+
* @param int $limit
|
56 |
+
* @param bool|mixed $offset
|
57 |
+
*
|
58 |
+
* @return array
|
59 |
+
*/
|
60 |
+
protected function get_items_to_process( $prefix, $limit, $offset = false ) {
|
61 |
+
global $wpdb;
|
62 |
+
|
63 |
+
$sql = "SELECT * FROM `{$prefix}postmeta` WHERE meta_key = 'edd_download_files'";
|
64 |
+
|
65 |
+
if ( false !== $offset ) {
|
66 |
+
$sql .= " AND meta_id > {$offset->meta_id}";
|
67 |
+
}
|
68 |
+
|
69 |
+
$sql .= " LIMIT {$limit}";
|
70 |
+
|
71 |
+
return $wpdb->get_results( $sql );
|
72 |
+
}
|
73 |
+
|
74 |
+
/**
|
75 |
+
* Upgrade item.
|
76 |
+
*
|
77 |
+
* @param mixed $item
|
78 |
+
*
|
79 |
+
* @return bool
|
80 |
+
*/
|
81 |
+
protected function upgrade_item( $item ) {
|
82 |
+
$attachments = maybe_unserialize( $item->meta_value );
|
83 |
+
|
84 |
+
if ( ! is_array( $attachments ) || empty( $attachments ) ) {
|
85 |
+
// No attachments to process, return
|
86 |
+
return false;
|
87 |
+
}
|
88 |
+
|
89 |
+
foreach ( $attachments as $key => $attachment ) {
|
90 |
+
if ( ! isset( $attachment['attachment_id'] ) || ! isset( $attachment['file'] ) ) {
|
91 |
+
// Can't determine ID or file, continue
|
92 |
+
continue;
|
93 |
+
}
|
94 |
+
|
95 |
+
if ( $url = $this->as3cf->get_attachment_local_url( $attachment['attachment_id'] ) ) {
|
96 |
+
$attachments[ $key ]['file'] = $url;
|
97 |
+
}
|
98 |
+
}
|
99 |
+
|
100 |
+
update_post_meta( $item->post_id, 'edd_download_files', $attachments );
|
101 |
+
|
102 |
+
return true;
|
103 |
+
}
|
104 |
+
|
105 |
+
}
|
classes/upgrades/as3cf-file-sizes.php
CHANGED
@@ -42,11 +42,11 @@ class AS3CF_Upgrade_File_Sizes extends AS3CF_Upgrade {
|
|
42 |
/**
|
43 |
* Get the total file sizes for an attachment and associated files.
|
44 |
*
|
45 |
-
* @param $attachment
|
46 |
*
|
47 |
* @return bool
|
48 |
*/
|
49 |
-
function
|
50 |
$s3object = unserialize( $attachment->s3object );
|
51 |
if ( false === $s3object ) {
|
52 |
AS3CF_Error::log( 'Failed to unserialize S3 meta for attachment ' . $attachment->ID . ': ' . $attachment->s3object );
|
@@ -130,7 +130,7 @@ class AS3CF_Upgrade_File_Sizes extends AS3CF_Upgrade {
|
|
130 |
*
|
131 |
* @return int
|
132 |
*/
|
133 |
-
function
|
134 |
// get the table prefixes for all the blogs
|
135 |
$table_prefixes = $this->as3cf->get_all_blog_table_prefixes();
|
136 |
$all_count = 0;
|
@@ -146,12 +146,13 @@ class AS3CF_Upgrade_File_Sizes extends AS3CF_Upgrade {
|
|
146 |
/**
|
147 |
* Get all attachments that don't have region in their S3 meta data for a blog
|
148 |
*
|
149 |
-
* @param string
|
150 |
-
* @param int
|
|
|
151 |
*
|
152 |
-
* @return
|
153 |
*/
|
154 |
-
function
|
155 |
$attachments = $this->get_attachments_removed_from_server( $prefix, false, $limit );
|
156 |
|
157 |
return $attachments;
|
@@ -166,7 +167,7 @@ class AS3CF_Upgrade_File_Sizes extends AS3CF_Upgrade {
|
|
166 |
*
|
167 |
* @return mixed
|
168 |
*/
|
169 |
-
function get_s3_attachments( $prefix, $limit = null ) {
|
170 |
global $wpdb;
|
171 |
|
172 |
$sql = "SELECT pm1.`post_id` as `ID`, pm1.`meta_value` AS 's3object'
|
@@ -195,7 +196,7 @@ class AS3CF_Upgrade_File_Sizes extends AS3CF_Upgrade {
|
|
195 |
*
|
196 |
* @return array|int
|
197 |
*/
|
198 |
-
function get_attachments_removed_from_server( $prefix, $count = false, $limit = null ) {
|
199 |
$all_attachments = $this->get_s3_attachments( $prefix, $limit );
|
200 |
$attachments = array();
|
201 |
|
42 |
/**
|
43 |
* Get the total file sizes for an attachment and associated files.
|
44 |
*
|
45 |
+
* @param mixed $attachment
|
46 |
*
|
47 |
* @return bool
|
48 |
*/
|
49 |
+
protected function upgrade_item( $attachment ) {
|
50 |
$s3object = unserialize( $attachment->s3object );
|
51 |
if ( false === $s3object ) {
|
52 |
AS3CF_Error::log( 'Failed to unserialize S3 meta for attachment ' . $attachment->ID . ': ' . $attachment->s3object );
|
130 |
*
|
131 |
* @return int
|
132 |
*/
|
133 |
+
protected function count_items_to_process() {
|
134 |
// get the table prefixes for all the blogs
|
135 |
$table_prefixes = $this->as3cf->get_all_blog_table_prefixes();
|
136 |
$all_count = 0;
|
146 |
/**
|
147 |
* Get all attachments that don't have region in their S3 meta data for a blog
|
148 |
*
|
149 |
+
* @param string $prefix
|
150 |
+
* @param int $limit
|
151 |
+
* @param bool|mixed $offset
|
152 |
*
|
153 |
+
* @return array
|
154 |
*/
|
155 |
+
protected function get_items_to_process( $prefix, $limit, $offset = false ) {
|
156 |
$attachments = $this->get_attachments_removed_from_server( $prefix, false, $limit );
|
157 |
|
158 |
return $attachments;
|
167 |
*
|
168 |
* @return mixed
|
169 |
*/
|
170 |
+
protected function get_s3_attachments( $prefix, $limit = null ) {
|
171 |
global $wpdb;
|
172 |
|
173 |
$sql = "SELECT pm1.`post_id` as `ID`, pm1.`meta_value` AS 's3object'
|
196 |
*
|
197 |
* @return array|int
|
198 |
*/
|
199 |
+
protected function get_attachments_removed_from_server( $prefix, $count = false, $limit = null ) {
|
200 |
$all_attachments = $this->get_s3_attachments( $prefix, $limit );
|
201 |
$attachments = array();
|
202 |
|
classes/upgrades/as3cf-meta-wp-error.php
CHANGED
@@ -43,11 +43,11 @@ class AS3CF_Upgrade_Meta_WP_Error extends AS3CF_Upgrade {
|
|
43 |
/**
|
44 |
* Rebuild the attachment metadata for an attachment
|
45 |
*
|
46 |
-
* @param $attachment
|
47 |
*
|
48 |
* @return bool
|
49 |
*/
|
50 |
-
function
|
51 |
$s3object = unserialize( $attachment->s3object );
|
52 |
if ( false === $s3object ) {
|
53 |
AS3CF_Error::log( 'Failed to unserialize S3 meta for attachment ' . $attachment->ID . ': ' . $attachment->s3object );
|
@@ -91,7 +91,7 @@ class AS3CF_Upgrade_Meta_WP_Error extends AS3CF_Upgrade {
|
|
91 |
*
|
92 |
* @return int
|
93 |
*/
|
94 |
-
function
|
95 |
// get the table prefixes for all the blogs
|
96 |
$table_prefixes = $this->as3cf->get_all_blog_table_prefixes();
|
97 |
$all_count = 0;
|
@@ -107,12 +107,13 @@ class AS3CF_Upgrade_Meta_WP_Error extends AS3CF_Upgrade {
|
|
107 |
/**
|
108 |
* Get all attachments that don't have region in their S3 meta data for a blog
|
109 |
*
|
110 |
-
* @param string
|
111 |
-
* @param int
|
|
|
112 |
*
|
113 |
-
* @return
|
114 |
*/
|
115 |
-
function
|
116 |
$attachments = $this->get_attachments_with_error_metadata( $prefix, false, $limit );
|
117 |
|
118 |
return $attachments;
|
@@ -127,7 +128,7 @@ class AS3CF_Upgrade_Meta_WP_Error extends AS3CF_Upgrade {
|
|
127 |
*
|
128 |
* @return array|int
|
129 |
*/
|
130 |
-
function get_attachments_with_error_metadata( $prefix, $count = false, $limit = null ) {
|
131 |
global $wpdb;
|
132 |
|
133 |
$sql = "FROM `{$prefix}postmeta` pm1
|
43 |
/**
|
44 |
* Rebuild the attachment metadata for an attachment
|
45 |
*
|
46 |
+
* @param mixed $attachment
|
47 |
*
|
48 |
* @return bool
|
49 |
*/
|
50 |
+
protected function upgrade_item( $attachment ) {
|
51 |
$s3object = unserialize( $attachment->s3object );
|
52 |
if ( false === $s3object ) {
|
53 |
AS3CF_Error::log( 'Failed to unserialize S3 meta for attachment ' . $attachment->ID . ': ' . $attachment->s3object );
|
91 |
*
|
92 |
* @return int
|
93 |
*/
|
94 |
+
protected function count_items_to_process() {
|
95 |
// get the table prefixes for all the blogs
|
96 |
$table_prefixes = $this->as3cf->get_all_blog_table_prefixes();
|
97 |
$all_count = 0;
|
107 |
/**
|
108 |
* Get all attachments that don't have region in their S3 meta data for a blog
|
109 |
*
|
110 |
+
* @param string $prefix
|
111 |
+
* @param int $limit
|
112 |
+
* @param bool|mixed $offset
|
113 |
*
|
114 |
+
* @return array
|
115 |
*/
|
116 |
+
protected function get_items_to_process( $prefix, $limit, $offset = false ) {
|
117 |
$attachments = $this->get_attachments_with_error_metadata( $prefix, false, $limit );
|
118 |
|
119 |
return $attachments;
|
128 |
*
|
129 |
* @return array|int
|
130 |
*/
|
131 |
+
protected function get_attachments_with_error_metadata( $prefix, $count = false, $limit = null ) {
|
132 |
global $wpdb;
|
133 |
|
134 |
$sql = "FROM `{$prefix}postmeta` pm1
|
classes/upgrades/as3cf-region-meta.php
CHANGED
@@ -41,11 +41,11 @@ class AS3CF_Upgrade_Region_Meta extends AS3CF_Upgrade {
|
|
41 |
/**
|
42 |
* Get the region for the bucket where an attachment is located, update the S3 meta.
|
43 |
*
|
44 |
-
* @param $attachment
|
45 |
*
|
46 |
* @return bool
|
47 |
*/
|
48 |
-
function
|
49 |
$s3object = unserialize( $attachment->s3object );
|
50 |
if ( false === $s3object ) {
|
51 |
AS3CF_Error::log( 'Failed to unserialize S3 meta for attachment ' . $attachment->ID . ': ' . $attachment->s3object );
|
@@ -71,7 +71,7 @@ class AS3CF_Upgrade_Region_Meta extends AS3CF_Upgrade {
|
|
71 |
*
|
72 |
* @return int
|
73 |
*/
|
74 |
-
function
|
75 |
// get the table prefixes for all the blogs
|
76 |
$table_prefixes = $this->as3cf->get_all_blog_table_prefixes();
|
77 |
$all_count = 0;
|
@@ -87,12 +87,13 @@ class AS3CF_Upgrade_Region_Meta extends AS3CF_Upgrade {
|
|
87 |
/**
|
88 |
* Get all attachments that don't have region in their S3 meta data for a blog
|
89 |
*
|
90 |
-
* @param string
|
91 |
-
* @param int
|
|
|
92 |
*
|
93 |
-
* @return
|
94 |
*/
|
95 |
-
function
|
96 |
$attachments = $this->get_attachments_without_region_results( $prefix, false, $limit );
|
97 |
|
98 |
return $attachments;
|
@@ -104,7 +105,7 @@ class AS3CF_Upgrade_Region_Meta extends AS3CF_Upgrade {
|
|
104 |
*
|
105 |
* @return int
|
106 |
*/
|
107 |
-
function count_attachments_without_region( $prefix ) {
|
108 |
$count = $this->get_attachments_without_region_results( $prefix, true );
|
109 |
|
110 |
return $count;
|
@@ -119,7 +120,7 @@ class AS3CF_Upgrade_Region_Meta extends AS3CF_Upgrade {
|
|
119 |
*
|
120 |
* @return mixed
|
121 |
*/
|
122 |
-
function get_attachments_without_region_results( $prefix, $count = false, $limit = null ) {
|
123 |
global $wpdb;
|
124 |
|
125 |
$sql = " FROM `{$prefix}postmeta`
|
41 |
/**
|
42 |
* Get the region for the bucket where an attachment is located, update the S3 meta.
|
43 |
*
|
44 |
+
* @param mixed $attachment
|
45 |
*
|
46 |
* @return bool
|
47 |
*/
|
48 |
+
protected function upgrade_item( $attachment ) {
|
49 |
$s3object = unserialize( $attachment->s3object );
|
50 |
if ( false === $s3object ) {
|
51 |
AS3CF_Error::log( 'Failed to unserialize S3 meta for attachment ' . $attachment->ID . ': ' . $attachment->s3object );
|
71 |
*
|
72 |
* @return int
|
73 |
*/
|
74 |
+
protected function count_items_to_process() {
|
75 |
// get the table prefixes for all the blogs
|
76 |
$table_prefixes = $this->as3cf->get_all_blog_table_prefixes();
|
77 |
$all_count = 0;
|
87 |
/**
|
88 |
* Get all attachments that don't have region in their S3 meta data for a blog
|
89 |
*
|
90 |
+
* @param string $prefix
|
91 |
+
* @param int $limit
|
92 |
+
* @param bool|mixed $offset
|
93 |
*
|
94 |
+
* @return array
|
95 |
*/
|
96 |
+
protected function get_items_to_process( $prefix, $limit, $offset = false ) {
|
97 |
$attachments = $this->get_attachments_without_region_results( $prefix, false, $limit );
|
98 |
|
99 |
return $attachments;
|
105 |
*
|
106 |
* @return int
|
107 |
*/
|
108 |
+
protected function count_attachments_without_region( $prefix ) {
|
109 |
$count = $this->get_attachments_without_region_results( $prefix, true );
|
110 |
|
111 |
return $count;
|
120 |
*
|
121 |
* @return mixed
|
122 |
*/
|
123 |
+
protected function get_attachments_without_region_results( $prefix, $count = false, $limit = null ) {
|
124 |
global $wpdb;
|
125 |
|
126 |
$sql = " FROM `{$prefix}postmeta`
|
languages/amazon-s3-and-cloudfront-en.pot
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
# SOME DESCRIPTIVE TITLE.
|
2 |
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
3 |
-
# This file is distributed under the same license as the
|
4 |
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
5 |
#
|
6 |
#, fuzzy
|
@@ -8,7 +8,7 @@ msgid ""
|
|
8 |
msgstr ""
|
9 |
"Project-Id-Version: amazon-s3-and-cloudfront\n"
|
10 |
"Report-Msgid-Bugs-To: nom@deliciousbrains.com\n"
|
11 |
-
"POT-Creation-Date: 2016-
|
12 |
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
13 |
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
14 |
"Language-Team: LANGUAGE <LL@li.org>\n"
|
@@ -17,135 +17,135 @@ msgstr ""
|
|
17 |
"Content-Type: text/plain; charset=UTF-8\n"
|
18 |
"Content-Transfer-Encoding: 8bit\n"
|
19 |
|
20 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
21 |
msgid "Offload S3 Lite"
|
22 |
msgstr ""
|
23 |
|
24 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
25 |
msgid "S3 and CloudFront"
|
26 |
msgstr ""
|
27 |
|
28 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
29 |
#: view/bucket-setting.php:18
|
30 |
msgid "defined in wp-config.php"
|
31 |
msgstr ""
|
32 |
|
33 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
34 |
msgid "Upload aborted by filter 'as3cf_pre_upload_attachment'"
|
35 |
msgstr ""
|
36 |
|
37 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
38 |
#, php-format
|
39 |
msgid "File %s does not exist"
|
40 |
msgstr ""
|
41 |
|
42 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
43 |
#, php-format
|
44 |
msgid "Mime type %s is not allowed"
|
45 |
msgstr ""
|
46 |
|
47 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
48 |
#, php-format
|
49 |
msgid "Error uploading %s to S3: %s"
|
50 |
msgstr ""
|
51 |
|
52 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
53 |
msgid "Cheatin’ eh?"
|
54 |
msgstr ""
|
55 |
|
56 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
57 |
msgid "You do not have sufficient permissions to access this page."
|
58 |
msgstr ""
|
59 |
|
60 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
61 |
msgid "No bucket name provided."
|
62 |
msgstr ""
|
63 |
|
64 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
65 |
msgid "Error Getting Bucket Region"
|
66 |
msgstr ""
|
67 |
|
68 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
69 |
#, php-format
|
70 |
msgid "There was an error attempting to get the region of the bucket %s: %s"
|
71 |
msgstr ""
|
72 |
|
73 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
74 |
msgid ""
|
75 |
"This is a test file to check if the user has write permission to S3. Delete "
|
76 |
"me if found."
|
77 |
msgstr ""
|
78 |
|
79 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
80 |
#, php-format
|
81 |
msgid ""
|
82 |
"There was an error attempting to check the permissions of the bucket %s: %s"
|
83 |
msgstr ""
|
84 |
|
85 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
86 |
msgid "Error creating bucket"
|
87 |
msgstr ""
|
88 |
|
89 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
90 |
msgid "Bucket name too short."
|
91 |
msgstr ""
|
92 |
|
93 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
94 |
msgid "Bucket name too long."
|
95 |
msgstr ""
|
96 |
|
97 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
98 |
msgid ""
|
99 |
"Invalid character. Bucket names can contain lowercase letters, numbers, "
|
100 |
"periods and hyphens."
|
101 |
msgstr ""
|
102 |
|
103 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
104 |
msgid "Error saving bucket"
|
105 |
msgstr ""
|
106 |
|
107 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
108 |
msgid "Error fetching buckets"
|
109 |
msgstr ""
|
110 |
|
111 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
112 |
msgid "Error getting URL preview: "
|
113 |
msgstr ""
|
114 |
|
115 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
116 |
msgid "The changes you made will be lost if you navigate away from this page"
|
117 |
msgstr ""
|
118 |
|
119 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
120 |
msgid "Getting diagnostic info..."
|
121 |
msgstr ""
|
122 |
|
123 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
124 |
msgid "Error getting diagnostic info: "
|
125 |
msgstr ""
|
126 |
|
127 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
128 |
msgid "Cheatin' eh?"
|
129 |
msgstr ""
|
130 |
|
131 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
132 |
msgctxt "Show the media library tab"
|
133 |
msgid "Media Library"
|
134 |
msgstr ""
|
135 |
|
136 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
137 |
msgctxt "Show the support tab"
|
138 |
msgid "Support"
|
139 |
msgstr ""
|
140 |
|
141 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
142 |
#, php-format
|
143 |
msgid ""
|
144 |
"<strong>WP Offload S3</strong> — The file %s has been given %s "
|
145 |
"permissions on Amazon S3."
|
146 |
msgstr ""
|
147 |
|
148 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
149 |
msgid ""
|
150 |
"<strong>WP Offload S3 Requirement Missing</strong> — Looks like you "
|
151 |
"don't have an image manipulation library installed on this server and "
|
@@ -153,11 +153,11 @@ msgid ""
|
|
153 |
"Please setup GD or ImageMagick."
|
154 |
msgstr ""
|
155 |
|
156 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
157 |
msgid "Quick Start Guide"
|
158 |
msgstr ""
|
159 |
|
160 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
161 |
#, php-format
|
162 |
msgid ""
|
163 |
"Looks like we don't have write access to this bucket. It's likely that the "
|
@@ -166,7 +166,7 @@ msgid ""
|
|
166 |
"correctly."
|
167 |
msgstr ""
|
168 |
|
169 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
170 |
#, php-format
|
171 |
msgid ""
|
172 |
"Looks like we don't have access to the buckets. It's likely that the user "
|
@@ -174,50 +174,39 @@ msgid ""
|
|
174 |
"Please see our %s for instructions on setting up permissions correctly."
|
175 |
msgstr ""
|
176 |
|
177 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
178 |
msgid "WP Offload S3 Activation"
|
179 |
msgstr ""
|
180 |
|
181 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
182 |
msgid ""
|
183 |
"WP Offload S3 Lite and WP Offload S3 cannot both be active. We've "
|
184 |
"automatically deactivated WP Offload S3 Lite."
|
185 |
msgstr ""
|
186 |
|
187 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
188 |
msgid "WP Offload S3 Lite Activation"
|
189 |
msgstr ""
|
190 |
|
191 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
192 |
msgid ""
|
193 |
"WP Offload S3 Lite and WP Offload S3 cannot both be active. We've "
|
194 |
"automatically deactivated WP Offload S3."
|
195 |
msgstr ""
|
196 |
|
197 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
198 |
msgid "More info"
|
199 |
msgstr ""
|
200 |
|
201 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
202 |
-
#: classes/amazon-s3-and-cloudfront.php:3833
|
203 |
msgid "this doc"
|
204 |
msgstr ""
|
205 |
|
206 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
207 |
-
#: classes/amazon-s3-and-cloudfront.php:3835
|
208 |
msgid "WP Offload S3 Feature Removed"
|
209 |
msgstr ""
|
210 |
|
211 |
-
#: classes/amazon-s3-and-cloudfront.php:
|
212 |
-
#, php-format
|
213 |
-
msgid ""
|
214 |
-
"The \"Copy HiDPI (@2x) Images\" feature has been removed as of version 1.1 "
|
215 |
-
"of WP Offload S3. It looks like you had this feature turned on. Please see "
|
216 |
-
"%s for why we removed this feature and how you can continue copying @2x "
|
217 |
-
"images to S3."
|
218 |
-
msgstr ""
|
219 |
-
|
220 |
-
#: classes/amazon-s3-and-cloudfront.php:3836
|
221 |
#, php-format
|
222 |
msgid ""
|
223 |
"You had the \"Always non-SSL\" option selected in your settings, but we've "
|
@@ -228,23 +217,52 @@ msgid ""
|
|
228 |
"to the old behavior."
|
229 |
msgstr ""
|
230 |
|
231 |
-
#: classes/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
232 |
msgid "Error dismissing notice."
|
233 |
msgstr ""
|
234 |
|
235 |
-
#: classes/as3cf-notices.php:
|
236 |
msgid "Invalid notice ID."
|
237 |
msgstr ""
|
238 |
|
239 |
-
#: classes/as3cf-plugin-compatibility.php:
|
240 |
msgid "WP Offload S3 Compatibility Addons"
|
241 |
msgstr ""
|
242 |
|
243 |
-
#: classes/as3cf-plugin-compatibility.php:
|
244 |
msgid "compatibility addons"
|
245 |
msgstr ""
|
246 |
|
247 |
-
#: classes/as3cf-plugin-compatibility.php:
|
248 |
#, php-format
|
249 |
msgid ""
|
250 |
"To get WP Offload S3 to work with certain 3rd party plugins, you might need "
|
@@ -253,7 +271,7 @@ msgid ""
|
|
253 |
"about each addon to determine if you need it or not."
|
254 |
msgstr ""
|
255 |
|
256 |
-
#: classes/as3cf-plugin-compatibility.php:
|
257 |
#, php-format
|
258 |
msgid ""
|
259 |
"You will need to purchase a license to get access to these addons. If you're "
|
@@ -261,62 +279,100 @@ msgid ""
|
|
261 |
"to %s."
|
262 |
msgstr ""
|
263 |
|
264 |
-
#: classes/as3cf-plugin-compatibility.php:
|
265 |
msgid "View Licenses"
|
266 |
msgstr ""
|
267 |
|
268 |
-
#: classes/as3cf-plugin-compatibility.php:
|
269 |
#, php-format
|
270 |
msgid "The local directory %s does not exist and could not be created."
|
271 |
msgstr ""
|
272 |
|
273 |
-
#: classes/as3cf-plugin-compatibility.php:
|
274 |
-
#: classes/as3cf-plugin-compatibility.php:
|
275 |
#: classes/upgrades/as3cf-meta-wp-error.php:72
|
276 |
#, php-format
|
277 |
msgid "There was an error attempting to download the file %s from S3: %s"
|
278 |
msgstr ""
|
279 |
|
280 |
-
#: classes/as3cf-upgrade.php:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
281 |
#, php-format
|
282 |
msgid ""
|
283 |
-
"<strong>Running %s Update</strong> — We’re going through
|
284 |
-
"Media Library items uploaded to S3 %s This will be done quietly in
|
285 |
-
"background, processing a small batch of Media Library items every %d "
|
286 |
"minutes. There should be no noticeable impact on your server’s "
|
287 |
"performance."
|
288 |
msgstr ""
|
289 |
|
290 |
-
#: classes/as3cf-upgrade.php:
|
291 |
-
|
|
|
|
|
|
|
292 |
msgstr ""
|
293 |
|
294 |
-
#: classes/as3cf-upgrade.php:
|
295 |
#, php-format
|
296 |
msgid ""
|
297 |
-
"<strong
|
298 |
-
"
|
|
|
299 |
msgstr ""
|
300 |
|
301 |
-
#: classes/as3cf-upgrade.php:
|
302 |
-
|
|
|
303 |
msgstr ""
|
304 |
|
305 |
-
#: classes/as3cf-upgrade.php:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
306 |
#, php-format
|
307 |
msgid ""
|
308 |
-
"<strong>
|
309 |
-
"
|
310 |
-
"uploaded to S3. Please check your error log for details. (#%d)"
|
311 |
msgstr ""
|
312 |
|
313 |
-
#: classes/as3cf-
|
314 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
315 |
msgstr ""
|
316 |
|
317 |
-
#: classes/as3cf-
|
318 |
#, php-format
|
319 |
-
msgid "
|
|
|
|
|
|
|
|
|
|
|
|
|
320 |
msgstr ""
|
321 |
|
322 |
#: classes/upgrades/as3cf-file-sizes.php:37
|
@@ -415,6 +471,14 @@ msgstr ""
|
|
415 |
msgid "The %s plugin has been deactivated."
|
416 |
msgstr ""
|
417 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
418 |
#: view/bucket-select.php:3
|
419 |
msgid "Change bucket"
|
420 |
msgstr ""
|
@@ -603,62 +667,62 @@ msgstr ""
|
|
603 |
msgid "By default the path is the same as your local WordPress files."
|
604 |
msgstr ""
|
605 |
|
606 |
-
#: view/settings.php:
|
607 |
msgid "Year/Month"
|
608 |
msgstr ""
|
609 |
|
610 |
-
#: view/settings.php:
|
611 |
msgid "Add the Year/Month in the URL."
|
612 |
msgstr ""
|
613 |
|
614 |
-
#: view/settings.php:
|
615 |
msgid "Force HTTPS"
|
616 |
msgstr ""
|
617 |
|
618 |
-
#: view/settings.php:
|
619 |
msgid ""
|
620 |
"By default we use HTTPS when the request is HTTPS and regular HTTP when the "
|
621 |
"request is HTTP, but you may want to force the use of HTTPS always, "
|
622 |
"regardless of the request."
|
623 |
msgstr ""
|
624 |
|
625 |
-
#: view/settings.php:
|
626 |
msgid "Advanced Options"
|
627 |
msgstr ""
|
628 |
|
629 |
-
#: view/settings.php:
|
630 |
msgid "Remove Files From Server"
|
631 |
msgstr ""
|
632 |
|
633 |
-
#: view/settings.php:
|
634 |
msgid "Once a file has been copied to S3, remove it from the local server."
|
635 |
msgstr ""
|
636 |
|
637 |
-
#: view/settings.php:
|
638 |
msgid ""
|
639 |
"<strong>Broken URLs</strong> — There will be broken URLs for files "
|
640 |
"that don't exist locally. You can fix this by enabling <strong>Rewrite File "
|
641 |
"URLs</strong> to use the S3 URLs."
|
642 |
msgstr ""
|
643 |
|
644 |
-
#: view/settings.php:
|
645 |
#, php-format
|
646 |
msgid ""
|
647 |
"<strong>Warning</strong> — Some plugins depend on the file being "
|
648 |
"present on the local server and may not work when the file is removed. %s"
|
649 |
msgstr ""
|
650 |
|
651 |
-
#: view/settings.php:
|
652 |
msgid "Object Versioning"
|
653 |
msgstr ""
|
654 |
|
655 |
-
#: view/settings.php:
|
656 |
msgid ""
|
657 |
"Append a timestamp to the S3 file path. Recommended when using CloudFront so "
|
658 |
"you don't have to worry about cache invalidation."
|
659 |
msgstr ""
|
660 |
|
661 |
-
#: view/settings.php:
|
662 |
msgid "Save Changes"
|
663 |
msgstr ""
|
664 |
|
@@ -667,61 +731,57 @@ msgid "Upload existing Media Library to S3"
|
|
667 |
msgstr ""
|
668 |
|
669 |
#: view/sidebar.php:11
|
670 |
-
msgid "Find & replace file URLs in content"
|
671 |
-
msgstr ""
|
672 |
-
|
673 |
-
#: view/sidebar.php:12
|
674 |
msgid "Manage S3 files in WordPress"
|
675 |
msgstr ""
|
676 |
|
677 |
-
#: view/sidebar.php:
|
678 |
msgid "Assets addon - Serve your CSS & JS from S3/CloudFront"
|
679 |
msgstr ""
|
680 |
|
681 |
-
#: view/sidebar.php:
|
682 |
msgid "WooCommerce addon"
|
683 |
msgstr ""
|
684 |
|
685 |
-
#: view/sidebar.php:
|
686 |
msgid "Easy Digital Downloads addon"
|
687 |
msgstr ""
|
688 |
|
689 |
-
#: view/sidebar.php:
|
690 |
msgid "PriorityExpert™ email support"
|
691 |
msgstr ""
|
692 |
|
693 |
-
#: view/sidebar.php:
|
694 |
msgid "Visit deliciousbrains.com →"
|
695 |
msgstr ""
|
696 |
|
697 |
-
#: view/sidebar.php:
|
698 |
msgid "Get 20% Off!"
|
699 |
msgstr ""
|
700 |
|
701 |
-
#: view/sidebar.php:
|
702 |
#, php-format
|
703 |
msgid ""
|
704 |
"Submit your name and email and we’ll send you a coupon for 20% off your "
|
705 |
"upgrade."
|
706 |
msgstr ""
|
707 |
|
708 |
-
#: view/sidebar.php:
|
709 |
msgid "Your Email"
|
710 |
msgstr ""
|
711 |
|
712 |
-
#: view/sidebar.php:
|
713 |
msgid "First Name"
|
714 |
msgstr ""
|
715 |
|
716 |
-
#: view/sidebar.php:
|
717 |
msgid "Last Name"
|
718 |
msgstr ""
|
719 |
|
720 |
-
#: view/sidebar.php:
|
721 |
msgid "Send me the coupon"
|
722 |
msgstr ""
|
723 |
|
724 |
-
#: view/sidebar.php:
|
725 |
msgid ""
|
726 |
"We promise we will not use your email for anything else and you can "
|
727 |
"unsubscribe with 1-click anytime."
|
1 |
# SOME DESCRIPTIVE TITLE.
|
2 |
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
3 |
+
# This file is distributed under the same license as the PACKAGE package.
|
4 |
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
5 |
#
|
6 |
#, fuzzy
|
8 |
msgstr ""
|
9 |
"Project-Id-Version: amazon-s3-and-cloudfront\n"
|
10 |
"Report-Msgid-Bugs-To: nom@deliciousbrains.com\n"
|
11 |
+
"POT-Creation-Date: 2016-10-17 13:06+0100\n"
|
12 |
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
13 |
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
14 |
"Language-Team: LANGUAGE <LL@li.org>\n"
|
17 |
"Content-Type: text/plain; charset=UTF-8\n"
|
18 |
"Content-Transfer-Encoding: 8bit\n"
|
19 |
|
20 |
+
#: classes/amazon-s3-and-cloudfront.php:108
|
21 |
msgid "Offload S3 Lite"
|
22 |
msgstr ""
|
23 |
|
24 |
+
#: classes/amazon-s3-and-cloudfront.php:109
|
25 |
msgid "S3 and CloudFront"
|
26 |
msgstr ""
|
27 |
|
28 |
+
#: classes/amazon-s3-and-cloudfront.php:214
|
29 |
#: view/bucket-setting.php:18
|
30 |
msgid "defined in wp-config.php"
|
31 |
msgstr ""
|
32 |
|
33 |
+
#: classes/amazon-s3-and-cloudfront.php:851
|
34 |
msgid "Upload aborted by filter 'as3cf_pre_upload_attachment'"
|
35 |
msgstr ""
|
36 |
|
37 |
+
#: classes/amazon-s3-and-cloudfront.php:862
|
38 |
#, php-format
|
39 |
msgid "File %s does not exist"
|
40 |
msgstr ""
|
41 |
|
42 |
+
#: classes/amazon-s3-and-cloudfront.php:873
|
43 |
#, php-format
|
44 |
msgid "Mime type %s is not allowed"
|
45 |
msgstr ""
|
46 |
|
47 |
+
#: classes/amazon-s3-and-cloudfront.php:958
|
48 |
#, php-format
|
49 |
msgid "Error uploading %s to S3: %s"
|
50 |
msgstr ""
|
51 |
|
52 |
+
#: classes/amazon-s3-and-cloudfront.php:2134
|
53 |
msgid "Cheatin’ eh?"
|
54 |
msgstr ""
|
55 |
|
56 |
+
#: classes/amazon-s3-and-cloudfront.php:2138
|
57 |
msgid "You do not have sufficient permissions to access this page."
|
58 |
msgstr ""
|
59 |
|
60 |
+
#: classes/amazon-s3-and-cloudfront.php:2144
|
61 |
msgid "No bucket name provided."
|
62 |
msgstr ""
|
63 |
|
64 |
+
#: classes/amazon-s3-and-cloudfront.php:2429
|
65 |
msgid "Error Getting Bucket Region"
|
66 |
msgstr ""
|
67 |
|
68 |
+
#: classes/amazon-s3-and-cloudfront.php:2430
|
69 |
#, php-format
|
70 |
msgid "There was an error attempting to get the region of the bucket %s: %s"
|
71 |
msgstr ""
|
72 |
|
73 |
+
#: classes/amazon-s3-and-cloudfront.php:2550
|
74 |
msgid ""
|
75 |
"This is a test file to check if the user has write permission to S3. Delete "
|
76 |
"me if found."
|
77 |
msgstr ""
|
78 |
|
79 |
+
#: classes/amazon-s3-and-cloudfront.php:2582
|
80 |
#, php-format
|
81 |
msgid ""
|
82 |
"There was an error attempting to check the permissions of the bucket %s: %s"
|
83 |
msgstr ""
|
84 |
|
85 |
+
#: classes/amazon-s3-and-cloudfront.php:2639
|
86 |
msgid "Error creating bucket"
|
87 |
msgstr ""
|
88 |
|
89 |
+
#: classes/amazon-s3-and-cloudfront.php:2640
|
90 |
msgid "Bucket name too short."
|
91 |
msgstr ""
|
92 |
|
93 |
+
#: classes/amazon-s3-and-cloudfront.php:2641
|
94 |
msgid "Bucket name too long."
|
95 |
msgstr ""
|
96 |
|
97 |
+
#: classes/amazon-s3-and-cloudfront.php:2642
|
98 |
msgid ""
|
99 |
"Invalid character. Bucket names can contain lowercase letters, numbers, "
|
100 |
"periods and hyphens."
|
101 |
msgstr ""
|
102 |
|
103 |
+
#: classes/amazon-s3-and-cloudfront.php:2643
|
104 |
msgid "Error saving bucket"
|
105 |
msgstr ""
|
106 |
|
107 |
+
#: classes/amazon-s3-and-cloudfront.php:2644
|
108 |
msgid "Error fetching buckets"
|
109 |
msgstr ""
|
110 |
|
111 |
+
#: classes/amazon-s3-and-cloudfront.php:2645
|
112 |
msgid "Error getting URL preview: "
|
113 |
msgstr ""
|
114 |
|
115 |
+
#: classes/amazon-s3-and-cloudfront.php:2646
|
116 |
msgid "The changes you made will be lost if you navigate away from this page"
|
117 |
msgstr ""
|
118 |
|
119 |
+
#: classes/amazon-s3-and-cloudfront.php:2647
|
120 |
msgid "Getting diagnostic info..."
|
121 |
msgstr ""
|
122 |
|
123 |
+
#: classes/amazon-s3-and-cloudfront.php:2648
|
124 |
msgid "Error getting diagnostic info: "
|
125 |
msgstr ""
|
126 |
|
127 |
+
#: classes/amazon-s3-and-cloudfront.php:2716
|
128 |
msgid "Cheatin' eh?"
|
129 |
msgstr ""
|
130 |
|
131 |
+
#: classes/amazon-s3-and-cloudfront.php:2824
|
132 |
msgctxt "Show the media library tab"
|
133 |
msgid "Media Library"
|
134 |
msgstr ""
|
135 |
|
136 |
+
#: classes/amazon-s3-and-cloudfront.php:2825
|
137 |
msgctxt "Show the support tab"
|
138 |
msgid "Support"
|
139 |
msgstr ""
|
140 |
|
141 |
+
#: classes/amazon-s3-and-cloudfront.php:3041
|
142 |
#, php-format
|
143 |
msgid ""
|
144 |
"<strong>WP Offload S3</strong> — The file %s has been given %s "
|
145 |
"permissions on Amazon S3."
|
146 |
msgstr ""
|
147 |
|
148 |
+
#: classes/amazon-s3-and-cloudfront.php:3060
|
149 |
msgid ""
|
150 |
"<strong>WP Offload S3 Requirement Missing</strong> — Looks like you "
|
151 |
"don't have an image manipulation library installed on this server and "
|
153 |
"Please setup GD or ImageMagick."
|
154 |
msgstr ""
|
155 |
|
156 |
+
#: classes/amazon-s3-and-cloudfront.php:3723
|
157 |
msgid "Quick Start Guide"
|
158 |
msgstr ""
|
159 |
|
160 |
+
#: classes/amazon-s3-and-cloudfront.php:3725
|
161 |
#, php-format
|
162 |
msgid ""
|
163 |
"Looks like we don't have write access to this bucket. It's likely that the "
|
166 |
"correctly."
|
167 |
msgstr ""
|
168 |
|
169 |
+
#: classes/amazon-s3-and-cloudfront.php:3727
|
170 |
#, php-format
|
171 |
msgid ""
|
172 |
"Looks like we don't have access to the buckets. It's likely that the user "
|
174 |
"Please see our %s for instructions on setting up permissions correctly."
|
175 |
msgstr ""
|
176 |
|
177 |
+
#: classes/amazon-s3-and-cloudfront.php:3878
|
178 |
msgid "WP Offload S3 Activation"
|
179 |
msgstr ""
|
180 |
|
181 |
+
#: classes/amazon-s3-and-cloudfront.php:3879
|
182 |
msgid ""
|
183 |
"WP Offload S3 Lite and WP Offload S3 cannot both be active. We've "
|
184 |
"automatically deactivated WP Offload S3 Lite."
|
185 |
msgstr ""
|
186 |
|
187 |
+
#: classes/amazon-s3-and-cloudfront.php:3881
|
188 |
msgid "WP Offload S3 Lite Activation"
|
189 |
msgstr ""
|
190 |
|
191 |
+
#: classes/amazon-s3-and-cloudfront.php:3882
|
192 |
msgid ""
|
193 |
"WP Offload S3 Lite and WP Offload S3 cannot both be active. We've "
|
194 |
"automatically deactivated WP Offload S3."
|
195 |
msgstr ""
|
196 |
|
197 |
+
#: classes/amazon-s3-and-cloudfront.php:3956
|
198 |
msgid "More info"
|
199 |
msgstr ""
|
200 |
|
201 |
+
#: classes/amazon-s3-and-cloudfront.php:4047
|
|
|
202 |
msgid "this doc"
|
203 |
msgstr ""
|
204 |
|
205 |
+
#: classes/amazon-s3-and-cloudfront.php:4049
|
|
|
206 |
msgid "WP Offload S3 Feature Removed"
|
207 |
msgstr ""
|
208 |
|
209 |
+
#: classes/amazon-s3-and-cloudfront.php:4050
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
210 |
#, php-format
|
211 |
msgid ""
|
212 |
"You had the \"Always non-SSL\" option selected in your settings, but we've "
|
217 |
"to the old behavior."
|
218 |
msgstr ""
|
219 |
|
220 |
+
#: classes/amazon-s3-and-cloudfront.php:4078
|
221 |
+
#: classes/amazon-s3-and-cloudfront.php:4171
|
222 |
+
msgid "Amazon S3"
|
223 |
+
msgstr ""
|
224 |
+
|
225 |
+
#: classes/amazon-s3-and-cloudfront.php:4172
|
226 |
+
msgctxt "Amazon S3 bucket"
|
227 |
+
msgid "Bucket"
|
228 |
+
msgstr ""
|
229 |
+
|
230 |
+
#: classes/amazon-s3-and-cloudfront.php:4173
|
231 |
+
msgctxt "Path to file on Amazon S3"
|
232 |
+
msgid "Path"
|
233 |
+
msgstr ""
|
234 |
+
|
235 |
+
#: classes/amazon-s3-and-cloudfront.php:4174
|
236 |
+
msgctxt "Location of Amazon S3 bucket"
|
237 |
+
msgid "Region"
|
238 |
+
msgstr ""
|
239 |
+
|
240 |
+
#: classes/amazon-s3-and-cloudfront.php:4175
|
241 |
+
msgctxt "Access control list of the file on Amazon S3"
|
242 |
+
msgid "Access"
|
243 |
+
msgstr ""
|
244 |
+
|
245 |
+
#: classes/amazon-s3-and-cloudfront.php:4176
|
246 |
+
msgid "URL"
|
247 |
+
msgstr ""
|
248 |
+
|
249 |
+
#: classes/as3cf-notices.php:438
|
250 |
msgid "Error dismissing notice."
|
251 |
msgstr ""
|
252 |
|
253 |
+
#: classes/as3cf-notices.php:453
|
254 |
msgid "Invalid notice ID."
|
255 |
msgstr ""
|
256 |
|
257 |
+
#: classes/as3cf-plugin-compatibility.php:192
|
258 |
msgid "WP Offload S3 Compatibility Addons"
|
259 |
msgstr ""
|
260 |
|
261 |
+
#: classes/as3cf-plugin-compatibility.php:194
|
262 |
msgid "compatibility addons"
|
263 |
msgstr ""
|
264 |
|
265 |
+
#: classes/as3cf-plugin-compatibility.php:195
|
266 |
#, php-format
|
267 |
msgid ""
|
268 |
"To get WP Offload S3 to work with certain 3rd party plugins, you might need "
|
271 |
"about each addon to determine if you need it or not."
|
272 |
msgstr ""
|
273 |
|
274 |
+
#: classes/as3cf-plugin-compatibility.php:201
|
275 |
#, php-format
|
276 |
msgid ""
|
277 |
"You will need to purchase a license to get access to these addons. If you're "
|
279 |
"to %s."
|
280 |
msgstr ""
|
281 |
|
282 |
+
#: classes/as3cf-plugin-compatibility.php:202
|
283 |
msgid "View Licenses"
|
284 |
msgstr ""
|
285 |
|
286 |
+
#: classes/as3cf-plugin-compatibility.php:664
|
287 |
#, php-format
|
288 |
msgid "The local directory %s does not exist and could not be created."
|
289 |
msgstr ""
|
290 |
|
291 |
+
#: classes/as3cf-plugin-compatibility.php:665
|
292 |
+
#: classes/as3cf-plugin-compatibility.php:677
|
293 |
#: classes/upgrades/as3cf-meta-wp-error.php:72
|
294 |
#, php-format
|
295 |
msgid "There was an error attempting to download the file %s from S3: %s"
|
296 |
msgstr ""
|
297 |
|
298 |
+
#: classes/as3cf-upgrade.php:298
|
299 |
+
msgid "Pause Update"
|
300 |
+
msgstr ""
|
301 |
+
|
302 |
+
#: classes/as3cf-upgrade.php:306
|
303 |
+
msgid "Restart Update"
|
304 |
+
msgstr ""
|
305 |
+
|
306 |
+
#: classes/as3cf-upgrade.php:310
|
307 |
+
msgid "Try Run It Again"
|
308 |
+
msgstr ""
|
309 |
+
|
310 |
+
#: classes/as3cf-upgrade.php:333
|
311 |
#, php-format
|
312 |
msgid ""
|
313 |
+
"<strong>Running %1$s Update%2$s</strong> — We’re going through "
|
314 |
+
"all the Media Library items uploaded to S3 %3$s This will be done quietly in "
|
315 |
+
"the background, processing a small batch of Media Library items every %4$d "
|
316 |
"minutes. There should be no noticeable impact on your server’s "
|
317 |
"performance."
|
318 |
msgstr ""
|
319 |
|
320 |
+
#: classes/as3cf-upgrade.php:347
|
321 |
+
#, php-format
|
322 |
+
msgid ""
|
323 |
+
"<strong>%1$s Update Paused%2$s</strong> — Updating Media Library %3$s "
|
324 |
+
"has been paused."
|
325 |
msgstr ""
|
326 |
|
327 |
+
#: classes/as3cf-upgrade.php:360
|
328 |
#, php-format
|
329 |
msgid ""
|
330 |
+
"<strong>Error Updating %1$s</strong> — We ran into some errors "
|
331 |
+
"attempting to update the %2$s for all your Media Library items that have "
|
332 |
+
"been uploaded to S3. Please check your error log for details. (#%3$d)"
|
333 |
msgstr ""
|
334 |
|
335 |
+
#: classes/as3cf-upgrade.php:384
|
336 |
+
#, php-format
|
337 |
+
msgid " (%s%% Complete)"
|
338 |
msgstr ""
|
339 |
|
340 |
+
#: classes/as3cf-upgrade.php:495
|
341 |
+
#, php-format
|
342 |
+
msgid "Every %d Minutes"
|
343 |
+
msgstr ""
|
344 |
+
|
345 |
+
#: classes/upgrades/as3cf-content-replace-urls.php:43
|
346 |
+
msgid "and ensuring that only the local URL exists in post content."
|
347 |
+
msgstr ""
|
348 |
+
|
349 |
+
#: classes/upgrades/as3cf-content-replace-urls.php:566
|
350 |
#, php-format
|
351 |
msgid ""
|
352 |
+
"<strong>Running 1.2 Upgrade%1$s</strong><br>A find & replace is running "
|
353 |
+
"in the background to update URLs in your content. %2$s"
|
|
|
354 |
msgstr ""
|
355 |
|
356 |
+
#: classes/upgrades/as3cf-content-replace-urls.php:575
|
357 |
+
#, php-format
|
358 |
+
msgid ""
|
359 |
+
"<strong>Paused 1.2 Upgrade</strong><br>The find & replace to update URLs "
|
360 |
+
"in your content has been paused. %s"
|
361 |
+
msgstr ""
|
362 |
+
|
363 |
+
#: classes/upgrades/as3cf-content-replace-urls.php:584
|
364 |
+
msgid "See our documentation"
|
365 |
msgstr ""
|
366 |
|
367 |
+
#: classes/upgrades/as3cf-content-replace-urls.php:587
|
368 |
#, php-format
|
369 |
+
msgid ""
|
370 |
+
"%s for details on why we’re doing this, why it runs slowly, and how to "
|
371 |
+
"make it run faster."
|
372 |
+
msgstr ""
|
373 |
+
|
374 |
+
#: classes/upgrades/as3cf-edd-replace-urls.php:28
|
375 |
+
msgid "and ensuring that only the local URL exists in EDD post meta."
|
376 |
msgstr ""
|
377 |
|
378 |
#: classes/upgrades/as3cf-file-sizes.php:37
|
471 |
msgid "The %s plugin has been deactivated."
|
472 |
msgstr ""
|
473 |
|
474 |
+
#: view/attachment-metabox.php:4
|
475 |
+
msgid "This item has not been copied to S3 yet."
|
476 |
+
msgstr ""
|
477 |
+
|
478 |
+
#: view/attachment-metabox.php:29
|
479 |
+
msgid "File does not exist on server"
|
480 |
+
msgstr ""
|
481 |
+
|
482 |
#: view/bucket-select.php:3
|
483 |
msgid "Change bucket"
|
484 |
msgstr ""
|
667 |
msgid "By default the path is the same as your local WordPress files."
|
668 |
msgstr ""
|
669 |
|
670 |
+
#: view/settings.php:120
|
671 |
msgid "Year/Month"
|
672 |
msgstr ""
|
673 |
|
674 |
+
#: view/settings.php:122
|
675 |
msgid "Add the Year/Month in the URL."
|
676 |
msgstr ""
|
677 |
|
678 |
+
#: view/settings.php:135
|
679 |
msgid "Force HTTPS"
|
680 |
msgstr ""
|
681 |
|
682 |
+
#: view/settings.php:137
|
683 |
msgid ""
|
684 |
"By default we use HTTPS when the request is HTTPS and regular HTTP when the "
|
685 |
"request is HTTP, but you may want to force the use of HTTPS always, "
|
686 |
"regardless of the request."
|
687 |
msgstr ""
|
688 |
|
689 |
+
#: view/settings.php:144
|
690 |
msgid "Advanced Options"
|
691 |
msgstr ""
|
692 |
|
693 |
+
#: view/settings.php:153
|
694 |
msgid "Remove Files From Server"
|
695 |
msgstr ""
|
696 |
|
697 |
+
#: view/settings.php:154
|
698 |
msgid "Once a file has been copied to S3, remove it from the local server."
|
699 |
msgstr ""
|
700 |
|
701 |
+
#: view/settings.php:158
|
702 |
msgid ""
|
703 |
"<strong>Broken URLs</strong> — There will be broken URLs for files "
|
704 |
"that don't exist locally. You can fix this by enabling <strong>Rewrite File "
|
705 |
"URLs</strong> to use the S3 URLs."
|
706 |
msgstr ""
|
707 |
|
708 |
+
#: view/settings.php:169
|
709 |
#, php-format
|
710 |
msgid ""
|
711 |
"<strong>Warning</strong> — Some plugins depend on the file being "
|
712 |
"present on the local server and may not work when the file is removed. %s"
|
713 |
msgstr ""
|
714 |
|
715 |
+
#: view/settings.php:187
|
716 |
msgid "Object Versioning"
|
717 |
msgstr ""
|
718 |
|
719 |
+
#: view/settings.php:189
|
720 |
msgid ""
|
721 |
"Append a timestamp to the S3 file path. Recommended when using CloudFront so "
|
722 |
"you don't have to worry about cache invalidation."
|
723 |
msgstr ""
|
724 |
|
725 |
+
#: view/settings.php:196
|
726 |
msgid "Save Changes"
|
727 |
msgstr ""
|
728 |
|
731 |
msgstr ""
|
732 |
|
733 |
#: view/sidebar.php:11
|
|
|
|
|
|
|
|
|
734 |
msgid "Manage S3 files in WordPress"
|
735 |
msgstr ""
|
736 |
|
737 |
+
#: view/sidebar.php:12
|
738 |
msgid "Assets addon - Serve your CSS & JS from S3/CloudFront"
|
739 |
msgstr ""
|
740 |
|
741 |
+
#: view/sidebar.php:13
|
742 |
msgid "WooCommerce addon"
|
743 |
msgstr ""
|
744 |
|
745 |
+
#: view/sidebar.php:14
|
746 |
msgid "Easy Digital Downloads addon"
|
747 |
msgstr ""
|
748 |
|
749 |
+
#: view/sidebar.php:15
|
750 |
msgid "PriorityExpert™ email support"
|
751 |
msgstr ""
|
752 |
|
753 |
+
#: view/sidebar.php:18
|
754 |
msgid "Visit deliciousbrains.com →"
|
755 |
msgstr ""
|
756 |
|
757 |
+
#: view/sidebar.php:25
|
758 |
msgid "Get 20% Off!"
|
759 |
msgstr ""
|
760 |
|
761 |
+
#: view/sidebar.php:28
|
762 |
#, php-format
|
763 |
msgid ""
|
764 |
"Submit your name and email and we’ll send you a coupon for 20% off your "
|
765 |
"upgrade."
|
766 |
msgstr ""
|
767 |
|
768 |
+
#: view/sidebar.php:32
|
769 |
msgid "Your Email"
|
770 |
msgstr ""
|
771 |
|
772 |
+
#: view/sidebar.php:36
|
773 |
msgid "First Name"
|
774 |
msgstr ""
|
775 |
|
776 |
+
#: view/sidebar.php:40
|
777 |
msgid "Last Name"
|
778 |
msgstr ""
|
779 |
|
780 |
+
#: view/sidebar.php:47
|
781 |
msgid "Send me the coupon"
|
782 |
msgstr ""
|
783 |
|
784 |
+
#: view/sidebar.php:51
|
785 |
msgid ""
|
786 |
"We promise we will not use your email for anything else and you can "
|
787 |
"unsubscribe with 1-click anytime."
|
readme.txt
CHANGED
@@ -2,8 +2,8 @@
|
|
2 |
Contributors: bradt, deliciousbrains
|
3 |
Tags: uploads, amazon, s3, amazon s3, mirror, admin, media, cdn, cloudfront
|
4 |
Requires at least: 4.4
|
5 |
-
Tested up to: 4.6
|
6 |
-
Stable tag: 1.
|
7 |
License: GPLv3
|
8 |
|
9 |
Copies files to Amazon S3 as they are uploaded to the Media Library. Optionally configure Amazon CloudFront for faster delivery.
|
@@ -21,7 +21,6 @@ If you're adding this plugin to a site that's been around for a while, your exis
|
|
21 |
**PRO Upgrade with Email Support and More Features**
|
22 |
|
23 |
* Upload existing Media Library to Amazon S3
|
24 |
-
* Find & replace file URLs in content
|
25 |
* Control Amazon S3 files from the Media Library
|
26 |
* [Assets addon](https://deliciousbrains.com/wp-offload-s3/?utm_source=wordpress.org&utm_medium=web&utm_content=desc&utm_campaign=os3-free-plugin#assets-addon) - Serve your CSS & JS from Amazon S3/CloudFront
|
27 |
* [WooCommerce addon](https://deliciousbrains.com/wp-offload-s3/?utm_source=wordpress.org&utm_medium=web&utm_content=desc&utm_campaign=os3-free-plugin#woocommerce-addon)
|
@@ -58,25 +57,45 @@ You can see the minimum requirements [here](https://deliciousbrains.com/wp-offlo
|
|
58 |
|
59 |
== Upgrade Notice ==
|
60 |
|
|
|
|
|
|
|
61 |
= 0.6 =
|
62 |
This version requires PHP 5.3.3+ and the Amazon Web Services plugin
|
63 |
|
64 |
== Changelog ==
|
65 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
66 |
= WP Offload S3 Lite 1.0.5 - 2016-09-01 =
|
67 |
* New: Compatibility with WordPress 4.6
|
68 |
* Improvement: No longer delete plugin data on uninstall. Manual removal possible, as per this [doc](https://deliciousbrains.com/wp-offload-s3/doc/uninstall/)
|
69 |
|
70 |
= WP Offload S3 Lite 1.0.4 - 2016-05-30 =
|
71 |
-
* New: Now using simpler Force HTTPS setting, removed redundant Always Use HTTP setting
|
72 |
-
* New: `as3cf_cloudfront_path_parts` filter allows changing served CloudFront path (useful when distribution pulls subdirectory)
|
73 |
-
* Improvement: Better compatibility with non-standard notices from other plugins and themes
|
74 |
-
* Improvement: Added basic auth and proxy info to diagnostic info
|
75 |
-
* Improvement: Added `allow_url_fopen` status to diagnostic info
|
76 |
-
* Improvement: Added memory usage to diagnostic info
|
77 |
-
* Improvement: Ensure notice text is 800px or less in width
|
78 |
-
* Improvement: Reduced database queries on settings screen
|
79 |
-
* Bug fix: Properly handle _wp_attachment_data metadata when it is a serialized WP_Error
|
80 |
|
81 |
= WP Offload S3 Lite 1.0.3 - 2016-03-23 =
|
82 |
* Bug fix: Don't replace srcset URLs when Rewrite File URLs option disabled
|
@@ -97,7 +116,7 @@ This version requires PHP 5.3.3+ and the Amazon Web Services plugin
|
|
97 |
* Improvement: Far future expiration header set by default
|
98 |
* Improvement: Newly created bucket now immediately appears in the bucket list
|
99 |
* Improvement: Cleanup user meta on uninstall
|
100 |
-
* Improvement: WP Retina 2x integration
|
101 |
* Bug fix: Year/Month folder structure on S3 not created if the 'Organise my uploads into month and year-based folders' WordPress setting is disabled
|
102 |
* Bug fix: Responsive srcset PHP notices
|
103 |
* Bug fix: Compatibility addon notices displayed to non-admin users
|
2 |
Contributors: bradt, deliciousbrains
|
3 |
Tags: uploads, amazon, s3, amazon s3, mirror, admin, media, cdn, cloudfront
|
4 |
Requires at least: 4.4
|
5 |
+
Tested up to: 4.6.1
|
6 |
+
Stable tag: 1.1.1
|
7 |
License: GPLv3
|
8 |
|
9 |
Copies files to Amazon S3 as they are uploaded to the Media Library. Optionally configure Amazon CloudFront for faster delivery.
|
21 |
**PRO Upgrade with Email Support and More Features**
|
22 |
|
23 |
* Upload existing Media Library to Amazon S3
|
|
|
24 |
* Control Amazon S3 files from the Media Library
|
25 |
* [Assets addon](https://deliciousbrains.com/wp-offload-s3/?utm_source=wordpress.org&utm_medium=web&utm_content=desc&utm_campaign=os3-free-plugin#assets-addon) - Serve your CSS & JS from Amazon S3/CloudFront
|
26 |
* [WooCommerce addon](https://deliciousbrains.com/wp-offload-s3/?utm_source=wordpress.org&utm_medium=web&utm_content=desc&utm_campaign=os3-free-plugin#woocommerce-addon)
|
57 |
|
58 |
== Upgrade Notice ==
|
59 |
|
60 |
+
= 1.1 =
|
61 |
+
This is a major change, which ensures S3 URLs are no longer saved in post content. Instead, local URLs are filtered on page generation and replaced with the S3 version. If you depend on the S3 URLs being stored in post content you will need to make modifications to support this version.
|
62 |
+
|
63 |
= 0.6 =
|
64 |
This version requires PHP 5.3.3+ and the Amazon Web Services plugin
|
65 |
|
66 |
== Changelog ==
|
67 |
|
68 |
+
= WP Offload S3 Lite 1.1.1 - 2016-10-17 =
|
69 |
+
* New: Filter post excerpts - S3 URLs will no longer be saved to the database
|
70 |
+
* Bug fix: PHP 5.3 Fatal error: Using $this when not in object context
|
71 |
+
* Bug fix: Query string parameters incorrectly encoded for Media Library items
|
72 |
+
|
73 |
+
= WP Offload S3 Lite 1.1 - 2016-09-29 =
|
74 |
+
* New: Filter post content. S3 URLs will no longer be saved to the database
|
75 |
+
* New: Upgrade routine to replace all S3 URLs in content with local URLs
|
76 |
+
* New: Support for theme custom logos
|
77 |
+
* New: Control the ACL for intermediate image sizes using the `as3cf_upload_acl_sizes` filter
|
78 |
+
* Bug fix: File names containing special characters double encoded
|
79 |
+
* Bug fix: `srcset` not working for file names containing special characters
|
80 |
+
* Bug fix: Incorrect placeholder text for 'Path' option
|
81 |
+
* Bug fix: Objects in root of bucket not deleted when removed from the Media Library
|
82 |
+
* Bug fix: No longer use deprecated functions in WordPress 4.6
|
83 |
+
* Bug fix: Don't delete local file when 'Remove Files From Server' enabled and upload to S3 fails
|
84 |
+
|
85 |
= WP Offload S3 Lite 1.0.5 - 2016-09-01 =
|
86 |
* New: Compatibility with WordPress 4.6
|
87 |
* Improvement: No longer delete plugin data on uninstall. Manual removal possible, as per this [doc](https://deliciousbrains.com/wp-offload-s3/doc/uninstall/)
|
88 |
|
89 |
= WP Offload S3 Lite 1.0.4 - 2016-05-30 =
|
90 |
+
* New: Now using simpler Force HTTPS setting, removed redundant Always Use HTTP setting
|
91 |
+
* New: `as3cf_cloudfront_path_parts` filter allows changing served CloudFront path (useful when distribution pulls subdirectory)
|
92 |
+
* Improvement: Better compatibility with non-standard notices from other plugins and themes
|
93 |
+
* Improvement: Added basic auth and proxy info to diagnostic info
|
94 |
+
* Improvement: Added `allow_url_fopen` status to diagnostic info
|
95 |
+
* Improvement: Added memory usage to diagnostic info
|
96 |
+
* Improvement: Ensure notice text is 800px or less in width
|
97 |
+
* Improvement: Reduced database queries on settings screen
|
98 |
+
* Bug fix: Properly handle _wp_attachment_data metadata when it is a serialized WP_Error
|
99 |
|
100 |
= WP Offload S3 Lite 1.0.3 - 2016-03-23 =
|
101 |
* Bug fix: Don't replace srcset URLs when Rewrite File URLs option disabled
|
116 |
* Improvement: Far future expiration header set by default
|
117 |
* Improvement: Newly created bucket now immediately appears in the bucket list
|
118 |
* Improvement: Cleanup user meta on uninstall
|
119 |
+
* Improvement: WP Retina 2x integration removed
|
120 |
* Bug fix: Year/Month folder structure on S3 not created if the 'Organise my uploads into month and year-based folders' WordPress setting is disabled
|
121 |
* Bug fix: Responsive srcset PHP notices
|
122 |
* Bug fix: Compatibility addon notices displayed to non-admin users
|
view/attachment-metabox.php
ADDED
@@ -0,0 +1,56 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<div class="s3-details">
|
2 |
+
<?php if ( ! $s3object ) : ?>
|
3 |
+
<div class="misc-pub-section">
|
4 |
+
<em class="not-copied"><?php _e( 'This item has not been copied to S3 yet.', 'amazon-s3-and-cloudfront' ); ?></em>
|
5 |
+
</div>
|
6 |
+
<?php else : ?>
|
7 |
+
<div class="misc-pub-section">
|
8 |
+
<div class="s3-key"><?php echo $this->get_media_action_strings( 'bucket' ); ?>:</div>
|
9 |
+
<input type="text" class="widefat" readonly="readonly" value="<?php echo $s3object['bucket']; ?>">
|
10 |
+
</div>
|
11 |
+
<div class="misc-pub-section">
|
12 |
+
<div class="s3-key"><?php echo $this->get_media_action_strings( 'key' ); ?>:</div>
|
13 |
+
<input type="text" class="widefat" readonly="readonly" value="<?php echo $s3object['key']; ?>">
|
14 |
+
</div>
|
15 |
+
<?php if ( isset( $s3object['region'] ) && $s3object['region'] ) : ?>
|
16 |
+
<div class="misc-pub-section">
|
17 |
+
<div class="s3-key"><?php echo $this->get_media_action_strings( 'region' ); ?>:</div>
|
18 |
+
<div class="s3-value"><?php echo $s3object['region']; ?></div>
|
19 |
+
</div>
|
20 |
+
<?php endif; ?>
|
21 |
+
<div class="misc-pub-section">
|
22 |
+
<div class="s3-key"><?php echo $this->get_media_action_strings( 'acl' ); ?>:</div>
|
23 |
+
<div class="s3-value">
|
24 |
+
<?php echo $this->get_acl_value_string( $s3object['acl'] ); ?>
|
25 |
+
</div>
|
26 |
+
</div>
|
27 |
+
<?php if ( $user_can_perform_actions && ! $local_file_exists ) : ?>
|
28 |
+
<div class="misc-pub-section">
|
29 |
+
<div class="not-copied"><?php _e( 'File does not exist on server', 'amazon-s3-and-cloudfront' ); ?></div>
|
30 |
+
<a href="<?php echo $this->get_media_action_url( 'download', $post->ID, $sendback ); ?>">
|
31 |
+
<?php echo $this->get_media_action_strings( 'download' ); ?>
|
32 |
+
</a>
|
33 |
+
</div>
|
34 |
+
<?php endif; ?>
|
35 |
+
<?php endif; ?>
|
36 |
+
<div class="clear"></div>
|
37 |
+
</div>
|
38 |
+
<?php if ( $user_can_perform_actions && ( $s3object || $local_file_exists ) ) : ?>
|
39 |
+
<div class="s3-actions">
|
40 |
+
<?php if ( $s3object ) : ?>
|
41 |
+
<div class="remove-action">
|
42 |
+
<a href="<?php echo $this->get_media_action_url( 'remove', $post->ID, $sendback ); ?>" class="<?php echo ( ! $local_file_exists ) ? 'local-warning' : ''; ?>">
|
43 |
+
<?php echo $this->get_media_action_strings( 'remove' ); ?>
|
44 |
+
</a>
|
45 |
+
</div>
|
46 |
+
<?php endif; ?>
|
47 |
+
<?php if ( $local_file_exists ) : ?>
|
48 |
+
<div class="copy-action">
|
49 |
+
<a href="<?php echo $this->get_media_action_url( 'copy', $post->ID, $sendback ); ?>" class="button button-secondary">
|
50 |
+
<?php echo $this->get_media_action_strings( 'copy' ); ?>
|
51 |
+
</a>
|
52 |
+
</div>
|
53 |
+
<?php endif; ?>
|
54 |
+
<div class="clear"></div>
|
55 |
+
</div>
|
56 |
+
<?php endif; ?>
|
view/settings.php
CHANGED
@@ -104,15 +104,8 @@ $selected_bucket_prefix = $this->get_object_prefix(); ?>
|
|
104 |
<?php echo $this->settings_more_info_link( 'object-prefix' ); ?>
|
105 |
</p>
|
106 |
<p class="as3cf-setting enable-object-prefix <?php echo ( $this->get_setting( 'enable-object-prefix' ) ) ? '' : 'hide'; // xss ok ?>">
|
107 |
-
<?php
|
108 |
-
|
109 |
-
if ( false === $this->get_defined_setting( 'object-prefix', false ) ) {
|
110 |
-
$placeholder = 'placeholder="placeholder"';
|
111 |
-
} else {
|
112 |
-
$placeholder = '';
|
113 |
-
}
|
114 |
-
?>
|
115 |
-
<input type="text" name="object-prefix" value="<?php echo esc_attr( $this->get_setting( 'object-prefix' ) ); ?>" size="30" placeholder="<?php echo $placeholder; ?>" <?php echo $args['disabled_attr']; ?> />
|
116 |
</p>
|
117 |
</td>
|
118 |
</tr>
|
104 |
<?php echo $this->settings_more_info_link( 'object-prefix' ); ?>
|
105 |
</p>
|
106 |
<p class="as3cf-setting enable-object-prefix <?php echo ( $this->get_setting( 'enable-object-prefix' ) ) ? '' : 'hide'; // xss ok ?>">
|
107 |
+
<?php $args = $this->get_setting_args( 'object-prefix' ); ?>
|
108 |
+
<input type="text" name="object-prefix" value="<?php echo esc_attr( $this->get_setting( 'object-prefix' ) ); ?>" size="30" placeholder="<?php echo $this->get_default_object_prefix(); ?>" <?php echo $args['disabled_attr']; ?> />
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
109 |
</p>
|
110 |
</td>
|
111 |
</tr>
|
view/sidebar.php
CHANGED
@@ -8,7 +8,6 @@
|
|
8 |
|
9 |
<ul>
|
10 |
<li><?php echo wptexturize( __( 'Upload existing Media Library to S3', 'amazon-s3-and-cloudfront' ) ); // xss ok ?></li>
|
11 |
-
<li><?php echo wptexturize( __( 'Find & replace file URLs in content', 'amazon-s3-and-cloudfront' ) ); // xss ok ?></li>
|
12 |
<li><?php echo wptexturize( __( 'Manage S3 files in WordPress', 'amazon-s3-and-cloudfront' ) ); // xss ok ?></li>
|
13 |
<li><?php echo wptexturize( __( 'Assets addon - Serve your CSS & JS from S3/CloudFront', 'amazon-s3-and-cloudfront' ) ); // xss ok ?></li>
|
14 |
<li><?php echo wptexturize( __( 'WooCommerce addon', 'amazon-s3-and-cloudfront' ) ); // xss ok ?></li>
|
8 |
|
9 |
<ul>
|
10 |
<li><?php echo wptexturize( __( 'Upload existing Media Library to S3', 'amazon-s3-and-cloudfront' ) ); // xss ok ?></li>
|
|
|
11 |
<li><?php echo wptexturize( __( 'Manage S3 files in WordPress', 'amazon-s3-and-cloudfront' ) ); // xss ok ?></li>
|
12 |
<li><?php echo wptexturize( __( 'Assets addon - Serve your CSS & JS from S3/CloudFront', 'amazon-s3-and-cloudfront' ) ); // xss ok ?></li>
|
13 |
<li><?php echo wptexturize( __( 'WooCommerce addon', 'amazon-s3-and-cloudfront' ) ); // xss ok ?></li>
|
wordpress-s3.php
CHANGED
@@ -4,7 +4,7 @@ Plugin Name: WP Offload S3 Lite
|
|
4 |
Plugin URI: http://wordpress.org/extend/plugins/amazon-s3-and-cloudfront/
|
5 |
Description: Automatically copies media uploads to Amazon S3 for storage and delivery. Optionally configure Amazon CloudFront for even faster delivery.
|
6 |
Author: Delicious Brains
|
7 |
-
Version: 1.
|
8 |
Author URI: http://deliciousbrains.com/
|
9 |
Network: True
|
10 |
Text Domain: amazon-s3-and-cloudfront
|
@@ -26,9 +26,9 @@ Domain Path: /languages/
|
|
26 |
// Then completely rewritten.
|
27 |
*/
|
28 |
|
29 |
-
$GLOBALS['aws_meta']['amazon-s3-and-cloudfront']['version'] = '1.
|
30 |
|
31 |
-
$aws_plugin_version_required = '0
|
32 |
|
33 |
require_once dirname( __FILE__ ) . '/classes/wp-aws-compatibility-check.php';
|
34 |
require_once dirname( __FILE__ ) . '/classes/as3cf-utils.php';
|
@@ -65,6 +65,11 @@ function as3cf_init( $aws ) {
|
|
65 |
require_once $abspath . '/classes/upgrades/as3cf-region-meta.php';
|
66 |
require_once $abspath . '/classes/upgrades/as3cf-file-sizes.php';
|
67 |
require_once $abspath . '/classes/upgrades/as3cf-meta-wp-error.php';
|
|
|
|
|
|
|
|
|
|
|
68 |
require_once $abspath . '/classes/as3cf-notices.php';
|
69 |
require_once $abspath . '/classes/as3cf-stream-wrapper.php';
|
70 |
require_once $abspath . '/classes/as3cf-plugin-compatibility.php';
|
4 |
Plugin URI: http://wordpress.org/extend/plugins/amazon-s3-and-cloudfront/
|
5 |
Description: Automatically copies media uploads to Amazon S3 for storage and delivery. Optionally configure Amazon CloudFront for even faster delivery.
|
6 |
Author: Delicious Brains
|
7 |
+
Version: 1.1.1
|
8 |
Author URI: http://deliciousbrains.com/
|
9 |
Network: True
|
10 |
Text Domain: amazon-s3-and-cloudfront
|
26 |
// Then completely rewritten.
|
27 |
*/
|
28 |
|
29 |
+
$GLOBALS['aws_meta']['amazon-s3-and-cloudfront']['version'] = '1.1.1';
|
30 |
|
31 |
+
$aws_plugin_version_required = '1.0';
|
32 |
|
33 |
require_once dirname( __FILE__ ) . '/classes/wp-aws-compatibility-check.php';
|
34 |
require_once dirname( __FILE__ ) . '/classes/as3cf-utils.php';
|
65 |
require_once $abspath . '/classes/upgrades/as3cf-region-meta.php';
|
66 |
require_once $abspath . '/classes/upgrades/as3cf-file-sizes.php';
|
67 |
require_once $abspath . '/classes/upgrades/as3cf-meta-wp-error.php';
|
68 |
+
require_once $abspath . '/classes/upgrades/as3cf-content-replace-urls.php';
|
69 |
+
require_once $abspath . '/classes/upgrades/as3cf-edd-replace-urls.php';
|
70 |
+
require_once $abspath . '/classes/as3cf-filter.php';
|
71 |
+
require_once $abspath . '/classes/filters/as3cf-local-to-s3.php';
|
72 |
+
require_once $abspath . '/classes/filters/as3cf-s3-to-local.php';
|
73 |
require_once $abspath . '/classes/as3cf-notices.php';
|
74 |
require_once $abspath . '/classes/as3cf-stream-wrapper.php';
|
75 |
require_once $abspath . '/classes/as3cf-plugin-compatibility.php';
|