diff --git a/README.md b/README.md index 4ea4735c5..4ffdf2eb8 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,6 @@ Stay tuned for updates, tips and tutorials: [Blog](http://cloudinary.com/blog), ## License ####################################################################### -Released under the MIT license. +Released under the GPL license. diff --git a/assets/banner-772x250.jpg b/assets/banner-772x250.jpg deleted file mode 100644 index d997bf257..000000000 Binary files a/assets/banner-772x250.jpg and /dev/null differ diff --git a/assets/banner-772x250.png b/assets/banner-772x250.png new file mode 100644 index 000000000..7f937958f Binary files /dev/null and b/assets/banner-772x250.png differ diff --git a/assets/icon-128x128.png b/assets/icon-128x128.png index 789340aac..b077639f9 100644 Binary files a/assets/icon-128x128.png and b/assets/icon-128x128.png differ diff --git a/assets/icon-256x256.png b/assets/icon-256x256.png index 913a7106a..e92c918e5 100644 Binary files a/assets/icon-256x256.png and b/assets/icon-256x256.png differ diff --git a/assets/screenshot-1.jpg b/assets/screenshot-1.jpg deleted file mode 100644 index d41a275d1..000000000 Binary files a/assets/screenshot-1.jpg and /dev/null differ diff --git a/assets/screenshot-1.png b/assets/screenshot-1.png new file mode 100644 index 000000000..f0626f437 Binary files /dev/null and b/assets/screenshot-1.png differ diff --git a/assets/screenshot-2.jpg b/assets/screenshot-2.jpg deleted file mode 100644 index d5da1dc1b..000000000 Binary files a/assets/screenshot-2.jpg and /dev/null differ diff --git a/assets/screenshot-2.png b/assets/screenshot-2.png new file mode 100644 index 000000000..5ae2bba59 Binary files /dev/null and b/assets/screenshot-2.png differ diff --git a/assets/screenshot-3.jpg b/assets/screenshot-3.jpg deleted file mode 100644 index b90f45398..000000000 Binary files a/assets/screenshot-3.jpg and /dev/null differ diff --git a/assets/screenshot-3.png b/assets/screenshot-3.png new file mode 100644 index 000000000..ad3190050 Binary files /dev/null and b/assets/screenshot-3.png differ diff --git a/assets/screenshot-4.jpg b/assets/screenshot-4.jpg deleted file mode 100644 index 877f41cc0..000000000 Binary files a/assets/screenshot-4.jpg and /dev/null differ diff --git a/assets/screenshot-4.png b/assets/screenshot-4.png new file mode 100644 index 000000000..4d66c57a0 Binary files /dev/null and b/assets/screenshot-4.png differ diff --git a/assets/screenshot-5.jpg b/assets/screenshot-5.jpg deleted file mode 100644 index cf0998778..000000000 Binary files a/assets/screenshot-5.jpg and /dev/null differ diff --git a/assets/screenshot-5.png b/assets/screenshot-5.png new file mode 100644 index 000000000..6671fe927 Binary files /dev/null and b/assets/screenshot-5.png differ diff --git a/assets/screenshot-6.jpg b/assets/screenshot-6.jpg deleted file mode 100644 index 06c49dd6d..000000000 Binary files a/assets/screenshot-6.jpg and /dev/null differ diff --git a/assets/screenshot-6.png b/assets/screenshot-6.png new file mode 100644 index 000000000..f5c5205d8 Binary files /dev/null and b/assets/screenshot-6.png differ diff --git a/assets/screenshot-7.png b/assets/screenshot-7.png new file mode 100644 index 000000000..31523862c Binary files /dev/null and b/assets/screenshot-7.png differ diff --git a/assets/screenshot-8.png b/assets/screenshot-8.png new file mode 100644 index 000000000..c59713136 Binary files /dev/null and b/assets/screenshot-8.png differ diff --git a/assets/screenshot-9.png b/assets/screenshot-9.png new file mode 100644 index 000000000..f8ac1c137 Binary files /dev/null and b/assets/screenshot-9.png differ diff --git a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/cloudinary.php b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/cloudinary.php index a036384a1..65cb8434a 100644 --- a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/cloudinary.php +++ b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/cloudinary.php @@ -3,7 +3,7 @@ * Plugin Name: Cloudinary * Plugin URI: https://cloudinary.com/documentation/wordpress_integration * Description: With the Cloudinary plugin, you can upload and manage your media assets in the cloud, then deliver them to your users through a fast content delivery network, improving your website’s loading speed and overall user experience. Apply multiple transformations and take advantage of a full digital asset management solution without leaving WordPress. - * Version: 2.0.0 + * Version: 2.0.3 * Author: Cloudinary Ltd., XWP * Author URI: https://cloudinary.com/ * License: GPLv2+ diff --git a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/src/video.scss b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/src/video.scss new file mode 100644 index 000000000..1c2cf9b48 --- /dev/null +++ b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/src/video.scss @@ -0,0 +1,9 @@ +// Frontend video styles. +.cld { + &-video { + &-player { + max-width: 100%; + } + } +} + diff --git a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/video.css b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/video.css new file mode 100644 index 000000000..1a254a1ec --- /dev/null +++ b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/video.css @@ -0,0 +1 @@ +.cld-video-player{max-width:100%} \ No newline at end of file diff --git a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/js/cloudinary.js b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/js/cloudinary.js index e12099400..e2580b210 100644 --- a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/js/cloudinary.js +++ b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/js/cloudinary.js @@ -1 +1 @@ -!function(e){var t={};function i(n){if(t[n])return t[n].exports;var s=t[n]={i:n,l:!1,exports:{}};return e[n].call(s.exports,s,s.exports,i),s.l=!0,s.exports}i.m=e,i.c=t,i.d=function(e,t,n){i.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},i.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},i.t=function(e,t){if(1&t&&(e=i(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(i.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var s in e)i.d(n,s,function(t){return e[t]}.bind(null,s));return n},i.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return i.d(t,"a",t),t},i.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},i.p="",i(i.s=3)}([function(e,t){window,jQuery,jQuery(document).ready((function(e){e(document).on("tabs.init",(function(){var t=e(".settings-tab-trigger"),i=e(".settings-tab-section");e(this).on("click",".settings-tab-trigger",(function(n){var s=e(this),a=e(s.attr("href"));n.preventDefault(),t.removeClass("active"),i.removeClass("active"),s.addClass("active"),a.addClass("active"),e(document).trigger("settings.tabbed",s)})),e(".cld-field").not('[data-condition="false"]').each((function(){const t=e(this),i=t.data("condition");for(let n in i){const s=i[n],a=e("#field-"+n),r=t.closest("tr");a.on("change init",(function(){this.value===s||this.checked?r.show():r.hide()})),a.trigger("init")}})),e("#field-cloudinary_url").on("input change",(function(){let t=e(this),i=t.val();new RegExp(/^(cloudinary:\/\/){1}(\d)*[:]{1}[^:@]*[@]{1}[^@]*$/g).test(i)?(t.addClass("settings-valid-field"),t.removeClass("settings-invalid-field")):(t.removeClass("settings-valid-field"),t.addClass("settings-invalid-field"))})).trigger("change")})),e(".render-trigger[data-event]").each((function(){var t=e(this),i=t.data("event");t.trigger(i,this)}))}))},function(e,t){if(wp.media&&window.CLDN){wp.media.events.on("editor:image-edit",(function(e){e.metadata.cldoverwrite=null,e.image.className.split(" ").indexOf("cld-overwrite")>=0&&(e.metadata.cldoverwrite="true")})),wp.media.events.on("editor:image-update",(function(e){let t=e.image.className.split(" ");e.metadata.cldoverwrite&&-1===t.indexOf("cld-overwrite")?t.push("cld-overwrite"):!e.metadata.cldoverwrite&&t.indexOf("cld-overwrite")>=0&&delete t[t.indexOf("cld-overwrite")],e.image.className=t.join(" ")}));let e=null,t=wp.media.string.props;wp.media.string.props=function(i,n){return i.cldoverwrite&&(i.classes=["cld-overwrite"],e=!0),t(i,n)},wp.media.post=function(t,i){if("send-attachment-to-editor"===t){let t=wp.media.editor.get().state().get("selection").get(i.attachment);t.attributes.transformations&&(i.attachment.transformations=t.attributes.transformations),(i.html.indexOf("cld-overwrite")>-1||!0===e)&&(i.attachment.cldoverwrite=!0,e=null)}return wp.ajax.post(t,i)};wp.media.controller.Library;let i=wp.media.view.MediaFrame.Select,n=wp.media.view.MediaFrame.Post,s=wp.media.view.MediaFrame.ImageDetails,a=wp.media.view.MediaFrame.VideoDetails,r=wp.media.View.extend({tagName:"div",className:"cloudinary-widget",template:wp.template("cloudinary-dam"),active:!1,toolbar:null,frame:null,ready:function(){let e=this.controller,t=this.model.get("selection"),i=this.model.get("library"),n=wp.media.model.Attachment;if(CLDN.mloptions.multiple=e.options.multiple,this.cid!==this.active){if(CLDN.mloptions.inline_container="#cloudinary-dam-"+e.cid,1===t.length){var s=n.get(t.models[0].id);void 0!==s.attributes.public_id&&(CLDN.mloptions.asset={resource_id:s.attributes.public_id})}else CLDN.mloptions.asset=null;window.ml=cloudinary.openMediaLibrary(CLDN.mloptions,{insertHandler:function(s){for(let a=0;a=100&&void 0!==e.started?(this.submitButton.style.display=this.hide,this.stopButton.style.display=this.show):e.pending>0?(this.submitButton.style.display=this.show,this.stopButton.style.display=this.hide):e.processing>0?this.stopButton.style.display=this.show:this.stopButton.style.display=this.hide,e.percent<100?(this.barSyncCount.innerText=e.total,this.progressCount.innerText=e.done,this.progress.style.display=this.show):(this.completed.style.display=this.show,this.progress.style.display=this.hide)},_start:function(e){e.preventDefault(),a.stopButton.style.display=a.show,a.submitButton.style.display=a.hide,a.pushAttachments()},_reset:function(e){a.submitButton.style.display=a.hide,a.getStatus()},_init:function(e){"undefined"!=typeof cloudinaryApi&&((document.attachEvent?"complete"===document.readyState:"loading"!==document.readyState)?e():document.addEventListener("DOMContentLoaded",e))}};var r=a;a._init((function(){a._reset(),a.submitButton.addEventListener("click",a._start),a.stopButton.addEventListener("click",a.stopSync)}));var o=i(1),l=i.n(o);const d={sample:{image:document.getElementById("transformation-sample-image"),video:document.getElementById("transformation-sample-video")},preview:{image:document.getElementById("sample-image"),video:document.getElementById("sample-video")},fields:document.getElementsByClassName("cld-field"),button:{image:document.getElementById("refresh-image-preview"),video:document.getElementById("refresh-video-preview")},spinner:{image:document.getElementById("image-loader"),video:document.getElementById("video-loader")},activeItem:null,elements:{image:[],video:[]},_placeItem:function(e){null!==e&&(e.style.display="block",e.style.visibility="visible",e.style.position="absolute",e.style.top=e.parentElement.clientHeight/2-e.clientHeight/2+"px",e.style.left=e.parentElement.clientWidth/2-e.clientWidth/2+"px")},_setLoading:function(e){this.button[e].style.display="block",this._placeItem(this.button[e]),this.preview[e].style.opacity="0.1"},_build:function(e){this.sample[e].innerHTML="",this.elements[e]=[];for(let t of this.fields){if(e!==t.dataset.context)continue;let i=t.value.trim();if(i.length){if("select-one"===t.type){if("none"===i)continue;i=t.dataset.meta+"_"+i}else{let e=t.dataset.context;i=this._transformations(i,e,!0)}i&&this.elements[e].push(i)}}let t="";this.elements[e].length&&(t="/"+this.elements[e].join(",").replace(/ /g,"%20")),this.sample[e].textContent=t,this.sample[e].parentElement.href="https://res.cloudinary.com/demo/"+this.sample[e].parentElement.innerText.trim().replace("../","").replace(/ /g,"%20")},_clearLoading:function(e){this.spinner[e].style.visibility="hidden",this.activeItem=null,this.preview[e].style.opacity=1},_refresh:function(e,t){e&&e.preventDefault();let i=this,n=CLD_GLOBAL_TRANSFORMATIONS[t].preview_url+i.elements[t].join(",")+CLD_GLOBAL_TRANSFORMATIONS[t].file;if(this.button[t].style.display="none",this._placeItem(this.spinner[t]),"image"===t){let e=new Image;e.onload=function(){i.preview[t].src=this.src,i._clearLoading(t),e.remove()},e.onerror=function(){alert(CLD_GLOBAL_TRANSFORMATIONS[t].error),i._clearLoading(t)},e.src=n}else{let e=i._transformations(i.elements[t].join(","),t);samplePlayer.source({publicId:"dog",transformation:e}),i._clearLoading(t)}},_transformations:function(e,t,i=!1){let n=CLD_GLOBAL_TRANSFORMATIONS[t].valid_types,s=null,a=e.split("/"),r=[];for(let e=0;e{const n=!!i.length&&jQuery('[data-item="'+s+":"+i[0].id+'"]');n.length?n.remove():(jQuery(`.cld-tax-order-list-item:contains(${r})`).remove(),--e.startId),this.processTags(t)})}),jQuery("body").on("change",".selectit input",(function(){const t=jQuery(this),i=t.val(),n=t.is(":checked"),s=t.parent().text().trim();!0===n?e.tags.find(`[data-item="category:${i}"]`).length||e._pushItem(`category:${i}`,s):e.tags.find(`[data-item="category:${i}"]`).remove()}))},_createItem:function(e,t){const i=jQuery("
  • "),n=jQuery(""),s=jQuery("");return i.addClass("cld-tax-order-list-item").attr("data-item",e),s.addClass("cld-tax-order-list-item-input").attr("type","hidden").attr("name","cld_tax_order[]").val(e),n.addClass("dashicons dashicons-menu cld-tax-order-list-item-handle"),i.append(n).append(t).append(s),i},_pushItem:function(e,t){let i=this._createItem(e,t);this.tags.append(i)},_sortable:function(){jQuery(".cld-tax-order-list").sortable({connectWith:".cld-tax-order",axis:"y",handle:".cld-tax-order-list-item-handle",placeholder:"cld-tax-order-list-item-placeholder",forcePlaceholderSize:!0,helper:"clone"})}};if(void 0!==window.CLDN&&(u._init(),jQuery("[data-wp-lists] .selectit input[checked]").map((e,t)=>{jQuery(t).trigger("change")})),wp.data&&wp.data.select("core/editor")){const e={};wp.data.subscribe((function(){let t=wp.data.select("core").getTaxonomies();if(t)for(let i in t){const n=wp.data.select("core/editor").getEditedPostAttribute(t[i].rest_base);e[t[i].slug]=n}}));const t=wp.element.createElement,i=i=>{class n extends i{constructor(e){super(e),this.currentItems=jQuery(".cld-tax-order-list-item").map((e,t)=>jQuery(t).data("item")).get()}makeItem(e){if(this.currentItems.includes(this.getId(e)))return;const t=this.makeElement(e);jQuery("#cld-tax-items").append(t)}removeItem(e){const t=jQuery(`[data-item="${this.getId(e)}"]`);t.length&&(t.remove(),this.currentItems=this.currentItems.filter(t=>t!==this.getId(e)))}findOrCreateTerm(e){return(e=super.findOrCreateTerm(e)).then(e=>this.makeItem(e)),e}onChange(t){super.onChange(t);const i=this.pickItem(t);i&&(e[this.props.slug].includes(i.id)?this.makeItem(i):this.removeItem(i))}pickItem(e){if("object"==typeof e){if(e.target){for(let t in this.state.availableTerms)if(this.state.availableTerms[t].id===parseInt(e.target.value))return this.state.availableTerms[t]}else if(Array.isArray(e)){let t=this.state.selectedTerms.filter(t=>!e.includes(t))[0];return void 0===t&&(t=e.filter(e=>!this.state.selectedTerms.includes(e))[0]),this.state.availableTerms.find(e=>e.name===t)}}else if("number"==typeof e){for(let t in this.state.availableTerms)if(this.state.availableTerms[t].id===e)return this.state.availableTerms[t]}else{let t;if(e.length>this.state.selectedTerms.length)for(let i in e)-1===this.state.selectedTerms.indexOf(e[i])&&(t=e[i]);else for(let i in this.state.selectedTerms)-1===e.indexOf(this.state.selectedTerms[i])&&(t=this.state.selectedTerms[i]);for(let e in this.state.availableTerms)if(this.state.availableTerms[e].name===t)return this.state.availableTerms[e]}}getId(e){return`${this.props.slug}:${e.id}`}makeElement(e){const t=jQuery("
  • "),i=jQuery(""),n=jQuery("");return t.addClass("cld-tax-order-list-item").attr("data-item",this.getId(e)),n.addClass("cld-tax-order-list-item-input").attr("type","hidden").attr("name","cld_tax_order[]").val(this.getId(e)),i.addClass("dashicons dashicons-menu cld-tax-order-list-item-handle"),t.append(i).append(e.name).append(n),t}}return e=>t(n,e)};wp.hooks.addFilter("editor.PostTaxonomyType","cld",i)}var p=u;const m={wpWrap:document.getElementById("wpwrap"),wpContent:document.getElementById("wpbody-content"),libraryWrap:document.getElementById("cloudinary-embed"),_init:function(){let e=this;"undefined"!=typeof CLD_ML&&(cloudinary.openMediaLibrary(CLD_ML.mloptions,{insertHandler:function(e){alert("Import is not yet implemented.")}}),window.addEventListener("resize",(function(t){e._resize()})),e._resize())},_resize:function(){let e=getComputedStyle(this.wpContent);this.libraryWrap.style.height=this.wpWrap.offsetHeight-parseInt(e.getPropertyValue("padding-bottom"))+"px"}};var h=m;m._init();i(2);i.d(t,"cloudinary",(function(){return f}));window.$=window.jQuery;const f={settings:s.a,sync:r,widget:l.a,Global_Transformations:c,Terms_Order:p,Media_Library:h}}]); \ No newline at end of file +!function(e){var t={};function i(n){if(t[n])return t[n].exports;var s=t[n]={i:n,l:!1,exports:{}};return e[n].call(s.exports,s,s.exports,i),s.l=!0,s.exports}i.m=e,i.c=t,i.d=function(e,t,n){i.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},i.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},i.t=function(e,t){if(1&t&&(e=i(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(i.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var s in e)i.d(n,s,function(t){return e[t]}.bind(null,s));return n},i.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return i.d(t,"a",t),t},i.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},i.p="",i(i.s=4)}([function(e,t){window,jQuery,jQuery(document).ready((function(e){e(document).on("tabs.init",(function(){var t=e(".settings-tab-trigger"),i=e(".settings-tab-section");e(this).on("click",".settings-tab-trigger",(function(n){var s=e(this),a=e(s.attr("href"));n.preventDefault(),t.removeClass("active"),i.removeClass("active"),s.addClass("active"),a.addClass("active"),e(document).trigger("settings.tabbed",s)})),e(".cld-field").not('[data-condition="false"]').each((function(){const t=e(this),i=t.data("condition");for(let n in i){const s=i[n],a=e("#field-"+n),r=t.closest("tr");a.on("change init",(function(){this.value===s||this.checked?r.show():r.hide()})),a.trigger("init")}})),e("#field-cloudinary_url").on("input change",(function(){let t=e(this),i=t.val();new RegExp(/^(cloudinary:\/\/){1}(\d)*[:]{1}[^:@]*[@]{1}[^@]*$/g).test(i)?(t.addClass("settings-valid-field"),t.removeClass("settings-invalid-field")):(t.removeClass("settings-valid-field"),t.addClass("settings-invalid-field"))})).trigger("change")})),e(".render-trigger[data-event]").each((function(){var t=e(this),i=t.data("event");t.trigger(i,this)}))}))},function(e,t){if(wp.media&&window.CLDN){wp.media.events.on("editor:image-edit",(function(e){e.metadata.cldoverwrite=null,e.image.className.split(" ").indexOf("cld-overwrite")>=0&&(e.metadata.cldoverwrite="true")})),wp.media.events.on("editor:image-update",(function(e){let t=e.image.className.split(" ");e.metadata.cldoverwrite&&-1===t.indexOf("cld-overwrite")?t.push("cld-overwrite"):!e.metadata.cldoverwrite&&t.indexOf("cld-overwrite")>=0&&delete t[t.indexOf("cld-overwrite")],e.image.className=t.join(" ")}));let e=null,t=wp.media.string.props;wp.media.string.props=function(i,n){return i.cldoverwrite&&(i.classes=["cld-overwrite"],e=!0),t(i,n)},wp.media.post=function(t,i){if("send-attachment-to-editor"===t){let t=wp.media.editor.get().state().get("selection").get(i.attachment);t.attributes.transformations&&(i.attachment.transformations=t.attributes.transformations),(i.html.indexOf("cld-overwrite")>-1||!0===e)&&(i.attachment.cldoverwrite=!0,e=null)}return wp.ajax.post(t,i)};wp.media.controller.Library;let i=wp.media.view.MediaFrame.Select,n=wp.media.view.MediaFrame.Post,s=wp.media.view.MediaFrame.ImageDetails,a=wp.media.view.MediaFrame.VideoDetails,r=wp.media.View.extend({tagName:"div",className:"cloudinary-widget",template:wp.template("cloudinary-dam"),active:!1,toolbar:null,frame:null,ready:function(){let e=this.controller,t=this.model.get("selection"),i=this.model.get("library"),n=wp.media.model.Attachment;if(CLDN.mloptions.multiple=e.options.multiple,this.cid!==this.active){if(CLDN.mloptions.inline_container="#cloudinary-dam-"+e.cid,1===t.length){var s=n.get(t.models[0].id);void 0!==s.attributes.public_id&&(CLDN.mloptions.asset={resource_id:s.attributes.public_id})}else CLDN.mloptions.asset=null;window.ml=cloudinary.openMediaLibrary(CLDN.mloptions,{insertHandler:function(s){for(let a=0;a=100&&void 0!==e.started?(this.submitButton.style.display=this.hide,this.stopButton.style.display=this.show):e.pending>0?(this.submitButton.style.display=this.show,this.stopButton.style.display=this.hide):e.processing>0?this.stopButton.style.display=this.show:this.stopButton.style.display=this.hide,e.percent<100?(this.barSyncCount.innerText=e.total,this.progressCount.innerText=e.done,this.progress.style.display=this.show):(this.completed.style.display=this.show,this.progress.style.display=this.hide)},_start:function(e){e.preventDefault(),a.stopButton.style.display=a.show,a.submitButton.style.display=a.hide,a.pushAttachments()},_reset:function(e){a.submitButton.style.display=a.hide,a.getStatus()},_init:function(e){"undefined"!=typeof cloudinaryApi&&((document.attachEvent?"complete"===document.readyState:"loading"!==document.readyState)?e():document.addEventListener("DOMContentLoaded",e))}};var r=a;a._init((function(){a._reset(),a.submitButton.addEventListener("click",a._start),a.stopButton.addEventListener("click",a.stopSync)}));var o=i(1),l=i.n(o);const d={sample:{image:document.getElementById("transformation-sample-image"),video:document.getElementById("transformation-sample-video")},preview:{image:document.getElementById("sample-image"),video:document.getElementById("sample-video")},fields:document.getElementsByClassName("cld-field"),button:{image:document.getElementById("refresh-image-preview"),video:document.getElementById("refresh-video-preview")},spinner:{image:document.getElementById("image-loader"),video:document.getElementById("video-loader")},activeItem:null,elements:{image:[],video:[]},_placeItem:function(e){null!==e&&(e.style.display="block",e.style.visibility="visible",e.style.position="absolute",e.style.top=e.parentElement.clientHeight/2-e.clientHeight/2+"px",e.style.left=e.parentElement.clientWidth/2-e.clientWidth/2+"px")},_setLoading:function(e){this.button[e].style.display="block",this._placeItem(this.button[e]),this.preview[e].style.opacity="0.1"},_build:function(e){this.sample[e].innerHTML="",this.elements[e]=[];for(let t of this.fields){if(e!==t.dataset.context)continue;let i=t.value.trim();if(i.length){if("select-one"===t.type){if("none"===i)continue;i=t.dataset.meta+"_"+i}else{let e=t.dataset.context;i=this._transformations(i,e,!0)}i&&this.elements[e].push(i)}}let t="";this.elements[e].length&&(t="/"+this.elements[e].join(",").replace(/ /g,"%20")),this.sample[e].textContent=t,this.sample[e].parentElement.href="https://res.cloudinary.com/demo/"+this.sample[e].parentElement.innerText.trim().replace("../","").replace(/ /g,"%20")},_clearLoading:function(e){this.spinner[e].style.visibility="hidden",this.activeItem=null,this.preview[e].style.opacity=1},_refresh:function(e,t){e&&e.preventDefault();let i=this,n=CLD_GLOBAL_TRANSFORMATIONS[t].preview_url+i.elements[t].join(",")+CLD_GLOBAL_TRANSFORMATIONS[t].file;if(this.button[t].style.display="none",this._placeItem(this.spinner[t]),"image"===t){let e=new Image;e.onload=function(){i.preview[t].src=this.src,i._clearLoading(t),e.remove()},e.onerror=function(){alert(CLD_GLOBAL_TRANSFORMATIONS[t].error),i._clearLoading(t)},e.src=n}else{let e=i._transformations(i.elements[t].join(","),t);samplePlayer.source({publicId:"dog",transformation:e}),i._clearLoading(t)}},_transformations:function(e,t,i=!1){let n=CLD_GLOBAL_TRANSFORMATIONS[t].valid_types,s=null,a=e.split("/"),r=[];for(let e=0;e{const n=!!i.length&&jQuery('[data-item="'+s+":"+i[0].id+'"]');n.length?n.remove():(jQuery(`.cld-tax-order-list-item:contains(${r})`).remove(),--e.startId),this.processTags(t)})}),jQuery("body").on("change",".selectit input",(function(){const t=jQuery(this),i=t.val(),n=t.is(":checked"),s=t.parent().text().trim();!0===n?e.tags.find(`[data-item="category:${i}"]`).length||e._pushItem(`category:${i}`,s):e.tags.find(`[data-item="category:${i}"]`).remove()}))},_createItem:function(e,t){const i=jQuery("
  • "),n=jQuery(""),s=jQuery("");return i.addClass("cld-tax-order-list-item").attr("data-item",e),s.addClass("cld-tax-order-list-item-input").attr("type","hidden").attr("name","cld_tax_order[]").val(e),n.addClass("dashicons dashicons-menu cld-tax-order-list-item-handle"),i.append(n).append(t).append(s),i},_pushItem:function(e,t){let i=this._createItem(e,t);this.tags.append(i)},_sortable:function(){jQuery(".cld-tax-order-list").sortable({connectWith:".cld-tax-order",axis:"y",handle:".cld-tax-order-list-item-handle",placeholder:"cld-tax-order-list-item-placeholder",forcePlaceholderSize:!0,helper:"clone"})}};if(void 0!==window.CLDN&&(u._init(),jQuery("[data-wp-lists] .selectit input[checked]").map((e,t)=>{jQuery(t).trigger("change")})),wp.data&&wp.data.select("core/editor")){const e={};wp.data.subscribe((function(){let t=wp.data.select("core").getTaxonomies();if(t)for(let i in t){const n=wp.data.select("core/editor").getEditedPostAttribute(t[i].rest_base);e[t[i].slug]=n}}));const t=wp.element.createElement,i=i=>{class n extends i{constructor(e){super(e),this.currentItems=jQuery(".cld-tax-order-list-item").map((e,t)=>jQuery(t).data("item")).get()}makeItem(e){if(this.currentItems.includes(this.getId(e)))return;const t=this.makeElement(e);jQuery("#cld-tax-items").append(t)}removeItem(e){const t=jQuery(`[data-item="${this.getId(e)}"]`);t.length&&(t.remove(),this.currentItems=this.currentItems.filter(t=>t!==this.getId(e)))}findOrCreateTerm(e){return(e=super.findOrCreateTerm(e)).then(e=>this.makeItem(e)),e}onChange(t){super.onChange(t);const i=this.pickItem(t);i&&(e[this.props.slug].includes(i.id)?this.makeItem(i):this.removeItem(i))}pickItem(e){if("object"==typeof e){if(e.target){for(let t in this.state.availableTerms)if(this.state.availableTerms[t].id===parseInt(e.target.value))return this.state.availableTerms[t]}else if(Array.isArray(e)){let t=this.state.selectedTerms.filter(t=>!e.includes(t))[0];return void 0===t&&(t=e.filter(e=>!this.state.selectedTerms.includes(e))[0]),this.state.availableTerms.find(e=>e.name===t)}}else if("number"==typeof e){for(let t in this.state.availableTerms)if(this.state.availableTerms[t].id===e)return this.state.availableTerms[t]}else{let t;if(e.length>this.state.selectedTerms.length)for(let i in e)-1===this.state.selectedTerms.indexOf(e[i])&&(t=e[i]);else for(let i in this.state.selectedTerms)-1===e.indexOf(this.state.selectedTerms[i])&&(t=this.state.selectedTerms[i]);for(let e in this.state.availableTerms)if(this.state.availableTerms[e].name===t)return this.state.availableTerms[e]}}getId(e){return`${this.props.slug}:${e.id}`}makeElement(e){const t=jQuery("
  • "),i=jQuery(""),n=jQuery("");return t.addClass("cld-tax-order-list-item").attr("data-item",this.getId(e)),n.addClass("cld-tax-order-list-item-input").attr("type","hidden").attr("name","cld_tax_order[]").val(this.getId(e)),i.addClass("dashicons dashicons-menu cld-tax-order-list-item-handle"),t.append(i).append(e.name).append(n),t}}return e=>t(n,e)};wp.hooks.addFilter("editor.PostTaxonomyType","cld",i)}var p=u;const m={wpWrap:document.getElementById("wpwrap"),wpContent:document.getElementById("wpbody-content"),libraryWrap:document.getElementById("cloudinary-embed"),_init:function(){let e=this;"undefined"!=typeof CLD_ML&&(cloudinary.openMediaLibrary(CLD_ML.mloptions,{insertHandler:function(e){alert("Import is not yet implemented.")}}),window.addEventListener("resize",(function(t){e._resize()})),e._resize())},_resize:function(){let e=getComputedStyle(this.wpContent);this.libraryWrap.style.height=this.wpWrap.offsetHeight-parseInt(e.getPropertyValue("padding-bottom"))+"px"}};var h=m;m._init();i(2);i.d(t,"cloudinary",(function(){return f}));window.$=window.jQuery;const f={settings:s.a,sync:r,widget:l.a,Global_Transformations:c,Terms_Order:p,Media_Library:h}}]); \ No newline at end of file diff --git a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/php/class-connect.php b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/php/class-connect.php index 7f2b62d39..163d9d5ee 100644 --- a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/php/class-connect.php +++ b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/php/class-connect.php @@ -10,7 +10,6 @@ use Cloudinary\Component\Config; use Cloudinary\Component\Notice; use Cloudinary\Component\Setup; -use Cloudinary\Connect\API; /** * Cloudinary connection class. @@ -302,25 +301,33 @@ public function setup() { */ public function get_config() { $signature = get_option( 'cloudinary_connection_signature', null ); - if ( empty( $signature ) ) { - // Check if theres a previous version. - $version = get_option( 'cloudinary_version' ); - if ( version_compare( $this->plugin->version, $version, '>' ) ) { + $version = get_option( 'cloudinary_version' ); + if ( empty( $signature ) || version_compare( $this->plugin->version, $version, '>' ) ) { + // Check if there's a previous version, or missing signature. + $cld_url = get_option( 'cloudinary_url', null ); + if ( is_null( $cld_url ) ) { + // Post V1. + $data = get_option( 'cloudinary_connect', array() ); + if ( ! isset( $data['cloudinary_url'] ) || empty( $data['cloudinary_url'] ) ) { + return null; // return null to indicate not valid. + } + } else { + // from V1 to V2. $data = array( - 'cloudinary_url' => get_option( 'cloudinary_url' ), + 'cloudinary_url' => $cld_url, ); - $test = $this->test_connection( $data['cloudinary_url'] ); - if ( 'connection_success' === $test['type'] ) { - $signature = md5( $data['cloudinary_url'] ); - - // remove filters as we've already verified it and 'add_settings_error()' isin't available yet. - remove_filter( 'pre_update_option_cloudinary_connect', array( $this, 'verify_connection' ) ); - update_option( 'cloudinary_connect', $data ); - update_option( 'cloudinary_connection_signature', $signature ); - update_option( 'cloudinary_version', $this->plugin->version ); - delete_option( 'cloudinary_settings_cache' ); // remove the cache. - $this->plugin->config['settings']['connect'] = $data; // Set the connection url for this round. - } + } + $test = $this->test_connection( $data['cloudinary_url'] ); + if ( 'connection_success' === $test['type'] ) { + $signature = md5( $data['cloudinary_url'] ); + + // remove filters as we've already verified it and 'add_settings_error()' isin't available yet. + remove_filter( 'pre_update_option_cloudinary_connect', array( $this, 'verify_connection' ) ); + update_option( 'cloudinary_connect', $data ); + update_option( 'cloudinary_connection_signature', $signature ); + update_option( 'cloudinary_version', $this->plugin->version ); + delete_option( 'cloudinary_settings_cache' ); // remove the cache. + $this->plugin->config['settings']['connect'] = $data; // Set the connection url for this round. } } diff --git a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/php/class-media.php b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/php/class-media.php index 3c654d76c..f91414f2a 100644 --- a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/php/class-media.php +++ b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/php/class-media.php @@ -497,7 +497,6 @@ public function apply_default_transformations( array $transformations, $type = ' $global = $this->global_transformations->globals[ $type ]; $default = array(); if ( 'video' === $type ) { - $default['quality'] = 'auto'; if ( isset( $global['video_limit_bitrate'] ) && 'on' === $global['video_limit_bitrate'] ) { $default['bit_rate'] = $global['video_bitrate'] . 'k'; } @@ -1007,7 +1006,7 @@ public function down_sync_asset() { } $transformations = $this->get_transformations_from_string( $url ); if ( ! empty( $transformations ) ) { - $sync_key .= wp_json_encode( $transformations ); + $sync_key .= wp_json_encode( $transformations ); $asset['transformations'] = $transformations; } // Check Format and url extension. @@ -1229,6 +1228,14 @@ public function get_post_meta( $post_id, $key, $single = false ) { $data = $this->build_cached_meta( $post_id, $key, $single ); } + // If public_id, ensure there's a sync_key saved. + if ( '_public_id' === $key && empty( $meta_data[ Sync::META_KEYS['cloudinary'] ]['_sync_key'] ) ) { + + //$sync_key = '_' . md5( $data ); + //$this->update_post_meta( $post_id, '_sync_key', $sync_key ); + //update_post_meta( $post_id, $sync_key, true ); // Set sync_key. + } + return $data; } @@ -1243,7 +1250,9 @@ public function get_post_meta( $post_id, $key, $single = false ) { */ public function build_cached_meta( $post_id, $key, $single ) { $data = get_post_meta( $post_id, $key, $single ); - $this->update_post_meta( $post_id, $key, $data ); + if ( '' !== $data ) { + $this->update_post_meta( $post_id, $key, $data ); + } return $data; } @@ -1251,9 +1260,9 @@ public function build_cached_meta( $post_id, $key, $single ) { /** * Update cloudinary metadata. * - * @param int $post_id The attachment ID. - * @param string $key The meta key to get. - * @param array $data $the meta data to update. + * @param int $post_id The attachment ID. + * @param string $key The meta key to get. + * @param string|array $data $the meta data to update. */ public function update_post_meta( $post_id, $key, $data ) { $meta_data = wp_get_attachment_metadata( $post_id, true ); @@ -1266,6 +1275,23 @@ public function update_post_meta( $post_id, $key, $data ) { update_post_meta( $post_id, $key, $data ); } + /** + * Delete cloudinary metadata. + * + * @param int $post_id The attachment ID. + * @param string $key The meta key to get. + */ + public function delete_post_meta( $post_id, $key ) { + $meta_data = wp_get_attachment_metadata( $post_id, true ); + if ( is_array( $meta_data ) && isset( $meta_data[ Sync::META_KEYS['cloudinary'] ] ) && is_array( $meta_data[ Sync::META_KEYS['cloudinary'] ] ) ) { + // Only do this side if has been set before. + unset( $meta_data[ Sync::META_KEYS['cloudinary'] ][ $key ] ); + wp_update_attachment_metadata( $post_id, $meta_data ); + } + // Delete meta data. + delete_post_meta( $post_id, $key ); + } + /** * Setup the hooks and base_url if configured. */ diff --git a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/php/class-rest-api.php b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/php/class-rest-api.php index 90314aaa3..c857cc0dd 100644 --- a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/php/class-rest-api.php +++ b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/php/class-rest-api.php @@ -63,11 +63,12 @@ public function background_request( $endpoint, $params, $method = 'POST' ) { // Setup a call for a background sync. $params['nonce'] = wp_create_nonce( 'wp_rest' ); $args = array( - 'timeout' => 1, - 'blocking' => false, - 'method' => $method, - 'headers' => array(), - 'body' => $params, + 'timeout' => 1, + 'blocking' => false, + 'sslverify' => false, + 'method' => $method, + 'headers' => array(), + 'body' => $params, ); if ( is_user_logged_in() ) { // Setup cookie. @@ -75,7 +76,7 @@ public function background_request( $endpoint, $params, $method = 'POST' ) { array_pop( $logged_cookie ); // remove the scheme. // Add logged in cookie to request. - $args['cookies'] = array( + $args['cookies'] = array( new \WP_Http_Cookie( array( 'name' => LOGGED_IN_COOKIE, @@ -85,8 +86,9 @@ public function background_request( $endpoint, $params, $method = 'POST' ) { $url ), ); - $args['headers']['X-WP-Nonce'] = $params['nonce']; + } + $args['headers']['X-WP-Nonce'] = $params['nonce']; // Send request. wp_safe_remote_request( $url, $args ); diff --git a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/php/media/class-upgrade.php b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/php/media/class-upgrade.php index f4568904f..55517a0db 100644 --- a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/php/media/class-upgrade.php +++ b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/php/media/class-upgrade.php @@ -55,6 +55,9 @@ public function check_cloudinary_version( $cloudinary_id, $attachment_id ) { */ if ( ! empty( $meta['cloudinary'] ) && empty( $public_id ) ) { $cloudinary_id = $this->convert_cloudinary_version( $attachment_id ); + } elseif ( ! empty( $public_id ) ) { + // Has public ID, but not fully down synced. + $cloudinary_id = $public_id; } } @@ -103,18 +106,8 @@ function ( $val ) use ( $media ) { // Remove extension. $path = pathinfo( $public_id ); $public_id = strstr( $public_id, '.' . $path['extension'], true ); - // Save public ID. $this->media->update_post_meta( $attachment_id, Sync::META_KEYS['public_id'], $public_id ); - // Setup a call for a background sync. - $params = array( - 'attachment_id' => $attachment_id, - 'src' => $file, - 'transformations' => $media->get_transformations_from_string( $file ), - 'filename' => basename( $file ), - ); - $media->plugin->components['api']->background_request( 'asset', $params ); - return $public_id; } @@ -122,10 +115,10 @@ function ( $val ) use ( $media ) { * Setup hooks for the filters. */ public function setup_hooks() { - add_filter( 'cloudinary_id', array( $this, 'check_cloudinary_version' ), 9, 2 ); // Priority 9, to take preference over prep_on_demand_upload. + add_filter( 'cloudinary_id', array( $this, 'check_cloudinary_version' ), 10, 2 ); // Priority 10, to allow prep_on_demand_upload. // Add a redirection to the new plugin settings, from the old plugin. - if( is_admin() ) { + if ( is_admin() ) { add_action( 'admin_menu', function () { global $plugin_page; if ( ! empty( $plugin_page ) && false !== strpos( $plugin_page, 'cloudinary-image-management-and-manipulation-in-the-cloud-cdn' ) ) { diff --git a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/php/media/class-video.php b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/php/media/class-video.php index a461f841f..d1fbf6b5b 100644 --- a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/php/media/class-video.php +++ b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/php/media/class-video.php @@ -104,6 +104,7 @@ public function init_player() { if ( ! empty( $has_video ) || ! empty( $video_tags ) ) { // Setup initial scripts. wp_enqueue_style( 'cld-player' ); + wp_enqueue_style( 'cld-player-local' ); wp_enqueue_script( 'cld-player' ); // Init cld script object. @@ -369,29 +370,31 @@ public function print_video_scripts() { var cldVideos = ; for ( var videoInstance in cldVideos ) { - var cldConfig = cldVideos[ videoInstance ]; - var cldId = 'cloudinary-video-' + videoInstance; - cld.videoPlayer( cldId, cldConfig ); + var cldConfig = cldVideos[ videoInstance ]; + var cldId = 'cloudinary-video-' + videoInstance; + cld.videoPlayer( cldId, cldConfig ); } window.addEventListener( 'load', function() { - for ( var videoInstance in cldVideos ) { - var cldId = 'cloudinary-video-' + videoInstance; - var videoContainer = document.getElementById( cldId ); - var videoElement = videoContainer.getElementsByTagName( 'video' ); - - if ( videoElement.length === 1 ) { - videoElement = videoElement[0]; - - - config['video_freeform'] ): ?> - videoElement.src = videoElement.src.replace( - 'upload/', - 'upload/config['video_freeform'] ) ?>/' - ); - - } - } + for ( var videoInstance in cldVideos ) { + var cldId = 'cloudinary-video-' + videoInstance; + var videoContainer = document.getElementById( cldId ); + var videoElement = videoContainer.getElementsByTagName( 'video' ); + + if ( videoElement.length === 1 ) { + videoElement = videoElement[0]; + videoElement.style.width = '100%'; + + config['video_freeform'] ): ?> + if ( videoElement.src.indexOf( 'config['video_freeform'] ) ?>' ) === -1 ) { + videoElement.src = videoElement.src.replace( + 'upload/', + 'upload/config['video_freeform'] ) ?>/' + ); + } + + } + } } ); media->plugin->dir_url . 'css/video.css', null, self::PLAYER_VER ); + wp_register_script( 'cld-core', 'https://unpkg.com/cloudinary-core@' . self::CORE_VER . '/cloudinary-core-shrinkwrap.min.js', null, self::CORE_VER, true ); wp_register_script( 'cld-player', 'https://unpkg.com/cloudinary-video-player@' . self::PLAYER_VER . '/dist/cld-video-player.min.js', array( 'cld-core' ), self::PLAYER_VER, true ); } @@ -427,13 +432,13 @@ public function setup_hooks() { add_filter( 'wp_video_shortcode_override', array( $this, 'filter_video_shortcode' ), 10, 2 ); // only filter video tags in front end. if ( ! is_admin() ) { - add_filter( 'the_content', array( $this, 'filter_video_tags' ), 10 ); + add_filter( 'the_content', array( $this, 'filter_video_tags' ), 4 ); } add_action( 'wp_print_styles', array( $this, 'init_player' ) ); add_action( 'wp_footer', array( $this, 'print_video_scripts' ) ); // Add inline scripts for gutenberg. add_action( 'enqueue_block_editor_assets', array( $this, 'enqueue_block_assets' ) ); - self::register_scripts_styles(); + $this->register_scripts_styles(); } } diff --git a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/php/sync/class-delete-sync.php b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/php/sync/class-delete-sync.php index 47387dba4..3852f38a4 100644 --- a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/php/sync/class-delete-sync.php +++ b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/php/sync/class-delete-sync.php @@ -95,7 +95,7 @@ public function delete_asset( $post_id ) { } // Next we need to check that the file is in the cloudinary folder. $parts = explode( '/', $public_id ); - $cloudinary_folder = $this->plugin->config['settings']['general']['cloudinary_folder']; + $cloudinary_folder = $this->plugin->config['settings']['sync_media']['cloudinary_folder'] ? $this->plugin->config['settings']['sync_media']['cloudinary_folder'] : ''; if ( $cloudinary_folder === $parts[0] ) { $type = $this->plugin->components['sync']->managers['push']->get_resource_type( $post_id ); $options = array( diff --git a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/php/sync/class-download-sync.php b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/php/sync/class-download-sync.php index cda52be93..cb4c9e6c6 100644 --- a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/php/sync/class-download-sync.php +++ b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/php/sync/class-download-sync.php @@ -7,6 +7,8 @@ namespace Cloudinary\Sync; +use Cloudinary\Sync; + /** * Class Download_Sync. * @@ -70,21 +72,16 @@ public function rest_endpoints( $endpoints ) { public function rest_can_upload_files( \WP_REST_Request $request ) { // This would have been from an ajax call. Therefore verify based on capability. - if ( is_user_logged_in() ) { - return current_user_can( 'upload_files' ); - } - - // If we get here, this is a background post, which will have a bg post nonce created. - $nonce = $request->get_param( 'nonce' ); - - return wp_verify_nonce( $nonce, 'wp_rest' ); + return current_user_can( 'upload_files' ); } /** - * Handle a failed download by deleting teh temp attachment and returning the error in json. + * Handle a failed download by deleting the temp attachment and returning the error in json. * * @param int $attachment_id The attachment ID. * @param string $error The error text to return. + * + * @return \WP_Error */ public function handle_failed_download( $attachment_id, $error ) { // @todo: Place a handler to catch the error for logging. @@ -109,6 +106,73 @@ public function rest_download_asset( \WP_REST_Request $request ) { $file_name = $request->get_param( 'filename' ); $transformations = (array) $request->get_param( 'transformations' ); + $response = $this->download_asset( $attachment_id, $file_path, $file_name, $transformations ); + if ( is_wp_error( $response ) ) { + $this->handle_failed_download( $attachment_id, $response->get_error_message() ); + } + + return rest_ensure_response( $response ); + } + + /** + * Prepare and sync down an asset stored remotely. + * + * @param $attachment_id + * + * @return array|\WP_Error + */ + public function down_sync( $attachment_id ) { + $file = get_post_meta( $attachment_id, '_wp_attached_file', true ); + $path = wp_parse_url( $file, PHP_URL_PATH ); + $media = $this->plugin->components['media']; + $parts = explode( '/', $path ); + $parts = array_map( + function ( $val ) use ( $media ) { + if ( empty( $val ) ) { + return false; + } + if ( $val === $media->credentials['cloud_name'] ) { + return false; + } + if ( in_array( $val, [ 'image', 'video', 'upload' ], true ) ) { + return false; + } + $transformation_maybe = $media->get_transformations_from_string( $val ); + if ( ! empty( $transformation_maybe ) ) { + return false; + } + if ( substr( $val, 0, 1 ) === 'v' && is_numeric( substr( $val, 1 ) ) ) { + return false; + } + + return $val; + }, + $parts + ); + // Build public_id. + $parts = array_filter( $parts ); + $public_id = implode( '/', $parts ); + // Remove extension. + $path = pathinfo( $public_id ); + $public_id = strstr( $public_id, '.' . $path['extension'], true ); + // Save public ID. + $media->update_post_meta( $attachment_id, Sync::META_KEYS['public_id'], $public_id ); + + return $this->download_asset( $attachment_id, $file, basename( $file ), $media->get_transformations_from_string( $file ) ); + } + + /** + * Download an attachment source to the file system. + * + * @param int $attachment_id The attachment ID. + * @param string $file_path The path of the file. + * @param string $file_name The filename. + * @param array|null $transformations + * + * @return array|\WP_Error + */ + public function download_asset( $attachment_id, $file_path, $file_name, $transformations = null ) { + // Get the image and update the attachment. require_once ABSPATH . WPINC . '/class-http.php'; require_once ABSPATH . 'wp-admin/includes/file.php'; @@ -120,8 +184,7 @@ public function rest_download_asset( \WP_REST_Request $request ) { // Prime a file to stream to. $upload = wp_upload_bits( $file_name, null, 'temp' ); if ( ! empty( $upload['error'] ) ) { - $this->handle_failed_download( $attachment_id, $upload['error'] ); - wp_send_json_error( $upload['error'] ); + return new \WP_Error( 'download_error', $upload['error'] ); } // If the public_id of an asset includes a file extension, a derived item will have the extension duplicated, but not in the source URL. // This creates a 404. So, instead, we get the actual file name, and use that over the file name that the source url has. @@ -137,7 +200,7 @@ public function rest_download_asset( \WP_REST_Request $request ) { ); if ( is_wp_error( $response ) ) { - $this->handle_failed_download( $attachment_id, $response->get_error_message() ); + return $response; } if ( 200 !== $response['response']['code'] ) { $header_error = wp_remote_retrieve_header( $response, 'x-cld-error' ); @@ -146,7 +209,8 @@ public function rest_download_asset( \WP_REST_Request $request ) { } else { $error = __( 'Could not download the Cloudinary asset.', 'cloudinary' ); } - $this->handle_failed_download( $attachment_id, $error ); + + return new \WP_Error( 'download_error', $error ); } // Prepare the asset. @@ -157,7 +221,7 @@ public function rest_download_asset( \WP_REST_Request $request ) { wp_update_attachment_metadata( $attachment_id, $meta ); } catch ( \Exception $e ) { - $this->handle_failed_download( $attachment_id, $e->getMessage() ); + return new \WP_Error( 'download_error', $e->getMessage() ); } $attachment = wp_prepare_attachment_for_js( $attachment_id ); @@ -181,6 +245,6 @@ public function rest_download_asset( \WP_REST_Request $request ) { 'data' => $attachment, ); - return rest_ensure_response( $response ); + return $response; } } diff --git a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/php/sync/class-push-sync.php b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/php/sync/class-push-sync.php index fe98e4448..a1a9ae025 100644 --- a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/php/sync/class-push-sync.php +++ b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/php/sync/class-push-sync.php @@ -210,6 +210,7 @@ public function rest_push_attachments( \WP_REST_Request $request ) { // Check if there is a Cloudinary ID in case this was synced on-demand before being processed by the queue. add_filter( 'cloudinary_on_demand_sync_enabled', '__return_false' ); // Disable the on-demand sync since we want the status. + add_filter( 'cloudinary_id', '__return_false' ); // Disable the on-demand sync since we want the status. if ( false === $this->plugin->components['media']->cloudinary_id( $post_id ) ) { $stat = $this->push_attachments( array( $post_id ) ); if ( ! empty( $stat['processed'] ) ) { @@ -307,11 +308,12 @@ private function get_sync_type( $attachment ) { /** * Prepare an attachment for upload. * - * @param int|\WP_Post $post The attachment to prepare. + * @param int|\WP_Post $post The attachment to prepare. + * @param bool $down_sync Flag to determine if a missing file starts a downsync. * * @return array|\WP_Error */ - public function prepare_upload( $post ) { + public function prepare_upload( $post, $down_sync = false ) { if ( is_numeric( $post ) ) { $post = get_post( $post ); @@ -331,9 +333,28 @@ public function prepare_upload( $post ) { $file = get_attached_file( $post->ID ); if ( empty( $file ) ) { return new \WP_Error( 'attachment_no_file', __( 'Attachment did not have a file.', 'cloudinary' ) ); + } elseif ( ! file_exists( $file ) ) { + // May be an old upload type. + $src = get_post_meta( $post->ID, '_wp_attached_file', true ); + if ( $this->plugin->components['media']->is_cloudinary_url( $src ) ) { + // Download first maybe. + if ( true === $down_sync ) { + $download = $this->plugin->components['sync']->managers['download']->down_sync( $post->ID ); + if ( is_wp_error( $download ) ) { + update_post_meta( $post->ID, Sync::META_KEYS['sync_error'], $download->get_error_message() ); + + return new \WP_Error( 'attachment_download_error', $download->get_error_message() ); + } + $file = get_attached_file( $post->ID ); + $file_size = filesize( $file ); + } else { + $file_size = 0; + } + } + } else { + $file_size = filesize( $file ); } - $file_size = filesize( $file ); $resource_type = $this->get_resource_type( $post ); $max_size = ( 'image' === $resource_type ? 'max_image_size' : 'max_video_size' ); @@ -341,7 +362,7 @@ public function prepare_upload( $post ) { $max_size_hr = size_format( $this->plugin->components['connect']->usage[ $max_size ] ); // translators: variable is file size. $error = sprintf( __( 'File size exceeds the maximum of %s. This media asset will be served from WordPress.', 'cloudinary' ), $max_size_hr ); - delete_post_meta( $post->ID, Sync::META_KEYS['pending'] ); // Remove Flag. + $this->plugin->components['media']->delete_post_meta( $post->ID, Sync::META_KEYS['pending'] ); // Remove Flag. return new \WP_Error( 'upload_error', $error ); } @@ -481,7 +502,7 @@ public function push_attachments( $attachments ) { // Go over each attachment. foreach ( $attachments as $attachment ) { $attachment = get_post( $attachment ); - $upload = $this->prepare_upload( $attachment->ID ); + $upload = $this->prepare_upload( $attachment->ID, true ); // Filter out any attachments with problematic options. if ( is_wp_error( $upload ) ) { @@ -555,8 +576,8 @@ public function push_attachments( $attachments ) { if ( ! empty( $result['version'] ) ) { $meta_data[ Sync::META_KEYS['version'] ] = $result['version']; } - delete_post_meta( $attachment->ID, Sync::META_KEYS['pending'] ); - $this->plugin->components['media']->update_post_meta( $attachment->ID, Sync::META_KEYS['sync_error'], false ); + $this->plugin->components['media']->delete_post_meta( $attachment->ID, Sync::META_KEYS['pending'] ); + $this->plugin->components['media']->delete_post_meta( $attachment->ID, Sync::META_KEYS['sync_error'], false ); if ( ! empty( $this->plugin->config['settings']['global_transformations']['enable_breakpoints'] ) ) { if ( ! empty( $result['responsive_breakpoints'] ) ) { // Images only. $meta_data[ Sync::META_KEYS['breakpoints'] ] = $result['responsive_breakpoints'][0]['breakpoints']; @@ -564,20 +585,20 @@ public function push_attachments( $attachments ) { // Remove records of breakpoints. delete_post_meta( $attachment->ID, Sync::META_KEYS['breakpoints'] ); } - if ( empty( $upload['options']['responsive_breakpoints']['transformation'] ) ) { - // a transformation breakpoints only ever happens on a down sync. - $sync_key = md5( $upload['options']['public_id'] ); - $meta_data[ $sync_key ] = true; - $meta_data[ '_' . $sync_key ] = true; - update_post_meta( $attachment->ID, $sync_key, true ); - // Add base ID. - update_post_meta( $attachment->ID, '_' . $sync_key, true ); - } + } + if ( ! empty( $upload['options']['public_id'] ) ) { + // a transformation breakpoints only ever happens on a down sync. + $sync_key = '_' . md5( $upload['options']['public_id'] ); + $meta_data['sync_key'] = true; + + // Add base ID. + update_post_meta( $attachment->ID, $sync_key, true ); } $stats['success'][] = $attachment->post_title; $meta = wp_get_attachment_metadata( $attachment->ID, true ); $meta[ Sync::META_KEYS['cloudinary'] ] = $meta_data; wp_update_attachment_metadata( $attachment->ID, $meta ); + $this->plugin->components['media']->update_post_meta( $attachment->ID, Sync::META_KEYS['public_id'], $upload['options']['public_id'] ); // Search and update link references in content. $content_search = new \WP_Query( array( 's' => 'wp-image-' . $attachment->ID, 'fields' => 'ids', 'posts_per_page' => 1000 ) ); if ( ! empty( $content_search->found_posts ) ) { diff --git a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/php/sync/class-upload-queue.php b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/php/sync/class-upload-queue.php index df904c314..6d0b77683 100644 --- a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/php/sync/class-upload-queue.php +++ b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/php/sync/class-upload-queue.php @@ -199,13 +199,6 @@ public function build_queue() { 'key' => Sync::META_KEYS['public_id'], 'compare' => 'NOT EXISTS', ), - array( - 'relation' => 'OR', - array( - 'key' => Sync::META_KEYS['signature'], - 'compare' => 'NOT EXISTS', - ), - ), ), 'ignore_sticky_posts' => false, 'no_found_rows' => true, diff --git a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/php/sync/class-upload-sync.php b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/php/sync/class-upload-sync.php index d4ff3e4a1..2c4bc7f62 100644 --- a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/php/sync/class-upload-sync.php +++ b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/php/sync/class-upload-sync.php @@ -66,7 +66,7 @@ private function register_hooks() { // Add action to upload. add_action( 'add_attachment', array( $this, 'push_on_upload' ), 10 ); // Filter id for on-demand upload sync. - add_filter( 'cloudinary_id', array( $this, 'prep_on_demand_upload' ), 10, 2 ); + add_filter( 'cloudinary_id', array( $this, 'prep_on_demand_upload' ), 9, 2 ); // Show sync status. add_filter( 'cloudinary_media_status', array( $this, 'filter_status' ), 10, 2 ); // Hook for on demand upload push. @@ -119,6 +119,13 @@ public function prep_on_demand_upload( $cloudinary_id, $attachment_id ) { // Get the file size to make sure it can exist in cloudinary. if ( file_exists( $file ) && filesize( $file ) < $this->plugin->components['connect']->usage[ $max_size ] ) { $this->add_to_sync( $attachment_id ); + } else { + // Check if the src is a url. + $file = get_post_meta( $attachment_id, '_wp_attached_file', true ); + if ( $this->plugin->components['media']->is_cloudinary_url( $file ) ) { + // Download sync. + $this->add_to_sync( $attachment_id ); + } } } } diff --git a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/readme.txt b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/readme.txt index bf2edb87a..19fdc2fbe 100644 --- a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/readme.txt +++ b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/readme.txt @@ -1,246 +1,124 @@ -=== Cloudinary - Image management and manipulation in the cloud + CDN === -Contributors: cloudinary -Tags: image, images, media, gallery, photo, photos, picture, pictures, thumbnail, upload, admin, administration, api, cms, dashboard, editor, flickr, integration, manage, mobile, page, pages, post, social-media -Requires at least: 3.0 -Tested up to: 5.1 +=== Cloudinary – Dynamic Image and Video Management === +Contributors: Cloudinary, XWP, Automattic +Tags: images, videos, DAM, optimizations, CDN, media, gallery, photo, photos, picture, pictures, thumbnail, upload, admin, administration, api, cms, dashboard, editor, integration, manage, mobile, social-media +Requires at least: 4.7 +Tested up to: 5.4 +Requires PHP: 5.6 Stable tag: trunk License: GPLv2 License URI: http://www.gnu.org/licenses/gpl-2.0.html -Cloudinary supercharges your images! Upload images to the cloud, deliver optimized via a fast CDN. Perform smart resizing and apply effects. +Cloudinary is the leading image, video, and rich media management solution that’s used by the world’s leading brands and innovative startups, now available as an easy plugin for WordPress. == Description == +Cloudinary makes automating your image, video, and rich media workflow easy, offering significant advantages over native WordPress capabilities. From upload to management to manipulation and optimization through delivery, all features are offered from within the plugin. -**Cloudinary is your one stop shop for EVERY image related task.** +Optimize your site performance and user experience with faster page load times, advanced auto-responsive delivery, and better visual experience. Automate quality and encoding settings, scale and crop images using AI to focus on the most important region, apply comprehensive transformations and effects, and deliver on any device in any resolution or pixel density. -With Cloudinary, all your images are automatically uploaded, normalized, optimized and backed-up in the cloud instead of being hosted on your servers. - -With Cloudinary, you can stop messing around with image editors. Cloudinary can manipulate and transform your images online, on-the-fly, directly from your WordPress console. Enhance your images using every possible filter and effect you can think of. All manipulations are done in the cloud using super-powerful hardware, and all resulting images are cached, optimized (smushed and more) and delivered via a lightning fast content delivery network (CDN). - -Install Cloudinary now, get the most powerful image solution available today, and get your WordPress powered site to the next level. +And with an embedded digital asset management platform offering full DAM capabilities, you won’t need to leave your WordPress environment. Take full advantage of advanced search, AI tagging, automation, collections, structured metadata, and an intuitive UI making it much easier to manage all of your media in WordPress. = Requirements = -* While you don't need to install any image software on your server, you will need to register for a (free) [Cloudinary account](https://cloudinary.com/users/register/free) to use the plugin and start uploading images to the cloud. -* Is your site gaining traction? Upgrade to one of our PRO accounts for higher usage limits with practically limitless scale. - - -= Overview = - -* Vast array of image manipulation capabilities. -* Virtually limitless scale. -* Lightning-fast image delivery. -* Highly improved user experience & website performance. -* Useful from small websites and blogs to large enterprise solutions. - -= Image Uploads = - -* Upload any image type: JPG, PNG, GIF, animated GIF, BMP, ICO, TIFF, PSD, WebP and even PDFs. -* Upload directly from your desktop. -* Upload a single image or multiple images with ease. -* Remote fetching from public URLs - -= Image Manipulations = - -You can apply one or more transformations and manipulations on every image: - -* **Image formats** - easily convert image formats and modify image quality. -* **Apply effects & filters** - sharpen, sepia, saturation, grayscale, black & white, hue, brightness, oil paint, pixelate, vignette, add borders. -* **Overlays & Text** - add watermarks, add image overlay and underlay, add text to the image. -* **Face detection** - face detection based cropping, thumbnail, multiple faces detection, pixelate faces. -* **Rotates & flips** - Image rotation (90 degrees), arbitrary rotation, exif-based automatic rotation, vertical & horizontal flips, -* **Shape alteration** - add rounded corners, crop to ellipses and circles. -* **Resize & crop** - scale, fill, fit, pad, crop, limit, custom coordinates. -* **PDF Processing** - extract pages, convert to images. - -= Image Storage = - -* All your images are stored in a cloud-based persistent storage. -* Scales to Terabytes and more. -* Highly available redundant storage. -* All your photos are automatically backed-up, including revision tracking. +* All you need to get started is to register for a free [Cloudinary account](https://cloudinary.com/users/register/free?utm_source=wp&utm_medium=wpmarketplace&utm_campaign=wpmarketplace) to use the plugin and start uploading your media to the cloud. +* As your site’s media management needs grow, you have the choice to easily upgrade to higher usage plans with practically limitless scale. -= Image Delivery = += Highlights = -* All your images are automatically delivered via a lightning-fast world-wide Content Delivery Network (CDN). -* Images are smartly cached for performance optimization, using every best practice in the book. -* Multiple CDN sub-domains (Domain Sharding). - -= Image Optimization = - -* Your images are automatically optimized. Their file size is reduced and they are delivered faster to your visitors. -* Stripping meta data. -* Converting formats. -* Optimizing compression. +* Automatically optimize and apply specified global transformations to pre-existing media upon plugin installation as well as all future uploads. +* Search and browse your media with AI-powered tagging and attributes including file type, size, format, and many other parameters all within the media library. +* Automatic responsive images for delivery on various devices in different resolutions. +* Taxonomy level transformations allow users to set transformations by “category” or “tag” and apply these in real time. +* Transcode, AI crop, apply filters, generate thumbnails, and more with our video transformation capabilities. +* The most comprehensive array of image and video manipulation capabilities, powered by AI. +* Ability to display videos using Cloudinary’s video player giving additional features such as bitrate limit, analytics, monetization, and more. = Simple Integration = -* Upload and manage your images with Cloudinary directly from your WordPress interface. -* Migrate all your locally hosted images to Cloudinary. -* Move your existing posts' images to Cloudinary in a single click. -* Easily restore your posts to use local images instead of Cloudinary. -* Seamlessly use Cloudinary's processed images as WordPress featured images. - -= Insights and Reports = +* Upload and manage your assets with Cloudinary directly from your WordPress interface. +* Migrate all your locally hosted assets to Cloudinary. +* Move your existing posts’ images and videos to Cloudinary with a single click. -* Cloudinary offers a powerful online management console. -* Browse all your images and transformations. -* View comprehensive statistics and usage reports. -* You can even automate your content management using a RESTful API. = About Cloudinary = -Read more about the Cloudinary service: +* [Our website](http://cloudinary.com?utm_source=wp&utm_medium=wpmarketplace&utm_campaign=wpmarketplace) +* [Blog](http://cloudinary.com/blog?utm_source=wp&utm_medium=wpmarketplace&utm_campaign=wpmarketplace) +* [Features overview](http://cloudinary.com/features?utm_source=wp&utm_medium=wpmarketplace&utm_campaign=wpmarketplace) +* [DAM solution](https://cloudinary.com/solutions/digital_asset_management?utm_source=wp&utm_medium=wpmarketplace&utm_campaign=wpmarketplace) +* [Detailed documentation](http://cloudinary.com/documentation?utm_source=wp&utm_medium=wpmarketplace&utm_campaign=wpmarketplace) +* [Image transformations documentation](http://cloudinary.com/documentation/image_transformations?utm_source=wp&utm_medium=wpmarketplace&utm_campaign=wpmarketplace) +* [Video transformations documentation](https://cloudinary.com/documentation/video_manipulation_and_delivery?utm_source=wp&utm_medium=wpmarketplace&utm_campaign=wpmarketplace) +* [FAQ](http://cloudinary.com/faq?utm_source=wp&utm_medium=wpmarketplace&utm_campaign=wpmarketplace) -* [Our website](http://cloudinary.com) -* [Blog](http://cloudinary.com/blog) -* [Features overview](http://cloudinary.com/features) -* [Detailed documentation](http://cloudinary.com/documentation) -* [Image transformations documentation](http://cloudinary.com/documentation/image_transformations) -* [FAQ](http://cloudinary.com/faq) += Contributors & Developers = +“Cloudinary – Dynamic Image and Video Management” is an open source software. The following people have contributed to this plugin: +[Cloudinary](https://profiles.wordpress.org/cloudinary/) +[XWP](https://profiles.wordpress.org/xwp/) +[Automattic](https://profiles.wordpress.org/automattic/) -= Support = -* [Support site](http://support.cloudinary.com/home) -* [Knowledge Base](http://support.cloudinary.com/forums) -* Support Email: [support@cloudinary.com](support@cloudinary.com) -* [Contact page](http://cloudinary.com/contact) -* Twitter: [@cloudinary](http://twitter.com/cloudinary) -* [Facebook page](https://www.facebook.com/Cloudinary) - - -**Keywords**: image, images, photo, photos, picture, pictures, thumbnail, thumbnails, upload, batch, cdn, content delivery network, transform, manipulate, effects, scale, high availability, fast, format, sharpen, sepia, saturation, grayscale, b&w, hue, brightness, oil paint, pixelate, vignette, -jpg, jpeg, png, gif, animated gif, pdf, face, faces, crop, resize, scale, fit, fill, pad, rotate, rotation, flip, corners, borders, exif, watermark, caption, overlay, underlay, text, embed, quality, smush. == Installation == += Install from within wordpress = +* Visit the plugins page within your dashboard and select `Add New`. +* Search for `Cloudinary`. +* Select `Cloudinary – Dynamic Image and Video Management` from the list. +* Activate `Cloudinary` from your Plugins page. +* Go to `Setting up` below. -1. Search and install the plugin through the `Install Plugins` page of your WordPress dashboard. Alternatively, upload the `cloudinary` folder to the `/wp-content/plugins/` directory of your blog. -1. Activate the Cloudinary plugin through the `Plugins` page of your WordPress dashboard. -1. Configure the plugin by selecting `Cloudinary' on the left menu of your WordPress dashboard. - -== Frequently Asked Questions == - -= How can I migrate existing posts to deliver images through Cloudinary? = - -Go to WordPress standard media library (select '**Media**' from the left menu). Click '**Upload to Cloudinary**' for each media item you want to migrate to Cloudinary. - -The images will be uploaded to Cloudinary while the content of all associated posts and pages will be automatically updated to point to Cloudinary's CDN URLs. - -You can perform bulk migration of multiple posts by selecting multiple media items, selecting '**Upload to Cloudinary**' from the '**Bulk Actions**' menu and click '**Apply**'. += Install Cloudinary manually = +* Upload the `Cloudinary` folder to the /wp-content/plugins/ directory. +* Activate the `Cloudinary` plugin through the `Plugins` menu in WordPress. +* Go to `Setting up` below. -Automatic post migration is supported since version 1.1.0 of the plugin. += Setting up = +* Once the plugin is activated, go to the `Cloudinary` settings. +* You’ll be prompted to “Add your Cloudinary URL”. +* Enter your “Cloudinary environment variable URL”, the format should be cloudinary://{API_Key}:{API_Secret}@{Cloud_Name} and can be found in the "Account Details" section of the Cloudinary Console Dashboard, then click save. +* After saving, additional settings tabs will be available. -= How can I update my posts to use local files again? = +**Note** +If you have two factor authentication configured for your account, you will need to open the Cloudinary Console and login before you can use the Cloudinary plugin. +Your site is now setup to start using Cloudinary. -In case that you decide to stop using Cloudinary's WordPress plugin, you can migrate your existing posts and pages to embed local image files instead of Cloudinary's cloud-based images. -Go to WordPress standard media library (select '**Media**' from the left menu). Select multiple media items you wish to migrate then select '**Migrate away from Cloudinary**' from the '**Bulk Actions**' menu and click '**Apply**'. -The selected images are automatically downloaded from Cloudinary to your local server. Associated posts are automatically updated to use local image files of Cloudinary's CDN URLs. +== Frequently Asked Questions == += Upgrade from v1= -Automatic migrate away is supported since version 1.1.0 of the plugin. +Once installing the new version of the plugin, the plugin will automatically upgrade all of your assets to work with the new plugin. +Upgrade is seamless and requires no action from your side. -We would appreciate it if you could let us know why you decided to stop using Cloudinary for your site. += Does the plugin sync all of my media to Cloudinary? = -= Where can I find answers to additional common questions? = +The plugin will automatically sync all of your WordPress media to your Cloudinary account and start delivering assets from Cloudinary. -Check out our dynamic [knowledge base](http://support.cloudinary.com/forums/21855426-WordPress) for additional questions and articles. += Where can I find more info? = +You can read the plugin [documentation](https://cloudinary.com/documentation/wordpress_integration?utm_source=wp&utm_medium=wpmarketplace&utm_campaign=wpmarketplace) == Screenshots == - -1. **Cloud-based image gallery** -2. **Drag & drop upload to the cloud** -3. **Powerful live image manipulation** -4. **Apply effects and face detection** -5. **Insert into post and edit** -6. **Simple setup after free sign-up** - -== Upgrade Notice == - -N/A +1. Streamline Your Creative Workflow +2. Media Editor +3. Media Library +4. Easy Generation of Asset Derivatives +5. Automatically Deliver Responsive Images +6. Global Image Transformation Settings +7. Global Video Transformation Settings +8. Folder and Syncing Settings +9. Easily Configure Your Account == Changelog == += 2.0.3 (03 Apr 2020) = + * Fix migration issue -= 1.1.12 (11 Mar 2019) = - * Fix jQuery exception - -= 1.1.11 (3 Mar 2019) = - * Add CLI command for syncing media - * Fix `update_window_dimensions` to fire only when library is visible - * Fix illegal function call in PHP5.3 - -= 1.1.10 (17 May 2018) = - * Fix memory exhaustion in "Upload to Cloudinary" functionality - * Fix "Cloudinary Upload/Insert" button compatibility and style - * Fix `url` and `secure_url` inconsistency - * Add handling of WP_Error - * Add cloudinary_php v1.10.0 to WordPress plugin - -= 1.1.9 (26 Apr 2018) = -* Fix "Cloudinary Upload/Insert" functionality - -= 1.1.8 (22 Apr 2018) = -* Fix PHP errors( notices) in DEBUG mode. -* Fix "tinyMCE is not defined" JS error when TinyMCE is not loaded. -* Fix include path in cloudinary.php. - -= 1.1.7 (11 Dec 2017) = -* Support https for bulk upload. -* Fix for DEPRECATED Old style constructor. - -= 1.1.6 (6 Aug 2017) = -* Confirm WordPress 4.8 support. -* Replace old logos. -* Fix "Edit with Cloudinaty" button for WP posts image edit. - -= 1.1.5 (14 Nov 2016) = -* Fix Upload/Insert button. -* Fix setting page on before set credentials. += 2.0.2 (03 Apr 2020) = + * Rollback last fix -= 1.1.4 (4 Nov 2014) = -* Support newer versions of PHP in file upload. Report user agent to Cloudinary. -* Correctly locate path to ajax-loader. += 2.0.1 (02 Apr 2020) = + * Fix an issue with v1 migrating -= 1.1.3 (18 Sep 2014) = -* Fix display compatibility issue with WordPress 4.0. -* Support earlier versions of PHP 5.2. += 2.0.0 (31 Mar 2020) = + * Release of a new major version of the plugin -= 1.1.2 (24 Dec 2013) = -* Fix display compatibility issue with WordPress 3.8. - -= 1.1.1 (6 Nov 2013) = -* Support WordPress sites that use relative URLs for images. - -= 1.1.0 (5 Aug 2013) = -* Migrate existing posts: upload images to Cloudinary and automatically update associated posts and pages to point to Cloudinary CDN URLs. -* Migrate away from Cloudinary: bulk image downloading from Cloudinary and automatic post updating to use local image files. -* Better integration with WordPress featured images and image galleries. -* Allow adding Cloudinary's images directly to WP's post gallery for setting as featured image and using for image galleries. - -= 1.0.8 (28 Mar 2013) = -* Register images uploaded to Cloudinary from WordPress media library as media items so they can be used as featured images. - -= 1.0.7 (25 Mar 2013) = -* Fix issue of Cloudinary settings not appearing with some themes activated. -* Better error handling when verifying CLOUDINARY_URL. - -= 1.0.6 (22 Mar 2013) = -* Register images with WordPress media to allow using them as featured images. -* Allow uploading images from WP's media library that aren't recognized properly by local PHP code. -* Add class prefix to elements in the settings page to avoid possible collisions. - -= 1.0.5 (17 Mar 2013) = -* Allow administrator (and not only super admin) to manage Cloudinary settings. -* Validation of CLOUDINARY_URL in Settings page. - -= 1.0.4 (16 Mar 2013) = -* Fixes menu and settings in multisite mode. - -= 1.0.3 (15 Mar 2013) = -* Fixes non saved settings issue. - -= 1.0.2 (7 Mar 2013) = -* Minor fixes related to changing directory name. - -= 1.0.1 (27 Feb 2013) = -* Fully tested version entering the plugin directory. +== Upgrade Notice == +Enjoy a seamless upgrade to experience the completely new look and feel of our plugin. Boasting many new features including our digital asset management platform, video player offering advanced capabilities, auto-responsive images, automatic optimizations and transformations, and much more. diff --git a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/ui-definitions/tabs/settings-global-video-transformations.php b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/ui-definitions/tabs/settings-global-video-transformations.php index 7e3314634..2976aff2b 100644 --- a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/ui-definitions/tabs/settings-global-video-transformations.php +++ b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/ui-definitions/tabs/settings-global-video-transformations.php @@ -13,7 +13,7 @@ 'connect', ), 'sanitize_callback' => function ( $value ) { - if ( 'off' === $value['video_autoplay'] && 'off' === $value['video_controls'] && 'off' === $value['video_loop'] ) { + if ( 'off' === $value['video_autoplay_mode'] && 'off' === $value['video_controls'] && 'off' === $value['video_loop'] ) { return new WP_Error( 'cant_play', __( 'At least one of the video player settings must be set to "On".', 'cloudinary' ) ); } @@ -32,10 +32,10 @@ 'label' => __( 'Video player', 'cloudinary' ), 'description' => __( 'Which video player to use on all videos.', 'cloudinary' ), 'type' => 'select', - 'default' => 'cld', + 'default' => 'wp', 'choices' => array( - 'cld' => __( 'Cloudinary Player', 'cloudinary' ), 'wp' => __( 'WordPress Player', 'cloudinary' ), + 'cld' => __( 'Cloudinary Player', 'cloudinary' ), ), ), 'video_controls' => array( diff --git a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/ui-definitions/tabs/sync-media-content.php b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/ui-definitions/tabs/sync-media-content.php index 11b58d552..a2b8345d2 100644 --- a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/ui-definitions/tabs/sync-media-content.php +++ b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/ui-definitions/tabs/sync-media-content.php @@ -9,7 +9,7 @@ plugin->config['connect'] ) ) : ?>
    - +


    diff --git a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/webpack.config.js b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/webpack.config.js index 2e0f62269..93b3c8dc9 100755 --- a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/webpack.config.js +++ b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/webpack.config.js @@ -39,6 +39,7 @@ const cldCore = { ...sharedConfig, entry: { 'cloudinary': './js/src/main.js', + 'video': './css/src/video.scss', }, output: { path: path.resolve( process.cwd(), 'js' ), diff --git a/cloudinary-update-tester/cloudinary-update-tester.php b/cloudinary-update-tester/cloudinary-update-tester.php deleted file mode 100644 index 667c76bf2..000000000 --- a/cloudinary-update-tester/cloudinary-update-tester.php +++ /dev/null @@ -1,58 +0,0 @@ -no_update ) ) { - $slug = 'cloudinary-image-management-and-manipulation-in-the-cloud-cdn/cloudinary.php'; - if ( ! empty( $data->no_update[ $slug ] ) ) { - $file = plugin_dir_path( __FILE__ ) . 'cloudinary.zip'; - $data->no_update[ $slug ]->package = $file; - $data->no_update[ $slug ]->new_version = 2.0; - $data->response[ $slug ] = $data->no_update[ $slug ]; - unset( $data->no_update[ $slug ] ); - deactivate_plugins( 'cloudinary-update-tester/cloudinary-update-tester.php' ); - } - } - - return $data; -} - -add_filter( 'pre_set_site_transient_update_plugins', 'cld_test_check_update', 100 ); - -/** - * Delete the update transient on activation. - */ -function cld_test_init_update() { - delete_site_transient( 'update_plugins' ); -} - -register_activation_hook( __FILE__, 'cld_test_init_update' ); diff --git a/cloudinary-update-tester/readme.txt b/cloudinary-update-tester/readme.txt deleted file mode 100644 index da0fa5eca..000000000 --- a/cloudinary-update-tester/readme.txt +++ /dev/null @@ -1,5 +0,0 @@ -This tests the update process of the Cloudinary plugin. - -To create a new test package, simply add the plugin zip package here and name it cloudinary.zip - -Then activate this plugin in WordPress. The cloudinary plugin listing will show an available update and this plugin will disable itself.