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 65cb8434a..23c09bc93 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.3 + * Version: 2.1.1 * Author: Cloudinary Ltd., XWP * Author URI: https://cloudinary.com/ * License: GPLv2+ diff --git a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/cloudinary.css b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/cloudinary.css index 7df57b89b..ab2783e7d 100644 --- a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/cloudinary.css +++ b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/cloudinary.css @@ -1 +1 @@ -@font-face{font-family:cloudinary;src:url(../css/fonts/cloudinary.eot);src:url(../css/fonts/cloudinary.eot#iefix) format("embedded-opentype"),url(../css/fonts/cloudinary.ttf) format("truetype"),url(../css/fonts/cloudinary.woff) format("woff"),url(../css/cloudinary.svg#cloudinary) format("svg");font-weight:400;font-style:normal}.dashicons-cloudinary{speak:none;font-style:normal;font-weight:400;font-variant:normal;text-transform:none;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.dashicons-cloudinary:before{font-family:cloudinary!important;content:"\e900"}.dashicons-cloudinary.success{color:#558b2f}.dashicons-cloudinary.error{color:#dd2c00}.dashicons-cloudinary.error:before{content:"\e901"}.dashicons-cloudinary.warning:before{content:"\e902"}.dashicons-cloudinary.warning{color:#fd9d2c}.column-cld_status{width:5.5em}.column-cld_status .dashicons-cloudinary{display:inline-block}.column-cld_status .dashicons-cloudinary:before{font-size:1.8rem}.form-field .error-notice,.form-table .error-notice{display:none;color:#dd2c00}.form-field input.cld-field:invalid,.form-table input.cld-field:invalid{border-color:#dd2c00}.form-field input.cld-field:invalid+.error-notice,.form-table input.cld-field:invalid+.error-notice{display:inline-block}.cloudinary-welcome{background-image:url(../css/logo.svg);background-repeat:no-repeat;background-size:153px;background-position:top 12px right 20px}.settings-image{max-width:100%;padding-top:5px}.settings-tabs>li{display:inline-block}.settings-tabs>li a{padding:.6em}.settings-tabs>li a.active{background-color:#fff}.settings-tab-section{padding:20px 0 0;max-width:1030px;position:relative}.settings-tab-section.cloudinary-welcome .settings-tab-section-fields-dashboard{display:flex;align-items:flex-start;align-content:flex-start;margin-top:40px}.settings-tab-section.cloudinary-welcome .settings-tab-section-fields-dashboard-description{width:55%;margin:0 auto 0 0}.settings-tab-section.cloudinary-welcome .settings-tab-section-fields-dashboard-content{width:35%;margin:0 auto}.settings-tab-section.cloudinary-welcome .settings-tab-section-fields-dashboard-content .dashicons{color:#9ea3a8}.settings-tab-section.cloudinary-welcome .settings-tab-section-card{margin-top:0}.settings-tab-section-fields .field-heading th{display:block;width:auto;color:#23282d;font-size:1.1em;margin:1em 0}.settings-tab-section-fields .field-heading td{display:none;visibility:hidden}.settings-tab-section-fields .regular-textarea{width:100%;height:60px}.settings-tab-section-fields .dashicons{text-decoration:none;vertical-align:middle}.settings-tab-section-fields a .dashicons{color:#5f5f5f}.settings-tab-section-fields-dashboard-error{font-size:1.2em;color:#5f5f5f}.settings-tab-section-fields-dashboard-error .dashicons{color:#ac0000}.settings-tab-section-fields-dashboard-error .button{font-size:1.1em;height:40px;line-height:40px;padding-right:40px;padding-left:40px}.settings-tab-section-fields-dashboard-success{font-size:1.2em;color:#23282d}.settings-tab-section-fields-dashboard-success.expanded{padding-top:40px}.settings-tab-section-fields-dashboard-success .dashicons{color:#4fb651}.settings-tab-section-fields-dashboard-success .button{font-size:1.1em;height:40px;line-height:40px;padding-right:40px;padding-left:40px}.settings-tab-section-fields-dashboard-success .description{color:#5f5f5f;font-weight:400;margin-top:12px}.settings-tab-section-card{box-sizing:border-box;border:1px solid #e5e5e5;background-color:#fff;box-shadow:0 1px 1px 0 rgba(0,0,0,.07);padding:20px 23px;margin-top:12px}.settings-tab-section-card .dashicons{font-size:1.4em}.settings-tab-section-card h2{font-size:1.8em;font-weight:400;margin-top:0}.settings-tab-section-card.pull-right{width:450px;padding:12px;float:right;position:relative;z-index:10}.settings-tab-section-card.pull-right img.settings-image{box-shadow:0 2px 4px 0 rgba(0,0,0,.5);border:1px solid #979797;margin-top:12px}.settings-tab-section-card.pull-right h3,.settings-tab-section-card.pull-right h4{margin-top:0}.settings-tab-section .field-row-cloudinary_url,.settings-tab-section .field-row-signup{display:block}.settings-tab-section .field-row-cloudinary_url td,.settings-tab-section .field-row-cloudinary_url th,.settings-tab-section .field-row-signup td,.settings-tab-section .field-row-signup th{display:block;width:auto;padding:10px 0 0}.settings-tab-section .field-row-cloudinary_url td .sign-up,.settings-tab-section .field-row-cloudinary_url th .sign-up,.settings-tab-section .field-row-signup td .sign-up,.settings-tab-section .field-row-signup th .sign-up{vertical-align:baseline}.settings-tab-section.connect .form-table{display:inline-block;width:auto;max-width:580px}.settings-valid{color:#558b2f;font-size:30px}.settings-valid-field{border-color:#558b2f!important}.settings-invalid-field{border-color:#dd2c00!important}.sync .spinner{display:inline-block;visibility:visible;float:none;margin:0 5px 0 0}.sync-media,.sync-media-progress{display:none}.sync-media-progress-outer{height:20px;margin:20px 0 10px;width:500px;background-color:#e5e5e5;position:relative}.sync-media-progress-outer .progress-bar{width:0;height:20px;background-color:#558b2f;transition:width .25s}.sync-media-progress-notice{color:#dd2c00}.sync-media-resource{width:100px;display:inline-block}.sync-media-error{color:#dd2c00}.sync-count{font-weight:700}.sync-details{margin-top:10px}.sync .button.start-sync,.sync .button.stop-sync{display:none;padding:0 16px}.sync .button.start-sync .dashicons,.sync .button.stop-sync .dashicons{line-height:2.2em}.sync .progress-text{padding:12px 4px 12px 12px;display:inline-block;font-weight:700}.sync .completed{max-width:300px;display:none}.cloudinary-widget{height:100%}.cloudinary-widget-wrapper{height:100%;overflow:hidden;background-image:url("data:image/svg+xml;base64,PHN2ZyBjbGFzcz0ic3Bpbm5lciIgdmlld0JveD0iLTQgLTQgMTUxIDEwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48c3R5bGU+QGtleWZyYW1lcyBjb2xvcnN7MCUsdG97c3Ryb2tlOiMwMDc4ZmZ9NTAle3N0cm9rZTojMGUyZjVhfX1Aa2V5ZnJhbWVzIGRhc2h7MCUsdG97c3Ryb2tlLWRhc2hvZmZzZXQ6NTYwfTUwJXtzdHJva2UtZGFzaG9mZnNldDowfX1ALXdlYmtpdC1rZXlmcmFtZXMgY29sb3JzezAlLHRve3N0cm9rZTojMDA3OGZmfTUwJXtzdHJva2U6IzBlMmY1YX19QC13ZWJraXQta2V5ZnJhbWVzIGRhc2h7MCUsdG97c3Ryb2tlLWRhc2hvZmZzZXQ6NTYwfTUwJXtzdHJva2UtZGFzaG9mZnNldDowfX08L3N0eWxlPjxwYXRoIGQ9Ik0xMjEuNjYzIDkwLjYzOGMtMS43OTYgMC05OS4zMy0uNDk4LTEwMS40NzQtMS40NzhDOC42ODUgODMuODc3IDEuMjUgNzIuMTk2IDEuMjUgNTkuMzk2YzAtMTYuNjU2IDEyLjc5Ny0zMC42MSAyOS4wNTItMzIuMzIzIDcuNDktMTUuNzA2IDIzLjE4Ni0yNS43MDcgNDAuNzE0LTI1LjcwNyAyMC45OCAwIDM5LjIxNSAxNC43NTIgNDMuOTQ1IDM0LjkwNyAxNS4wOS4yNDUgMjcuMjkgMTIuNjMgMjcuMjkgMjcuODIyIDAgMTEuOTY4LTcuNzM4IDIyLjU1LTE5LjI1NiAyNi4zMyIgc3Ryb2tlLXdpZHRoPSI5IiBzdHJva2UtbGluZWNhcD0icm91bmQiIGZpbGw9Im5vbmUiIGZpbGwtcnVsZT0iZXZlbm9kZCIgc3R5bGU9InRyYW5zZm9ybS1vcmlnaW46Y2VudGVyOy13ZWJraXQtYW5pbWF0aW9uOmRhc2ggMnMgZWFzZS1pbi1vdXQgaW5maW5pdGUsY29sb3JzIDhzIGVhc2UtaW4tb3V0IGluZmluaXRlO2FuaW1hdGlvbjpkYXNoIDJzIGVhc2UtaW4tb3V0IGluZmluaXRlLGNvbG9ycyA4cyBlYXNlLWluLW91dCBpbmZpbml0ZSIgc3Ryb2tlLWRhc2hhcnJheT0iMjgwIi8+PC9zdmc+");background-repeat:no-repeat;background-position:50%;background-size:150px}.attachment-actions .button.edit-attachment,.attachment-info .edit-attachment{display:none}.global-transformations-preview{position:relative;max-width:600px}.global-transformations-spinner{display:none}.global-transformations-button.button-primary{display:none;position:absolute;z-index:100}.global-transformations-url{margin-bottom:5px;margin-top:5px}.global-transformations-url-transformation{max-width:100px;overflow:hidden;text-overflow:ellipsis;color:#51a3ff}.global-transformations-url-file{color:#f2d864}.global-transformations-url-link{display:block;padding:16px;background-color:#262c35;text-decoration:none;color:#fff;border-radius:6px;overflow:hidden;text-overflow:ellipsis}.global-transformations-url-link:hover{color:#888;text-decoration:underline}.cld-tax-order-list-item{border:1px solid #efefef;padding:4px;margin:0 0 -1px;background-color:#fff}.cld-tax-order-list-item.no-items{color:#888;text-align:center;display:none}.cld-tax-order-list-item.no-items:last-child{display:block}.cld-tax-order-list-item.ui-sortable-helper{box-shadow:0 2px 5px rgba(0,0,0,.2)}.cld-tax-order-list-item-placeholder{background-color:#efefef;height:45px;margin:0}.cld-tax-order-list-item-handle{cursor:grab;margin-right:4px;color:#999}.cld-tax-order-list-type{width:45%;display:inline-block;margin-right:8px}.cld-tax-order-list-type input{margin-right:4px!important}.cloudinary-media-library{position:relative;margin-left:-20px}@media screen and (max-width:782px){.cloudinary-media-library{margin-left:-10px}} \ No newline at end of file +@font-face{font-family:cloudinary;src:url(../css/fonts/cloudinary.eot);src:url(../css/fonts/cloudinary.eot#iefix) format("embedded-opentype"),url(../css/fonts/cloudinary.ttf) format("truetype"),url(../css/fonts/cloudinary.woff) format("woff"),url(../css/cloudinary.svg#cloudinary) format("svg");font-weight:400;font-style:normal}.dashicons-cloudinary{speak:none;font-style:normal;font-weight:400;font-variant:normal;text-transform:none;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.dashicons-cloudinary:before{font-family:cloudinary!important;content:"\e900"}.dashicons-cloudinary.success{color:#558b2f}.dashicons-cloudinary.error{color:#dd2c00}.dashicons-cloudinary.error:before{content:"\e901"}.dashicons-cloudinary.warning:before{content:"\e902"}.dashicons-cloudinary.warning{color:#fd9d2c}.column-cld_status{width:5.5em}.column-cld_status .dashicons-cloudinary{display:inline-block}.column-cld_status .dashicons-cloudinary:before{font-size:1.8rem}.form-field .error-notice,.form-table .error-notice{display:none;color:#dd2c00}.form-field input.cld-field:invalid,.form-table input.cld-field:invalid{border-color:#dd2c00}.form-field input.cld-field:invalid+.error-notice,.form-table input.cld-field:invalid+.error-notice{display:inline-block}.cloudinary-welcome{background-image:url(../css/logo.svg);background-repeat:no-repeat;background-size:153px;background-position:top 12px right 20px}.cloudinary-stats{display:inline-block;margin-left:25px}.cloudinary-stat{cursor:help}.cloudinary-percent{font-size:.8em;vertical-align:top;color:#0078ff}.settings-image{max-width:100%;padding-top:5px}.settings-tabs>li{display:inline-block}.settings-tabs>li a{padding:.6em}.settings-tabs>li a.active{background-color:#fff}.settings-tab-section{padding:20px 0 0;max-width:1030px;position:relative}.settings-tab-section.cloudinary-welcome .settings-tab-section-fields-dashboard{display:flex;align-items:flex-start;align-content:flex-start;margin-top:40px}.settings-tab-section.cloudinary-welcome .settings-tab-section-fields-dashboard-description{width:55%;margin:0 auto 0 0}.settings-tab-section.cloudinary-welcome .settings-tab-section-fields-dashboard-content{width:35%;margin:0 auto}.settings-tab-section.cloudinary-welcome .settings-tab-section-fields-dashboard-content .dashicons{color:#9ea3a8}.settings-tab-section.cloudinary-welcome .settings-tab-section-card{margin-top:0}.settings-tab-section-fields .field-heading th{display:block;width:auto;color:#23282d;font-size:1.1em;margin:1em 0}.settings-tab-section-fields .field-heading td{display:none;visibility:hidden}.settings-tab-section-fields .regular-textarea{width:100%;height:60px}.settings-tab-section-fields .dashicons{text-decoration:none;vertical-align:middle}.settings-tab-section-fields a .dashicons{color:#5f5f5f}.settings-tab-section-fields-dashboard-error{font-size:1.2em;color:#5f5f5f}.settings-tab-section-fields-dashboard-error .dashicons{color:#ac0000}.settings-tab-section-fields-dashboard-error .button{font-size:1.1em;height:40px;line-height:40px;padding-right:40px;padding-left:40px}.settings-tab-section-fields-dashboard-success{font-size:1.2em;color:#23282d}.settings-tab-section-fields-dashboard-success.expanded{padding-top:40px}.settings-tab-section-fields-dashboard-success .dashicons{color:#4fb651}.settings-tab-section-fields-dashboard-success .button{font-size:1.1em;height:40px;line-height:40px;padding-right:40px;padding-left:40px}.settings-tab-section-fields-dashboard-success .description{color:#5f5f5f;font-weight:400;margin-top:12px}.settings-tab-section-card{box-sizing:border-box;border:1px solid #e5e5e5;background-color:#fff;box-shadow:0 1px 1px 0 rgba(0,0,0,.07);padding:20px 23px;margin-top:12px}.settings-tab-section-card .dashicons{font-size:1.4em}.settings-tab-section-card h2{font-size:1.8em;font-weight:400;margin-top:0}.settings-tab-section-card.pull-right{width:450px;padding:12px;float:right;position:relative;z-index:10}.settings-tab-section-card.pull-right img.settings-image{box-shadow:0 2px 4px 0 rgba(0,0,0,.5);border:1px solid #979797;margin-top:12px}.settings-tab-section-card.pull-right h3,.settings-tab-section-card.pull-right h4{margin-top:0}.settings-tab-section .field-row-cloudinary_url,.settings-tab-section .field-row-signup{display:block}.settings-tab-section .field-row-cloudinary_url td,.settings-tab-section .field-row-cloudinary_url th,.settings-tab-section .field-row-signup td,.settings-tab-section .field-row-signup th{display:block;width:auto;padding:10px 0 0}.settings-tab-section .field-row-cloudinary_url td .sign-up,.settings-tab-section .field-row-cloudinary_url th .sign-up,.settings-tab-section .field-row-signup td .sign-up,.settings-tab-section .field-row-signup th .sign-up{vertical-align:baseline}.settings-tab-section.connect .form-table{display:inline-block;width:auto;max-width:580px}.settings-valid{color:#558b2f;font-size:30px}.settings-valid-field{border-color:#558b2f!important}.settings-invalid-field{border-color:#dd2c00!important}.sync .spinner{display:inline-block;visibility:visible;float:none;margin:0 5px 0 0}.sync-media,.sync-media-progress{display:none}.sync-media-progress-outer{height:20px;margin:20px 0 10px;width:500px;background-color:#e5e5e5;position:relative}.sync-media-progress-outer .progress-bar{width:0;height:20px;background-color:#558b2f;transition:width .25s}.sync-media-progress-notice{color:#dd2c00}.sync-media-resource{width:100px;display:inline-block}.sync-media-error{color:#dd2c00}.sync-count{font-weight:700}.sync-details{margin-top:10px}.sync .button.start-sync,.sync .button.stop-sync{display:none;padding:0 16px}.sync .button.start-sync .dashicons,.sync .button.stop-sync .dashicons{line-height:2.2em}.sync .progress-text{padding:12px 4px 12px 12px;display:inline-block;font-weight:700}.sync .completed{max-width:300px;display:none}.sync-status-disabled{color:#dd2c00}.sync-status-enabled{color:#558b2f}.sync-status-button.button{vertical-align:baseline}.cloudinary-widget{height:100%}.cloudinary-widget-wrapper{height:100%;overflow:hidden;background-image:url("data:image/svg+xml;base64,PHN2ZyBjbGFzcz0ic3Bpbm5lciIgdmlld0JveD0iLTQgLTQgMTUxIDEwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48c3R5bGU+QGtleWZyYW1lcyBjb2xvcnN7MCUsdG97c3Ryb2tlOiMwMDc4ZmZ9NTAle3N0cm9rZTojMGUyZjVhfX1Aa2V5ZnJhbWVzIGRhc2h7MCUsdG97c3Ryb2tlLWRhc2hvZmZzZXQ6NTYwfTUwJXtzdHJva2UtZGFzaG9mZnNldDowfX1ALXdlYmtpdC1rZXlmcmFtZXMgY29sb3JzezAlLHRve3N0cm9rZTojMDA3OGZmfTUwJXtzdHJva2U6IzBlMmY1YX19QC13ZWJraXQta2V5ZnJhbWVzIGRhc2h7MCUsdG97c3Ryb2tlLWRhc2hvZmZzZXQ6NTYwfTUwJXtzdHJva2UtZGFzaG9mZnNldDowfX08L3N0eWxlPjxwYXRoIGQ9Ik0xMjEuNjYzIDkwLjYzOGMtMS43OTYgMC05OS4zMy0uNDk4LTEwMS40NzQtMS40NzhDOC42ODUgODMuODc3IDEuMjUgNzIuMTk2IDEuMjUgNTkuMzk2YzAtMTYuNjU2IDEyLjc5Ny0zMC42MSAyOS4wNTItMzIuMzIzIDcuNDktMTUuNzA2IDIzLjE4Ni0yNS43MDcgNDAuNzE0LTI1LjcwNyAyMC45OCAwIDM5LjIxNSAxNC43NTIgNDMuOTQ1IDM0LjkwNyAxNS4wOS4yNDUgMjcuMjkgMTIuNjMgMjcuMjkgMjcuODIyIDAgMTEuOTY4LTcuNzM4IDIyLjU1LTE5LjI1NiAyNi4zMyIgc3Ryb2tlLXdpZHRoPSI5IiBzdHJva2UtbGluZWNhcD0icm91bmQiIGZpbGw9Im5vbmUiIGZpbGwtcnVsZT0iZXZlbm9kZCIgc3R5bGU9InRyYW5zZm9ybS1vcmlnaW46Y2VudGVyOy13ZWJraXQtYW5pbWF0aW9uOmRhc2ggMnMgZWFzZS1pbi1vdXQgaW5maW5pdGUsY29sb3JzIDhzIGVhc2UtaW4tb3V0IGluZmluaXRlO2FuaW1hdGlvbjpkYXNoIDJzIGVhc2UtaW4tb3V0IGluZmluaXRlLGNvbG9ycyA4cyBlYXNlLWluLW91dCBpbmZpbml0ZSIgc3Ryb2tlLWRhc2hhcnJheT0iMjgwIi8+PC9zdmc+");background-repeat:no-repeat;background-position:50%;background-size:150px}.attachment-actions .button.edit-attachment,.attachment-info .edit-attachment{display:none}.global-transformations-preview{position:relative;max-width:600px}.global-transformations-spinner{display:none}.global-transformations-button.button-primary{display:none;position:absolute;z-index:100}.global-transformations-url{margin-bottom:5px;margin-top:5px}.global-transformations-url-transformation{max-width:100px;overflow:hidden;text-overflow:ellipsis;color:#51a3ff}.global-transformations-url-file{color:#f2d864}.global-transformations-url-link{display:block;padding:16px;background-color:#262c35;text-decoration:none;color:#fff;border-radius:6px;overflow:hidden;text-overflow:ellipsis}.global-transformations-url-link:hover{color:#888;text-decoration:underline}.cld-tax-order-list-item{border:1px solid #efefef;padding:4px;margin:0 0 -1px;background-color:#fff}.cld-tax-order-list-item.no-items{color:#888;text-align:center;display:none}.cld-tax-order-list-item.no-items:last-child{display:block}.cld-tax-order-list-item.ui-sortable-helper{box-shadow:0 2px 5px rgba(0,0,0,.2)}.cld-tax-order-list-item-placeholder{background-color:#efefef;height:45px;margin:0}.cld-tax-order-list-item-handle{cursor:grab;margin-right:4px;color:#999}.cld-tax-order-list-type{width:45%;display:inline-block;margin-right:8px}.cld-tax-order-list-type input{margin-right:4px!important}.cloudinary-media-library{position:relative;margin-left:-20px}@media screen and (max-width:782px){.cloudinary-media-library{margin-left:-10px}} \ No newline at end of file diff --git a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/loading.svg b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/loading.svg new file mode 100644 index 000000000..0cf4e763f --- /dev/null +++ b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/loading.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + diff --git a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/src/components/_brand.scss b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/src/components/_brand.scss index 3e80e6340..34f384d33 100755 --- a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/src/components/_brand.scss +++ b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/src/components/_brand.scss @@ -1,72 +1,72 @@ @font-face { - font-family: 'cloudinary'; - src: url('fonts/cloudinary.eot?fj77m5'); - src: url('fonts/cloudinary.eot?fj77m5#iefix') format('embedded-opentype'), + font-family : 'cloudinary'; + src : url('fonts/cloudinary.eot?fj77m5'); + src : url('fonts/cloudinary.eot?fj77m5#iefix') format('embedded-opentype'), url('fonts/cloudinary.ttf?fj77m5') format('truetype'), url('fonts/cloudinary.woff?fj77m5') format('woff'), url('fonts/cloudinary.svg?fj77m5#cloudinary') format('svg'); - font-weight: normal; - font-style: normal; + font-weight : normal; + font-style : normal; } .dashicons { &-cloudinary { /* use !important to prevent issues with browser extensions that change fonts */ - speak: none; - font-style: normal; - font-weight: normal; - font-variant: normal; - text-transform: none; - line-height: 1; + speak : none; + font-style : normal; + font-weight : normal; + font-variant : normal; + text-transform : none; + line-height : 1; /* Better Font Rendering =========== */ - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; + -webkit-font-smoothing : antialiased; + -moz-osx-font-smoothing : grayscale; &:before { - font-family: 'cloudinary' !important; - content: '\e900'; + font-family : 'cloudinary' !important; + content : '\e900'; } &.success { - color: $color-green; + color : $color-green; } &.error { - color: $color-red; + color : $color-red; &:before { - content: '\e901'; + content : '\e901'; } } &.warning { - color: $color-orange; + color : $color-orange; &:before { - content: '\e902'; + content : '\e902'; } } &.warning { - color: $color-orange; + color : $color-orange; } &.warning { - color: $color-orange; + color : $color-orange; } } } .column-cld_status { - width: 5.5em; + width : 5.5em; .dashicons { &-cloudinary { - display: inline-block; + display : inline-block; &:before { - font-size: 1.8rem; + font-size : 1.8rem; } } } @@ -74,22 +74,36 @@ .form-field, .form-table { .error-notice { - display: none; - color: $color-red; + display : none; + color : $color-red; } input.cld-field:invalid { - border-color: $color-red; + border-color : $color-red; + .error-notice { - display: inline-block; + display : inline-block; } } } -.cloudinary-welcome { - background-image: url("logo.svg"); - background-repeat: no-repeat; - background-size: 153px; - background-position: top 12px right 20px; +.cloudinary { + &-welcome { + background-image : url("logo.svg"); + background-repeat : no-repeat; + background-size : 153px; + background-position : top 12px right 20px; + } + &-stats{ + display: inline-block; + margin-left: 25px; + } + &-stat{ + cursor: help; + } + &-percent { + font-size : 0.8em; + vertical-align : top; + color : $color-blue; + } } diff --git a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/src/components/_sync.scss b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/src/components/_sync.scss index d5536a061..ade7882b1 100644 --- a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/src/components/_sync.scss +++ b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/css/src/components/_sync.scss @@ -70,5 +70,19 @@ max-width : 300px; display : none; } + + &-status { + &-disabled { + color : $color-red; + } + + &-enabled { + color : $color-green; + } + + &-button.button { + vertical-align : baseline; + } + } } 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..9450213d7 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=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_URL=)?(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/js/src/components/settings-page.js b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/js/src/components/settings-page.js index 3000d58ec..6c638d976 100644 --- a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/js/src/components/settings-page.js +++ b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/js/src/components/settings-page.js @@ -50,7 +50,7 @@ let field = $(this), value = field.val(); - let reg = new RegExp(/^(cloudinary:\/\/){1}(\d)*[:]{1}[^:@]*[@]{1}[^@]*$/g ); + let reg = new RegExp(/^(?:CLOUDINARY_URL=)?(cloudinary:\/\/){1}(\d)*[:]{1}[^:@]*[@]{1}[^@]*$/g ); if( reg.test( value ) ){ field.addClass( 'settings-valid-field' ); field.removeClass( 'settings-invalid-field' ); diff --git a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/js/src/components/sync.js b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/js/src/components/sync.js index 941580985..e08df5416 100644 --- a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/js/src/components/sync.js +++ b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/js/src/components/sync.js @@ -4,11 +4,10 @@ const Sync = { progress: document.getElementById( 'progress-wrapper' ), submitButton: document.getElementById( 'submit' ), stopButton: document.getElementById( 'stop-sync' ), - progressCount: document.getElementById( 'sync-progress' ), - barSyncCount: document.getElementById( 'sync-total' ), completed: document.getElementById( 'completed-notice' ), show: 'inline-block', hide: 'none', + isRunning: false, getStatus: function getStatus() { var self = this, resourceType = [], @@ -22,8 +21,9 @@ const Sync = { request.setRequestHeader( 'X-WP-Nonce', cloudinaryApi.nonce ); }, } ).done( function( data ) { - if ( data.done < data.total ) { - setTimeout( Sync.getStatus, 2000 ); + Sync.isRunning = data.is_running; + if ( Sync.isRunning ) { + setTimeout( Sync.getStatus, 10000 ); } Sync._updateUI( data ); } ); @@ -32,6 +32,8 @@ const Sync = { var self = this, url = cloudinaryApi.restUrl + 'cloudinary/v1/sync'; + Sync.isRunning = false; + wp.ajax.send( { url: url, data: { @@ -48,11 +50,16 @@ const Sync = { var self = this, url = cloudinaryApi.restUrl + 'cloudinary/v1/sync'; + Sync.isRunning = true; + Sync.progress.style.display = Sync.show; + wp.ajax.send( { url: url, beforeSend: function( request ) { request.setRequestHeader( 'X-WP-Nonce', cloudinaryApi.nonce ); }, + } ).done( function ( data ) { + setTimeout( Sync.getStatus, 10000 ); } ); }, _updateUI: function _updateUI( data ) { @@ -75,13 +82,14 @@ const Sync = { this.stopButton.style.display = this.hide; } - if ( data.percent < 100 ) { - this.barSyncCount.innerText = data.total; - this.progressCount.innerText = data.done; + if ( data.percent === 100 ) { + this.completed.style.display = this.show; + } + + if ( this.isRunning ) { this.progress.style.display = this.show; } else { - this.completed.style.display = this.show; this.progress.style.display = this.hide; } }, 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..90b15c803 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. @@ -62,6 +61,26 @@ class Connect implements Config, Setup, Notice { */ public $handle; + /** + * Holder of general notices. + * + * @var array + */ + protected $notices = array(); + + /** + * Holds the meta keys for connect meta to maintain consistency. + */ + const META_KEYS = array( + 'usage' => '_cloudinary_usage', + 'last_usage' => '_cloudinary_last_usage', + 'signature' => 'cloudinary_connection_signature', + 'version' => 'cloudinary_version', + 'url' => 'cloudinary_url', + 'connect' => 'cloudinary_connect', + 'cache' => 'cloudinary_settings_cache', + ); + /** * Initiate the plugin resources. * @@ -118,30 +137,47 @@ public function media_library_script() { */ public function verify_connection( $data ) { if ( empty( $data['cloudinary_url'] ) ) { - delete_option( 'cloudinary_connection_signature' ); - add_settings_error( 'cloudinary_connect', 'connection_error', __( 'Connection to Cloudinary has been removed.', 'cloudinary' ), 'notice-warning' ); + delete_option( self::META_KEYS['signature'] ); + + add_settings_error( + 'cloudinary_connect', + 'connection_error', + __( 'Connection to Cloudinary has been removed.', 'cloudinary' ), + 'notice-warning' + ); return $data; } - $current = $this->plugin->config['settings']['connect']; + + $data['cloudinary_url'] = str_replace( 'CLOUDINARY_URL=', '', $data['cloudinary_url'] ); + $current = $this->plugin->config['settings']['connect']; + if ( $current['cloudinary_url'] === $data['cloudinary_url'] ) { return $data; } - if ( ! preg_match( '~^cloudinary://~', $data['cloudinary_url'] ) ) { - add_settings_error( 'cloudinary_connect', 'format_mismatch', __( 'The Environment variable URL must be in this format: cloudinary://API_Key:API_Secret@Cloud_Name', 'cloudinary' ), 'error' ); + // Pattern match to ensure validity of the provided url + if ( ! preg_match( '~^(?:CLOUDINARY_URL=)?cloudinary://[0-9]+:[A-Za-z_0-9]+@[A-Za-z]+~', $data['cloudinary_url'] ) ) { + add_settings_error( + 'cloudinary_connect', + 'format_mismatch', + __( 'The environment variable URL must be in this format: cloudinary://API_KEY:API_SECRET@CLOUD_NAME', 'cloudinary' ), + 'error' + ); return $current; } $result = $this->test_connection( $data['cloudinary_url'] ); + if ( ! empty( $result['message'] ) ) { add_settings_error( 'cloudinary_connect', $result['type'], $result['message'], 'error' ); return $current; } + add_settings_error( 'cloudinary_connect', 'connection_success', __( 'Successfully connected to Cloudinary.', 'cloudinary' ), 'updated' ); - update_option( 'cloudinary_connection_signature', md5( $data['cloudinary_url'] ) ); + update_option( self::META_KEYS['signature'], md5( $data['cloudinary_url'] ) ); return $data; } @@ -170,9 +206,9 @@ function ( $a ) { if ( 4 > count( $valid ) ) { $result['type'] = 'invalid_url'; $result['message'] = sprintf( - // translators: Placeholder refers to the expected URL format. + // translators: Placeholder refers to the expected URL format. __( 'Incorrect Format. Expecting: %s', 'cloudinary' ), - 'cloudinary://API_Key:API_Secret@Cloud_Name' + 'cloudinary://API_KEY:API_SECRET@CLOUD_NAME' ); return $result; @@ -198,11 +234,14 @@ function ( $a ) { } $this->config_from_url( $url ); - $test = new Connect\Api( $this, $this->plugin->version ); - $test = $test->ping(); - if ( is_wp_error( $test ) ) { + $test = new Connect\Api( $this, $this->plugin->version ); + $test_result = $test->ping(); + if ( is_wp_error( $test_result ) ) { $result['type'] = 'connection_error'; - $result['message'] = ucwords( str_replace( '_', ' ', $test->get_error_message() ) ); + $result['message'] = ucwords( str_replace( '_', ' ', $test_result->get_error_message() ) ); + } else { + $this->api = $test; + $this->usage_stats( true ); } return $result; @@ -274,23 +313,62 @@ public function setup() { // Get the cloudinary url from plugin config. $config = $this->plugin->config['settings']['connect']; if ( ! empty( $config['cloudinary_url'] ) ) { - $this->config_from_url( $config['cloudinary_url'] ); - $this->api = new Connect\Api( $this, $this->plugin->version ); - $stats = get_transient( '_cloudinary_usage' ); - if ( empty( $stats ) ) { - // Get users plan. - $stats = $this->plugin->components['connect']->api->usage(); - if ( ! is_wp_error( $stats ) && ! empty( $stats['media_limits'] ) ) { - $stats['max_image_size'] = $stats['media_limits']['image_max_size_bytes']; - $stats['max_video_size'] = $stats['media_limits']['video_max_size_bytes']; - set_transient( '_cloudinary_usage', $stats, HOUR_IN_SECONDS ); - } + $this->usage_stats(); + } + } + + /** + * Set the usage stats from the Cloudinary API. + * + * @param bool $refresh Flag to force a refresh. + */ + public function usage_stats( $refresh = false ) { + $stats = get_transient( self::META_KEYS['usage'] ); + if ( empty( $stats ) || true === $refresh ) { + // Get users plan. + $stats = $this->api->usage(); + if ( ! is_wp_error( $stats ) && ! empty( $stats['media_limits'] ) ) { + $stats['max_image_size'] = $stats['media_limits']['image_max_size_bytes']; + $stats['max_video_size'] = $stats['media_limits']['video_max_size_bytes']; + set_transient( self::META_KEYS['usage'], $stats, HOUR_IN_SECONDS ); + update_option( self::META_KEYS['last_usage'], $stats );// Save the last successful call to prevent crashing. + } else { + // Handle error by logging and fetching the last success. + // @todo : log issue. + $stats = get_option( self::META_KEYS['last_usage'] ); } - $this->usage = $stats; + } + $this->usage = $stats; + } + /** + * Get a usage stat for display. + * + * @param string $type The type of stat to get. + * @param string|null $stat The stat to get. + * + * @return bool|string + */ + public function get_usage_stat( $type, $stat = null ) { + $value = false; + if ( isset( $this->usage[ $type ] ) ) { + if ( is_string( $this->usage[ $type ] ) ) { + $value = $this->usage[ $type ]; + } elseif ( is_array( $this->usage[ $type ] ) && isset( $this->usage[ $type ][ $stat ] ) ) { + $value = $this->usage[ $type ][ $stat ]; + } elseif ( is_array( $this->usage[ $type ] ) ) { + + if ( 'limit' === $stat && isset( $this->usage[ $type ]['usage'] ) ) { + $value = $this->usage[ $type ]['usage']; + } elseif ( 'used_percent' === $stat && isset( $this->usage[ $type ]['credits_usage'] ) ) { + $value = $this->usage[ $type ]['credits_usage']; + } + } } + + return $value; } /** @@ -301,42 +379,115 @@ public function setup() { * @return array The array of the config options stored. */ 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, '>' ) ) { + $signature = get_option( self::META_KEYS['signature'], null ); + $version = get_option( self::META_KEYS['version'] ); + if ( empty( $signature ) || version_compare( $this->plugin->version, $version, '>' ) ) { + // Check if there's a previous version, or missing signature. + $cld_url = get_option( self::META_KEYS['url'], null ); + if ( null === $cld_url ) { + // Post V1. + $data = get_option( self::META_KEYS['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. + // Set auto sync off. + $sync = get_option( 'cloudinary_sync_media' ); + if ( empty( $sync ) ) { + $sync = array( + 'auto_sync' => '', + 'cloudinary_folder' => '', + ); } + $sync['auto_sync'] = 'off'; + update_option( 'cloudinary_sync_media', $sync ); + delete_option( 'cloudinary_settings_cache' ); // remove the cache. + } + + $data['cloudinary_url'] = str_replace( 'CLOUDINARY_URL=', '', $data['cloudinary_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( self::META_KEYS['connect'], $data ); + update_option( self::META_KEYS['signature'], $signature ); + update_option( self::META_KEYS['version'], $this->plugin->version ); + delete_option( self::META_KEYS['cache'] ); // remove the cache. + $this->plugin->config['settings']['connect'] = $data; // Set the connection url for this round. } } return $signature; } + /** + * Set usage notices if limits are towards higher end. + */ + public function usage_notices() { + if ( ! empty( $this->usage ) ) { + $usage_type = 'used_percent'; + if ( isset( $this->usage['credits'] ) ) { + $usage_type = 'credits_usage'; + } + foreach ( $this->usage as $stat => $values ) { + + if ( ! is_array( $values ) || ! isset( $values[ $usage_type ] ) || 0 > $values[ $usage_type ] ) { + continue; + } + + $link = null; + $link_text = null; + if ( 90 <= $values[ $usage_type ] ) { + // 90% used - show error. + $level = 'error'; + $link = 'https://cloudinary.com/console/lui/upgrade_options'; + $link_text = __( 'upgrade your account', 'cloudinary' ); + } elseif ( 80 <= $values[ $usage_type ] ) { + $level = 'warning'; + $link_text = __( 'upgrade your account', 'cloudinary' ); + } elseif ( 70 <= $values[ $usage_type ] ) { + $level = 'neutral'; + $link_text = __( 'upgrade your account', 'cloudinary' ); + } else { + continue; + } + // translators: Placeholders are URLS and percentage values. + $message = sprintf( + __( + ' You are %2$s of the way through your monthly quota for %1$s on your Cloudinary account. If you exceed your quota, the Cloudinary plugin will be deactivated until your next billing cycle and your media assets will be served from your WordPress Media Library. You may wish to %4$s and increase your quota to ensure you maintain full functionality.', + 'cloudinary' + ), + ucwords( $stat ), + $values[ $usage_type ] . '%', + $link, + $link_text + ); + $this->notices[] = array( + 'message' => $message, + 'type' => $level, + 'dismissible' => false, + ); + } + } + } + /** * Get admin notices. */ public function get_notices() { - $screen = get_current_screen(); - $notices = array(); + $this->usage_notices(); + $screen = get_current_screen(); if ( empty( $this->plugin->config['connect'] ) ) { if ( is_object( $screen ) && in_array( $screen->id, $this->plugin->components['settings']->handles, true ) ) { - $link = '' . __( 'Connect', 'cloudinary' ) . ' '; - $notices[] = array( + $link = '' . __( 'Connect', 'cloudinary' ) . ' '; + $this->notices[] = array( 'message' => $link . __( 'your Cloudinary account with WordPress to get started.', 'cloudinary' ), 'type' => 'error', 'dismissible' => true, @@ -344,7 +495,7 @@ public function get_notices() { } } - return $notices; + return $this->notices; } } 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 cd966dc35..56b38edf2 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 @@ -463,7 +463,7 @@ public function get_transformations_from_string( $str, $type = 'image' ) { * @return string Cloudinary URL. */ public function attachment_url( $url, $attachment_id ) { - if ( ! doing_action( 'wp_insert_post_data' ) && wp_attachment_is( 'video', $attachment_id ) ) { + if ( ! doing_action( 'wp_insert_post_data' ) && ! is_admin() ) { $cloudinary_id = $this->cloudinary_id( $attachment_id ); if ( false !== $cloudinary_id ) { $url = $this->cloudinary_url( $attachment_id, $cloudinary_id ); @@ -542,16 +542,16 @@ public function apply_default_transformations( array $transformations, $type = ' /** * Generate a Cloudinary URL based on attachment ID and required size. * - * @param int $attachment_id The id of the attachment. - * @param array|string $size The wp size to set for the URL. - * @param array $transformations Set of transformations to apply to this url. - * @param string $cloudinary_id Optional forced cloudinary ID. - * @param bool $breakpoint Flag url is a breakpoint URL to stop re-applying default transformations. - * @param bool $clean Flag to present a clean url (With out a WP size variable. + * @param int $attachment_id The id of the attachment. + * @param array|string $size The wp size to set for the URL. + * @param array $transformations Set of transformations to apply to this url. + * @param string $cloudinary_id Optional forced cloudinary ID. + * @param bool $overwrite_transformations Flag url is a breakpoint URL to stop re-applying default transformations. + * @param bool $clean Flag to present a clean url (With out a WP size variable. * * @return string The converted URL. */ - public function cloudinary_url( $attachment_id, $size = array(), $transformations = array(), $cloudinary_id = null, $breakpoint = false, $clean = false ) { + public function cloudinary_url( $attachment_id, $size = array(), $transformations = array(), $cloudinary_id = null, $overwrite_transformations = false, $clean = false ) { if ( empty( $cloudinary_id ) ) { $cloudinary_id = $this->cloudinary_id( $attachment_id ); @@ -574,7 +574,9 @@ public function cloudinary_url( $attachment_id, $size = array(), $transformation // Check size and correct if string or size. if ( is_string( $size ) || ( is_array( $size ) && 3 === count( $size ) ) ) { $intermediate = image_get_intermediate_size( $attachment_id, $size ); - $size = $this->get_crop( $intermediate['url'], $attachment_id ); + if ( is_array( $intermediate ) ) { + $size = $this->get_crop( $intermediate['url'], $attachment_id ); + } } /** @@ -587,7 +589,7 @@ public function cloudinary_url( $attachment_id, $size = array(), $transformation */ $pre_args['transformation'] = apply_filters( 'cloudinary_transformations', $transformations, $attachment_id ); // Defaults are only to be added on front, main images ( not breakpoints, since these are adapted down), and videos. - if ( ( ! defined( 'REST_REQUEST' ) || false === REST_REQUEST ) && ! is_admin() && false === $breakpoint ) { + if ( ( ! defined( 'REST_REQUEST' ) || false === REST_REQUEST ) && ! is_admin() && false === $overwrite_transformations ) { $pre_args['transformation'] = $this->apply_default_transformations( $pre_args['transformation'], $resource_type ); } @@ -732,17 +734,21 @@ public function filter_downsize( $image, $attachment_id, $size ) { /** * Convert an attachment URL to a Cloudinary one. * - * @param string $url Url to convert. - * @param int $attachment_id Attachment ID. - * @param array $transformations Optional transformations. + * @param string $url Url to convert. + * @param int $attachment_id Attachment ID. + * @param array $transformations Optional transformations. + * @param bool $overwrite_transformations Flag url as having an overwrite transformation. * * @return string Converted URL. */ - public function convert_url( $url, $attachment_id, $transformations = array() ) { + public function convert_url( $url, $attachment_id, $transformations = array(), $overwrite_transformations = true ) { + if ( $this->is_cloudinary_url( $url ) ) { + return $url; // Already is a cloudinary URL, just return. + } $size = $this->get_crop( $url, $attachment_id ); - return $this->cloudinary_url( $attachment_id, $size, $transformations, null, true ); + return $this->cloudinary_url( $attachment_id, $size, $transformations, null, $overwrite_transformations, true ); } /** @@ -820,7 +826,7 @@ function ( $item ) use ( $crop ) { // Use current sources, but convert the URLS. foreach ( $sources as &$source ) { if ( ! $this->is_cloudinary_url( $source['url'] ) ) { - $source['url'] = $this->convert_url( $source['url'], $attachment_id, $transformations ); + $source['url'] = $this->convert_url( $source['url'], $attachment_id, $transformations, true ); // Overwrite transformations applied, since the $transformations includes globals from the primary URL. } } @@ -1006,7 +1012,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. @@ -1072,19 +1078,24 @@ public function media_column_value( $column_name, $attachment_id ) { if ( 'cld_status' === $column_name ) { if ( $this->is_media( $attachment_id ) ) { $status = array( - 'state' => 'success', - 'note' => esc_html__( 'Synced', 'cloudinary' ), + 'state' => 'inactive', + 'note' => esc_html__( 'Not Synced', 'cloudinary' ), ); if ( false === $this->cloudinary_id( $attachment_id ) ) { // If false, lets check why by seeing if the file size is too large. $file = get_attached_file( $attachment_id ); // Get the file size to make sure it can exist in cloudinary. - $max_size = ( wp_attachment_is_image( $attachment_id ) ? 'max_image_size' : 'max_video_size' ); - if ( file_exists( $file ) && filesize( $file ) > $this->plugin->components['connect']->usage[ $max_size ] ) { - $max_size_hr = size_format( $this->plugin->components['connect']->usage[ $max_size ] ); + $max_size = ( wp_attachment_is_image( $attachment_id ) ? 'image_max_size_bytes' : 'video_max_size_bytes' ); + if ( file_exists( $file ) && filesize( $file ) > $this->plugin->components['connect']->usage['media_limits'][ $max_size ] ) { + $max_size_hr = size_format( $this->plugin->components['connect']->usage['media_limits'][ $max_size ] ); // translators: variable is file size. $status['note'] = sprintf( __( 'File size exceeds the maximum of %s. This media asset will be served from WordPress.', 'cloudinary' ), $max_size_hr ); $status['state'] = 'error'; } + } else { + $status = array( + 'state' => 'success', + 'note' => esc_html__( 'Synced', 'cloudinary' ), + ); } // filter status. $status = apply_filters( 'cloudinary_media_status', $status, $attachment_id ); @@ -1252,9 +1263,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 ); diff --git a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/php/connect/class-api.php b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/php/connect/class-api.php index bad5c3d94..75c0bbb27 100644 --- a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/php/connect/class-api.php +++ b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/php/connect/class-api.php @@ -186,6 +186,9 @@ public static function generate_transformation_string( array $options, $type = ' $transformations = array_map( function ( $item ) use ( $transformation_index ) { $transform = array(); + if ( is_string ( $item ) ) { + return $item; + } foreach ( $item as $type => $value ) { // phpcs:ignore $key = array_search( $type, $transformation_index, true ); if ( 'wpsize' === $type ) { @@ -241,7 +244,7 @@ public function cloudinary_url( $public_id, $args = array(), $size = array(), $c $url_parts[] = self::generate_transformation_string( $args['transformation'] ); } // Add size. - if ( ! empty( $size ) ) { + if ( ! empty( $size ) && is_array( $size ) ) { if ( true === $clean ) { $size['clean'] = true; } diff --git a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/php/media/class-filter.php b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/php/media/class-filter.php index 5c2b0890a..553b4117a 100644 --- a/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/php/media/class-filter.php +++ b/cloudinary-image-management-and-manipulation-in-the-cloud-cdn/php/media/class-filter.php @@ -671,6 +671,45 @@ public function filter_image_block_pre_render( $block, $source_block ) { return $block; } + /** + * Attempt to set the width and height for SVGs. + * + * @param array|false $image The image details. + * @param int $attachment_id The attachment ID. + * @param string|int[] $size The requested image size. + * + * @return array|false + */ + public function filter_svg_image_size( $image, $attachment_id, $size ) { + if ( is_array( $image ) && preg_match('/\.svg$/i', $image[0] ) && $image[1] <= 1 ) { + $image[1] = $image[2] = null; + + if ( is_array( $size ) ) { + $image[1] = $size[0]; + $image[2] = $size[1]; + } elseif ( false !== ( $xml = simplexml_load_file( $image[0] ) ) ) { + $attr = $xml->attributes(); + $viewbox = explode( ' ', $attr->viewBox ); + + // Get width + if ( isset( $attr->width ) && preg_match( '/\d+/', $attr->width, $value ) ) { + $image[1] = (int) $value[0]; + } elseif ( 4 === count( $viewbox ) ) { + $image[1] = (int) $viewbox[2]; + } + + // Get height + if ( isset( $attr->height ) && preg_match( '/\d+/', $attr->height, $value ) ) { + $image[2] = (int) $value[0]; + } elseif ( 4 === count( $viewbox ) ) { + $image[2] = (int) $viewbox[3]; + } + } + } + + return $image; + } + /** * Setup hooks for the filters. */ @@ -709,5 +748,7 @@ function ( $type ) use ( $filter ) { // Filter for block rendering. add_filter( 'render_block_data', array( $this, 'filter_image_block_pre_render' ), 10, 2 ); + // Try to get SVGs size. + add_filter( 'wp_get_attachment_image_src', array( $this, 'filter_svg_image_size' ), 10, 3 ); } } 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..f971948dd 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', $this->media->plugin->dir_url . 'css/video.css', null, self::PLAYER_VER ); wp_enqueue_script( 'cld-player' ); // Init cld script object. @@ -240,7 +241,7 @@ public function filter_video_shortcode( $html, $attr ) { $instance = $this->queue_video_config( $attr['id'], $attr[ $video['fileformat'] ], $video['fileformat'], $args ); // Replace with video tag. - return ''; + return ''; } /** @@ -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->filter->get_media_tags( $content ); + foreach ( $video_tags as $tag ) { + if ( false !== strpos( $tag, 'class="' ) ) { + $content = str_replace( 'class="', 'class="' . $classes . ' ', $content ); + } else { + $content = str_replace( '